├── .clang-format ├── .clang-tidy ├── .clangd.in ├── .cmake-format.yaml ├── .commitlintrc.json ├── .devcontainer ├── .zshrc ├── Dockerfile └── devcontainer.json ├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── cmake-build.yml │ └── gh-pages.yml ├── .gitignore ├── .gitmodules ├── .husky └── commit-msg ├── .versionrc.json ├── .vscode ├── extensions.json └── settings.json ├── AUTHORS ├── CHANGELOG.md ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── SECURITY.md ├── cmake ├── AsapInstall.cmake ├── AsapTargets.cmake ├── BuildHelpers.cmake ├── CPM.cmake ├── ClangTidy.cmake ├── CodeCoverage.cmake ├── CompileDefinitions.cmake ├── CompileOptions.cmake ├── ComponentInstall.cmake ├── DoxGeneration.cmake ├── FasterBuild.cmake ├── FindSphinx.cmake ├── FindValgrind.cmake ├── Format.cmake ├── GetGitRevisionDescription.cmake ├── GetGitRevisionDescription.cmake.in ├── GoogleSanitizers.cmake ├── LanguageStandards.cmake ├── ListTargets.cmake ├── LogHelpers.cmake ├── ResetInitialCompilerOptions.cmake ├── SphinxGeneration.cmake ├── TestTargets.cmake ├── Valgrind.cmake └── scripts │ └── standard-version-updater.js ├── codec ├── .gitignore ├── CMakeLists.txt ├── README.md ├── config.cmake.in ├── config.pc.in ├── doc │ ├── _static │ │ ├── favicon.ico │ │ └── logo.png │ ├── api.rst │ ├── api │ │ └── codec.rst │ ├── conf.py.in │ ├── index.rst │ ├── license.rst │ └── version.rst ├── include │ └── codec │ │ └── base16.h ├── src │ └── base16.cpp └── test │ ├── CMakeLists.txt │ ├── base16_test.cpp │ └── main.cpp ├── crypto ├── .gitignore ├── CMakeLists.txt ├── README.md ├── config.cmake.in ├── config.pc.in ├── doc │ ├── _static │ │ ├── favicon.ico │ │ └── logo.png │ ├── api.rst │ ├── api │ │ └── codec.rst │ ├── conf.py.in │ ├── index.rst │ ├── license.rst │ └── version.rst ├── include │ └── crypto │ │ ├── config.h.in │ │ ├── hash.h │ │ ├── keypair.h │ │ └── random.h ├── src │ ├── hash.cpp │ ├── keypair.cpp │ └── random.cpp └── test │ ├── CMakeLists.txt │ ├── hash_test.cpp │ ├── keypair_test.cpp │ └── main.cpp ├── data └── REPLACE_WITH_REAL_DATA ├── doc ├── _static │ ├── favicon.ico │ └── logo.png ├── changelog.md ├── conf.py.in ├── index.html ├── index.rst ├── license.rst ├── tools │ └── index.rst └── version.rst ├── doxygen ├── Doxyfile.in ├── footer.html └── header.html ├── nat ├── .gitignore ├── CMakeLists.txt ├── README.md ├── config.cmake.in ├── config.pc.in ├── doc │ ├── _static │ │ ├── favicon.ico │ │ └── logo.png │ ├── api.rst │ ├── api │ │ └── nat.rst │ ├── conf.py.in │ ├── index.rst │ ├── license.rst │ └── version.rst ├── include │ └── nat │ │ ├── error.h │ │ ├── nat.h │ │ ├── port_mapper.h │ │ └── upnp_port_mapper.h ├── src │ ├── error.cpp │ ├── nat.cpp │ └── upnp_port_mapper.cpp └── test │ ├── CMakeLists.txt │ ├── main.cpp │ └── portfwd_test.cpp ├── p2p ├── .gitignore ├── CMakeLists.txt ├── README.md ├── config.cmake.in ├── config.pc.in ├── doc │ ├── _static │ │ ├── favicon.ico │ │ └── logo.png │ ├── api.rst │ ├── api │ │ └── p2p.rst │ ├── conf.py.in │ ├── index.rst │ ├── license.rst │ └── version.rst ├── examples │ ├── CMakeLists.txt │ ├── simple-node │ │ ├── CMakeLists.txt │ │ └── main.cpp │ └── utils │ │ ├── console_runner.cpp │ │ ├── console_runner.h │ │ └── runner_base.h ├── include │ └── p2p │ │ └── kademlia │ │ ├── boost_asio.h │ │ ├── buffer.h │ │ ├── channel.h │ │ ├── detail │ │ ├── bootstrap_procedure.h │ │ ├── error_impl.h │ │ ├── find_node_task.h │ │ ├── find_value_task.h │ │ ├── lookup_task.h │ │ ├── ping_node_task.h │ │ └── store_value_task.h │ │ ├── endpoint.h │ │ ├── engine.h │ │ ├── error.h │ │ ├── kbucket.h │ │ ├── key.h │ │ ├── message.h │ │ ├── message_serializer.h │ │ ├── network.h │ │ ├── node.h │ │ ├── parameters.h │ │ ├── response_dispatcher.h │ │ ├── routing.h │ │ ├── session.h │ │ ├── timer.h │ │ └── value_store.h ├── src │ └── kademlia │ │ ├── error.cpp │ │ ├── error_impl.cpp │ │ ├── kbucket.cpp │ │ ├── message.cpp │ │ ├── message_serializer.cpp │ │ ├── node.cpp │ │ ├── routing.cpp │ │ └── timer.cpp └── test │ ├── CMakeLists.txt │ ├── channel_test.cpp │ ├── kbucket_test.cpp │ ├── main.cpp │ ├── network_test.cpp │ ├── node_test.cpp │ ├── response_dispatcher_test.cpp │ ├── routingtable_test.cpp │ └── timer_test.cpp ├── requirements.txt ├── templates └── version.h.in ├── third_party └── CMakeLists.txt └── tools └── version-info ├── .gitignore ├── CMakeLists.txt ├── README.md └── src └── main.cpp.in /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | Language: Cpp 4 | BasedOnStyle: LLVM 5 | AccessModifierOffset: -2 6 | AlignAfterOpenBracket: DontAlign 7 | AlignConsecutiveMacros: false 8 | AlignConsecutiveAssignments: false 9 | AlignConsecutiveDeclarations: false 10 | AlignEscapedNewlines: Right 11 | AlignOperands: true 12 | AlignTrailingComments: true 13 | AllowAllArgumentsOnNextLine: true 14 | AllowAllConstructorInitializersOnNextLine: true 15 | AllowAllParametersOfDeclarationOnNextLine: true 16 | AllowShortBlocksOnASingleLine: Never 17 | AllowShortCaseLabelsOnASingleLine: false 18 | AllowShortFunctionsOnASingleLine: false 19 | AllowShortLambdasOnASingleLine: All 20 | AllowShortIfStatementsOnASingleLine: Never 21 | AllowShortLoopsOnASingleLine: false 22 | AlwaysBreakAfterDefinitionReturnType: None 23 | AlwaysBreakAfterReturnType: None 24 | AlwaysBreakBeforeMultilineStrings: false 25 | AlwaysBreakTemplateDeclarations: MultiLine 26 | BinPackArguments: true 27 | BinPackParameters: true 28 | BraceWrapping: 29 | AfterCaseLabel: false 30 | AfterClass: false 31 | AfterControlStatement: false 32 | AfterEnum: false 33 | AfterFunction: false 34 | AfterNamespace: false 35 | AfterObjCDeclaration: false 36 | AfterStruct: false 37 | AfterUnion: false 38 | AfterExternBlock: false 39 | BeforeCatch: false 40 | BeforeElse: false 41 | IndentBraces: false 42 | SplitEmptyFunction: true 43 | SplitEmptyRecord: true 44 | SplitEmptyNamespace: true 45 | BreakBeforeBinaryOperators: None 46 | BreakBeforeBraces: Attach 47 | BreakBeforeInheritanceComma: false 48 | BreakInheritanceList: BeforeColon 49 | BreakBeforeTernaryOperators: true 50 | BreakConstructorInitializersBeforeComma: false 51 | BreakConstructorInitializers: BeforeColon 52 | BreakAfterJavaFieldAnnotations: false 53 | BreakStringLiterals: true 54 | ColumnLimit: 80 55 | CommentPragmas: "^ IWYU pragma:" 56 | CompactNamespaces: false 57 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 58 | ConstructorInitializerIndentWidth: 4 59 | ContinuationIndentWidth: 4 60 | Cpp11BracedListStyle: true 61 | DeriveLineEnding: true 62 | DerivePointerAlignment: false 63 | DisableFormat: false 64 | ExperimentalAutoDetectBinPacking: false 65 | FixNamespaceComments: true 66 | ForEachMacros: 67 | - foreach 68 | - Q_FOREACH 69 | - BOOST_FOREACH 70 | IncludeBlocks: Preserve 71 | IncludeCategories: 72 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 73 | Priority: 2 74 | SortPriority: 0 75 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 76 | Priority: 3 77 | SortPriority: 0 78 | - Regex: ".*" 79 | Priority: 1 80 | SortPriority: 0 81 | IncludeIsMainRegex: "(Test)?$" 82 | IncludeIsMainSourceRegex: "" 83 | IndentCaseLabels: false 84 | IndentGotoLabels: true 85 | IndentPPDirectives: None 86 | IndentWidth: 2 87 | IndentWrappedFunctionNames: false 88 | JavaScriptQuotes: Leave 89 | JavaScriptWrapImports: true 90 | KeepEmptyLinesAtTheStartOfBlocks: true 91 | MacroBlockBegin: "" 92 | MacroBlockEnd: "" 93 | MaxEmptyLinesToKeep: 1 94 | NamespaceIndentation: None 95 | ObjCBinPackProtocolList: Auto 96 | ObjCBlockIndentWidth: 2 97 | ObjCSpaceAfterProperty: false 98 | ObjCSpaceBeforeProtocolList: true 99 | PenaltyBreakAssignment: 2 100 | PenaltyBreakBeforeFirstCallParameter: 19 101 | PenaltyBreakComment: 300 102 | PenaltyBreakFirstLessLess: 120 103 | PenaltyBreakString: 1000 104 | PenaltyBreakTemplateDeclaration: 10 105 | PenaltyExcessCharacter: 1000000 106 | PenaltyReturnTypeOnItsOwnLine: 60 107 | PointerAlignment: Right 108 | ReflowComments: true 109 | SortIncludes: true 110 | SortUsingDeclarations: true 111 | SpaceAfterCStyleCast: false 112 | SpaceAfterLogicalNot: false 113 | SpaceAfterTemplateKeyword: true 114 | SpaceBeforeAssignmentOperators: true 115 | SpaceBeforeCpp11BracedList: false 116 | SpaceBeforeCtorInitializerColon: true 117 | SpaceBeforeInheritanceColon: true 118 | SpaceBeforeParens: ControlStatements 119 | SpaceBeforeRangeBasedForLoopColon: true 120 | SpaceInEmptyBlock: false 121 | SpaceInEmptyParentheses: false 122 | SpacesBeforeTrailingComments: 1 123 | SpacesInAngles: false 124 | SpacesInConditionalStatement: false 125 | SpacesInContainerLiterals: true 126 | SpacesInCStyleCastParentheses: false 127 | SpacesInParentheses: false 128 | SpacesInSquareBrackets: false 129 | SpaceBeforeSquareBrackets: false 130 | Standard: Latest 131 | StatementMacros: 132 | - Q_UNUSED 133 | - QT_REQUIRE_VERSION 134 | TabWidth: 8 135 | UseCRLF: false 136 | UseTab: Never 137 | --- 138 | Language: JavaScript 139 | BasedOnStyle: Google 140 | ColumnLimit: 80 141 | --- 142 | Language: Json 143 | ColumnLimit: 80 144 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | UseColor: true 2 | 3 | Checks: > 4 | bugprone-*, 5 | clang-analyzer-*, 6 | cppcoreguidelines-*, 7 | google-*, 8 | hicpp-*, 9 | modernize-*, 10 | performance-*, 11 | portability-*, 12 | readability-*, 13 | -cppcoreguidelines-macro-usage, 14 | -google-runtime-references 15 | -hicpp-exception-baseclass, 16 | -hicpp-signed-bitwise, 17 | -readability-function-cognitive-complexity, 18 | -used-but-marked-unused, 19 | HeaderFilterRegex: ".*/[common|logging]/.*" 20 | -------------------------------------------------------------------------------- /.clangd.in: -------------------------------------------------------------------------------- 1 | # We need to configure the location of the compilation database in this file 2 | # and not in vscode `.settings` until we have a way to get the cmake build 3 | # directory or preset name as a subsititution variable. 4 | # 5 | # See https://github.com/clangd/vscode-clangd/issues/48 6 | 7 | CompileFlags: 8 | CompilationDatabase: "@CMAKE_BINARY_DIR@" 9 | -------------------------------------------------------------------------------- /.cmake-format.yaml: -------------------------------------------------------------------------------- 1 | parse: {} 2 | format: 3 | line_width: 80 4 | tab_size: 2 5 | use_tabchars: false 6 | fractional_tab_policy: use-space 7 | max_subgroups_hwrap: 2 8 | max_pargs_hwrap: 6 9 | max_rows_cmdline: 2 10 | separate_ctrl_name_with_space: false 11 | separate_fn_name_with_space: false 12 | dangle_parens: false 13 | dangle_align: prefix 14 | min_prefix_chars: 4 15 | max_prefix_chars: 10 16 | max_lines_hwrap: 2 17 | line_ending: unix 18 | command_case: canonical 19 | keyword_case: unchanged 20 | always_wrap: [] 21 | enable_sort: true 22 | autosort: false 23 | require_valid_layout: false 24 | layout_passes: {} 25 | markup: 26 | bullet_char: "*" 27 | enum_char: . 28 | first_comment_is_literal: false 29 | literal_comment_pattern: null 30 | fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$ 31 | ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$ 32 | explicit_trailing_pattern: "#<" 33 | hashruler_min_length: 10 34 | canonicalize_hashrulers: true 35 | enable_markup: true 36 | lint: 37 | disabled_codes: 38 | - C0103 # Invalid argument name 39 | - C0113 # Missing COMMENT in statement which allows it 40 | - C0111 # Missing docstring on function or macro declaration 41 | function_pattern: "[0-9a-z_]+" 42 | macro_pattern: "[0-9A-Z_]+" 43 | global_var_pattern: "[A-Z][0-9A-Z_]+" 44 | internal_var_pattern: _[A-Z][0-9A-Z_]+ 45 | local_var_pattern: "[a-z][a-z0-9_]+" 46 | private_var_pattern: _[0-9a-z_]+ 47 | public_var_pattern: "[A-Z][0-9A-Z_]+" 48 | argument_var_pattern: "[a-z][a-z0-9_]+" 49 | keyword_pattern: "[A-Z][0-9A-Z_]+" 50 | max_conditionals_custom_parser: 2 51 | min_statement_spacing: 1 52 | max_statement_spacing: 2 53 | max_returns: 6 54 | max_branches: 30 # Default target: 12 55 | max_arguments: 6 # Default target: 5 56 | max_localvars: 15 57 | max_statements: 110 # Default target: 50 58 | encode: 59 | emit_byteorder_mark: false 60 | input_encoding: utf-8 61 | output_encoding: utf-8 62 | misc: 63 | per_command: {} 64 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@commitlint/config-conventional" 4 | ] 5 | } -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VARIANT=debian-11 2 | # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.205.2/containers/python-3/.devcontainer/base.Dockerfile 3 | FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT} 4 | 5 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 6 | && apt-get -y install lsb-release wget software-properties-common 7 | 8 | RUN export DEBIAN_FRONTEND=noninteractive \ 9 | && apt-get -y install build-essential ninja-build valgrind gdb lcov doxygen graphviz 10 | 11 | # Install latest cmake 3.22 so we have support for cmake presets and a better integration in IDEs 12 | RUN wget https://github.com/Kitware/CMake/releases/download/v3.22.0/cmake-3.22.0-linux-x86_64.sh \ 13 | -q -O /tmp/cmake-install.sh \ 14 | && chmod u+x /tmp/cmake-install.sh \ 15 | && /tmp/cmake-install.sh --skip-license --prefix=/usr \ 16 | && rm /tmp/cmake-install.sh 17 | 18 | # Install clang-14 19 | RUN wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - 20 | RUN add-apt-repository 'deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-14 main' 21 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 22 | && apt-get -y install clang-14 clangd-14 lldb-14 llvm-14 clang-format-14 clang-tidy-14 23 | 24 | RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 100 25 | RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-14 100 26 | RUN update-alternatives --install /usr/bin/clang-apply-replacements clang-apply-replacements /usr/bin/clang-apply-replacements-14 100 27 | RUN update-alternatives --install /usr/bin/clang-check clang-check /usr/bin/clang-check-14 100 28 | RUN update-alternatives --install /usr/bin/clang-query clang-query /usr/bin/clang-query-14 100 29 | RUN update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-14 100 30 | RUN update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-14 100 31 | RUN update-alternatives --install /usr/bin/scan-build scan-build /usr/bin/scan-build-14 100 32 | RUN update-alternatives --install /usr/bin/scan-view scan-view /usr/bin/scan-view-14 100 33 | RUN update-alternatives --install /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-14 100 34 | RUN update-alternatives --install /usr/bin/llvm-profdata llvm-profdata /usr/bin/llvm-profdata-14 100 35 | 36 | # Install ccache 37 | RUN apt-get -y install ccache 38 | 39 | # Clean-up 40 | RUN apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* 41 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.205.2/containers/python-3 3 | { 4 | "name": "asap_dev", 5 | "build": { 6 | "dockerfile": "Dockerfile", 7 | "context": "..", 8 | "args": { 9 | // Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6 10 | // Append -bullseye or -buster to pin to an OS version. 11 | // Use -bullseye variants on local on arm64/Apple Silicon. 12 | "VARIANT": "debian-11" 13 | } 14 | }, 15 | "features": { 16 | "ghcr.io/devcontainers/features/common-utils:1": { 17 | "configureZshAsDefaultShell": true, 18 | "userName": "vscode", 19 | "uid": "1000", 20 | "gid": "1000" 21 | }, 22 | "ghcr.io/devcontainers/features/node:1": { 23 | "version": "16" 24 | }, 25 | "ghcr.io/devcontainers/features/python:1": { 26 | "version": "os-provided" 27 | } 28 | }, 29 | // Set *default* container specific settings.json values on container create. 30 | "settings": { 31 | "python.defaultInterpreterPath": "/usr/local/bin/python", 32 | "python.linting.enabled": true, 33 | "python.linting.pylintEnabled": true, 34 | "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", 35 | "python.formatting.blackPath": "/usr/local/py-utils/bin/black", 36 | "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", 37 | "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", 38 | "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", 39 | "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", 40 | "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", 41 | "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", 42 | "python.linting.pylintPath": "/usr/local/py-utils/bin/pylint", 43 | "clangd.path": "/usr/bin/clangd-14" 44 | }, 45 | // Add the IDs of extensions you want installed when the container is created. 46 | "extensions": [ 47 | "ms-python.python", 48 | "ms-python.vscode-pylance", 49 | "ms-vscode.cpptools", 50 | "matepek.vscode-catch2-test-adapter", 51 | "llvm-vs-code-extensions.vscode-clangd", 52 | "twxs.cmake", 53 | "ms-vscode.cmake-tools", 54 | "swyddfa.esbonio", 55 | "eamodio.gitlens", 56 | "hbenl.vscode-test-explorer", 57 | "guyutongxue.cpp-reference", 58 | "cheshirekow.cmake-format", 59 | "kevinkyang.auto-comment-blocks", 60 | "editorconfig.editorconfig" 61 | ], 62 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 63 | // "forwardPorts": [], 64 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 65 | "remoteUser": "vscode", 66 | "postCreateCommand": { 67 | "git_dubious_fix": "git config --global --add safe.directory ${containerWorkspaceFolder}", 68 | "commit_tools": "npm install -g husky standard-version @commitlint/cli @commitlint/config-conventional", 69 | "enable_husky": "npx husky install < /dev/null", 70 | "update_python_modules": "pip --disable-pip-version-check --no-cache-dir install -r requirements.txt" 71 | } 72 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 2 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | guidelines = 80, 100 8 | end_of_line = lf 9 | 10 | [*.{css,html,html.in,yml,rb}] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto eol=lf 3 | 4 | # Force batch scripts to always use CRLF line endings so that if a repo is accessed 5 | # in Windows via a file share from Linux, the scripts will work. 6 | *.{cmd,[cC][mM][dD]} text eol=crlf 7 | *.{bat,[bB][aA][tT]} text eol=crlf 8 | 9 | # Force bash scripts to always use LF line endings so that if a repo is accessed 10 | # in Unix via a file share from Windows, the scripts will work. 11 | *.sh text eol=lf 12 | .husky/commit-msg eol=lf 13 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: github pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | with: 14 | submodules: recursive 15 | 16 | - name: Install doxygen 17 | run: sudo apt-get install -y doxygen 18 | 19 | - name: Install Graphviz 20 | run: sudo apt-get install -y graphviz 21 | 22 | - name: Setup Python 23 | uses: actions/setup-python@v2 24 | with: 25 | python-version: "3.9" 26 | 27 | - name: Upgrade pip 28 | run: | 29 | # install pip=>20.1 to use "pip cache dir" 30 | python3 -m pip install --upgrade pip 31 | 32 | - name: Get pip cache dir 33 | id: pip-cache 34 | run: echo "::set-output name=dir::$(pip cache dir)" 35 | 36 | - name: Cache dependencies 37 | uses: actions/cache@v2 38 | with: 39 | path: ${{ steps.pip-cache.outputs.dir }} 40 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 41 | restore-keys: | 42 | ${{ runner.os }}-pip- 43 | 44 | - name: Install dependencies 45 | run: python3 -m pip install -r ./requirements.txt 46 | 47 | - name: Configure CMake 48 | run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 49 | 50 | - name: Build doxygen documentation 51 | run: cmake --build build --target dox 52 | 53 | - name: Build sphinx documentation 54 | run: cmake --build build --target sphinx 55 | 56 | - name: Deploy 57 | uses: peaceiris/actions-gh-pages@v3 58 | with: 59 | github_token: ${{ secrets.GITHUB_TOKEN }} 60 | publish_dir: build/sphinx 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directories 2 | build/ 3 | build-*/ 4 | *-build/ 5 | _build/ 6 | _build-*/ 7 | cmake-build*/ 8 | out/ 9 | 10 | .vs 11 | .sphinx 12 | .cache 13 | .idea 14 | 15 | # In this specific project we ignore .clangd as it is dynamycally generated by cmake during the 16 | # configuration stage. 17 | .clangd 18 | 19 | # Generated files inside source tree 20 | doc/conf.py 21 | 22 | # clang-tidy fixes 23 | fixes*.yaml 24 | 25 | ### Linux template 26 | *~ 27 | 28 | # temporary files which can be created if a process still has a handle open of a deleted file 29 | .fuse_hidden* 30 | 31 | # KDE directory preferences 32 | .directory 33 | 34 | # Linux trash folder which might appear on any partition or disk 35 | .Trash-* 36 | 37 | # .nfs files are created when an open file is removed but is still being accessed 38 | .nfs* 39 | 40 | ### macOS template 41 | # General 42 | .DS_Store 43 | .AppleDouble 44 | .LSOverride 45 | 46 | # Icon must end with two \r 47 | Icon 48 | 49 | # Thumbnails 50 | ._* 51 | 52 | # Files that might appear in the root of a volume 53 | .DocumentRevisions-V100 54 | .fseventsd 55 | .Spotlight-V100 56 | .TemporaryItems 57 | .Trashes 58 | .VolumeIcon.icns 59 | .com.apple.timemachine.donotpresent 60 | 61 | # Directories potentially created on remote AFP share 62 | .AppleDB 63 | .AppleDesktop 64 | Network Trash Folder 65 | Temporary Items 66 | .apdisk 67 | ### Dropbox template 68 | # Dropbox settings and caches 69 | .dropbox 70 | .dropbox.attr 71 | .dropbox.cache 72 | ### Ninja template 73 | .ninja_deps 74 | .ninja_log 75 | ### Tags template 76 | # Ignore tags created by etags, ctags, gtags (GNU global) and cscope 77 | TAGS 78 | .TAGS 79 | !TAGS/ 80 | tags 81 | .tags 82 | !tags/ 83 | gtags.files 84 | GTAGS 85 | GRTAGS 86 | GPATH 87 | GSYMS 88 | cscope.files 89 | cscope.out 90 | cscope.in.out 91 | cscope.po.out 92 | 93 | ### Vim template 94 | # Swap 95 | [._]*.s[a-v][a-z] 96 | [._]*.sw[a-p] 97 | [._]s[a-rt-v][a-z] 98 | [._]ss[a-gi-z] 99 | [._]sw[a-p] 100 | 101 | # Session 102 | Session.vim 103 | 104 | # Temporary 105 | .netrwhist 106 | # Persistent undo 107 | [._]*.un~ 108 | ### C++ template 109 | # Prerequisites 110 | *.d 111 | 112 | # Compiled Object files 113 | *.slo 114 | *.lo 115 | *.o 116 | *.obj 117 | 118 | # Precompiled Headers 119 | *.gch 120 | *.pch 121 | 122 | # Compiled Dynamic libraries 123 | *.so 124 | *.dylib 125 | *.dll 126 | 127 | # Fortran module files 128 | *.mod 129 | *.smod 130 | 131 | # Compiled Static libraries 132 | *.lai 133 | *.la 134 | *.a 135 | *.lib 136 | 137 | # Executables 138 | *.exe 139 | *.out 140 | *.app 141 | ### VisualStudioCode template 142 | .vscode/* 143 | !.vscode/settings.json 144 | !.vscode/tasks.json 145 | !.vscode/launch.json 146 | !.vscode/extensions.json 147 | 148 | ### Xcode template 149 | # Xcode 150 | # 151 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 152 | 153 | ## User settings 154 | xcuserdata/ 155 | 156 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 157 | *.xcscmblueprint 158 | *.xccheckout 159 | 160 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 161 | build/ 162 | DerivedData/ 163 | *.moved-aside 164 | *.pbxuser 165 | !default.pbxuser 166 | *.mode1v3 167 | !default.mode1v3 168 | *.mode2v3 169 | !default.mode2v3 170 | *.perspectivev3 171 | !default.perspectivev3 172 | 173 | ### Backup template 174 | *.bak 175 | *.gho 176 | *.ori 177 | *.orig 178 | *.tmp 179 | ### Vagrant template 180 | # General 181 | .vagrant/ 182 | 183 | # Log files (if you are creating logs in debug mode, uncomment this) 184 | *.log 185 | ### C template 186 | 187 | # Object files 188 | *.ko 189 | *.elf 190 | 191 | # Linker output 192 | *.ilk 193 | *.map 194 | *.exp 195 | 196 | # Executables 197 | *.i*86 198 | *.x86_64 199 | *.hex 200 | 201 | # Debug files 202 | *.dSYM/ 203 | *.su 204 | *.idb 205 | *.pdb 206 | 207 | # Kernel Module Compile Results 208 | *.mod* 209 | *.cmd 210 | .tmp_versions/ 211 | modules.order 212 | Module.symvers 213 | Mkfile.old 214 | dkms.conf 215 | 216 | ### Windows template 217 | # Windows thumbnail cache files 218 | Thumbs.db 219 | ehthumbs.db 220 | ehthumbs_vista.db 221 | 222 | # Dump file 223 | *.stackdump 224 | 225 | # Folder config file 226 | [Dd]esktop.ini 227 | 228 | # Recycle Bin used on file shares 229 | $RECYCLE.BIN/ 230 | 231 | # Windows Installer files 232 | *.cab 233 | *.msi 234 | *.msix 235 | *.msm 236 | *.msp 237 | 238 | # Windows shortcuts 239 | *.lnk 240 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cmake/common"] 2 | path = cmake/common 3 | url = https://github.com/swift-nav/cmake 4 | [submodule "doxygen/doxygen-awesome-css"] 5 | path = doxygen/doxygen-awesome-css 6 | url = https://github.com/jothepro/doxygen-awesome-css.git 7 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint -x $(npm root -g)/@commitlint/config-conventional --edit $1 5 | -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | { 4 | "type": "feat", 5 | "section": "Features" 6 | }, 7 | { 8 | "type": "fix", 9 | "section": "Bug Fixes" 10 | }, 11 | { 12 | "type": "chore", 13 | "hidden": true 14 | }, 15 | { 16 | "type": "docs", 17 | "section": "Documentation" 18 | }, 19 | { 20 | "type": "style", 21 | "hidden": true 22 | }, 23 | { 24 | "type": "refactor", 25 | "hidden": true 26 | }, 27 | { 28 | "type": "perf", 29 | "hidden": true 30 | }, 31 | { 32 | "type": "test", 33 | "hidden": true 34 | }, 35 | { 36 | "type": "build", 37 | "hidden": true 38 | }, 39 | { 40 | "type": "ops", 41 | "hidden": true 42 | } 43 | ], 44 | "bumpFiles": [ 45 | { 46 | "filename": "CMakeLists.txt", 47 | "updater": "cmake/scripts/standard-version-updater.js" 48 | } 49 | ], 50 | "commitUrlFormat": "http://github.com/abdes/asap/commit/{{hash}}", 51 | "compareUrlFormat": "http://github.com/abdes/asap/compare/{{previousTag}}...{{currentTag}}", 52 | "issueUrlFormat": "http://github.com/abdes/asap/issues/{{id}}", 53 | "userUrlFormat": "http://github.com/abdes" 54 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "cheshirekow.cmake-format", 4 | "cschlosser.doxdocgen", 5 | "donjayamanne.githistory", 6 | "eamodio.gitlens", 7 | "editorconfig.editorconfig", 8 | "guyutongxue.cpp-reference", 9 | "hbenl.vscode-test-explorer", 10 | "jeff-hykin.better-cpp-syntax", 11 | "kevinkyang.auto-comment-blocks", 12 | "llvm-vs-code-extensions.vscode-clangd", 13 | "matepek.vscode-catch2-test-adapter", 14 | "ms-python.python", 15 | "ms-vscode.cmake-tools", 16 | "ms-vscode.cpptools", 17 | "ms-vscode.test-adapter-converter", 18 | "stkb.rewrap", 19 | "streetsidesoftware.code-spell-checker", 20 | "swyddfa.esbonio", 21 | "vadimcn.vscode-lldb", 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Names should be added to this file with this pattern: 2 | # 3 | # For individuals: 4 | # Name 5 | # 6 | # For organizations: 7 | # Organization 8 | # 9 | # See python fnmatch module documentation for more information. 10 | 11 | Abdessattar Sassi <457645+abdes@users.noreply.github.com> 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, The Authors. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security (Top level page) 2 | 3 | ## Vulnerability reporting (security issues) 4 | 5 | We gratefully welcome vulnerability reports! 6 | 7 | If you find a significant vulnerability, or evidence of one, 8 | please send an email to the security contacts that you have such 9 | information, and we'll tell you the next steps. 10 | 11 | For now, the security contacts are listed in the AUTHORS file at the root of 12 | this project's repository. 13 | 14 | Please use an email system (like Gmail) that supports 15 | hop-to-hop encryption using STARTTLS when reporting vulnerabilities. 16 | Examples of such systems include Gmail, Outlook.com, and runbox.com. 17 | See [STARTTLS Everywhere](https://starttls-everywhere.org/) 18 | if you wish to learn more about efforts to encourage the use of STARTTLS. 19 | Your email client should use encryption to communicate with 20 | your email system (i.e., if you use a web-based email client then use HTTPS, 21 | and if you use email client software then configure it to use encryption). 22 | Hop-to-hop encryption isn't as strong as end-to-end encryption, 23 | but we've decided that it's strong enough for this purpose 24 | and it's much easier to get everyone to use it. 25 | 26 | We will gladly give credit to anyone who reports a vulnerability 27 | so that we can fix it. 28 | If you want to remain anonymous or pseudonymous instead, 29 | please let us know that; we will gladly respect your wishes. 30 | -------------------------------------------------------------------------------- /cmake/BuildHelpers.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # ------------------------------------------------------------------------------ 8 | # Build Helpers to simplify target creation. 9 | # ------------------------------------------------------------------------------ 10 | 11 | function(asap_generate_export_headers target include_dir) 12 | # Set API export file and macro 13 | string(MAKE_C_IDENTIFIER ${target} TEMPLATE_TARGET_ID) 14 | string(TOUPPER ${TEMPLATE_TARGET_ID} TEMPLATE_TARGET_ID) 15 | set(export_file "include/${include_dir}/${target}_export.h") 16 | set(template_export_file "include/${include_dir}/${target}_api.h") 17 | set(TEMPLATE_TARGET "${target}") 18 | set(TEMPLATE_INCLUDE_DIR "${include_dir}") 19 | 20 | # Create API export headers 21 | generate_export_header(${target} EXPORT_FILE_NAME ${export_file} 22 | EXPORT_MACRO_NAME ${TEMPLATE_TARGET_ID}_API) 23 | endfunction() 24 | -------------------------------------------------------------------------------- /cmake/CPM.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # Do this only once for the project by checking if we already have loaded CPM 8 | # which will define the CURRENT_CPM_VERSION, and if that version is what we want 9 | # to have here. 10 | if(NOT CURRENT_CPM_VERSION VERSION_EQUAL 0.38.1) 11 | set(CPM_DOWNLOAD_VERSION 0.38.1) 12 | 13 | if(CPM_SOURCE_CACHE) 14 | # Expand relative path. This is important if the provided path contains a 15 | # tilde (~) 16 | get_filename_component(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE} ABSOLUTE) 17 | set(CPM_DOWNLOAD_LOCATION 18 | "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 19 | elseif(DEFINED ENV{CPM_SOURCE_CACHE}) 20 | set(CPM_DOWNLOAD_LOCATION 21 | "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 22 | else() 23 | set(CPM_DOWNLOAD_LOCATION 24 | "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 25 | endif() 26 | 27 | if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 28 | message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 29 | file( 30 | DOWNLOAD 31 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 32 | ${CPM_DOWNLOAD_LOCATION}) 33 | endif() 34 | include(${CPM_DOWNLOAD_LOCATION}) 35 | endif() 36 | 37 | # This is a wrapper function around CPM `cpmaddpackage` to automatically 38 | # push/pop the package on the hierarchy stack for logging. Use it instead of 39 | # calling CPM. 40 | function(asap_add_package) 41 | set(options) 42 | set(oneValueArgs NAME) 43 | set(multiValueArgs) 44 | 45 | cmake_parse_arguments(x "${options}" "${oneValueArgs}" "${multiValueArgs}" 46 | ${ARGN}) 47 | 48 | if(NOT DEFINED x_NAME) 49 | message( 50 | FATAL_ERROR 51 | "Package name is required. Refer to CPM docs for the full usage.") 52 | return() 53 | endif() 54 | asap_push_module(${x_NAME}) 55 | cpmaddpackage(NAME ${x_NAME} ${ARGN}) 56 | asap_pop_module(${x_NAME}) 57 | 58 | endfunction() 59 | -------------------------------------------------------------------------------- /cmake/ClangTidy.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # 8 | # clang-tidy targets work only when clang-tidy executable can be found and the 9 | # compiler being used is clang (otherwise gcc/others options may cause errors 10 | # for clang-tidy) 11 | # 12 | find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-14) 13 | if(NOT "${CLANG_TIDY}" STREQUAL "CLANG_TIDY-NOTFOUND") 14 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 15 | include(common/ClangTidy) 16 | 17 | function(asap_create_clang_tidy_targets) 18 | swift_create_clang_tidy_targets(DONT_GENERATE_CLANG_TIDY_CONFIG ${ARGV}) 19 | endfunction() 20 | return() 21 | 22 | else() 23 | message( 24 | STATUS "Not using clang as a compiler, disabling clang-tidy targets") 25 | endif() 26 | else() 27 | message(STATUS "Could not find appropriate clang-tidy, targets disabled") 28 | endif() 29 | 30 | function(asap_create_clang_tidy_targets) 31 | # empty 32 | endfunction() 33 | -------------------------------------------------------------------------------- /cmake/CodeCoverage.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # 8 | # Code coverage only works with clang/gcc. 9 | # 10 | if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang|GNU") 11 | 12 | include(common/CodeCoverage) 13 | 14 | function(asap_add_code_coverage) 15 | add_code_coverage(${ARGV}) 16 | endfunction() 17 | 18 | function(asap_add_code_coverage_all_targets) 19 | # Add standard exclusion patterns for code coverage reports 20 | if("${CMAKE_C_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") 21 | # For clang we'll be using llvm-cov which expect regex as input for 22 | # exclusions 23 | set(STANDARD_EXCLUDES '.*/test/.*' '.*/\.cache/CPM/.*' '/usr/.*') 24 | else() 25 | # For GNU however, we'll be using lcov which expects file patterns as 26 | # input for excludions 27 | set(STANDARD_EXCLUDES */test/* */.cache/CPM/* /usr/*) 28 | endif() 29 | add_code_coverage_all_targets(EXCLUDE ${STANDARD_EXCLUDES} ${ARGV}) 30 | endfunction() 31 | 32 | else() 33 | function(target_code_coverage) 34 | # empty 35 | endfunction() 36 | 37 | function(asap_add_code_coverage) 38 | # empty 39 | endfunction() 40 | 41 | function(asap_add_code_coverage_all_targets) 42 | # empty 43 | endfunction() 44 | 45 | endif() 46 | -------------------------------------------------------------------------------- /cmake/CompileDefinitions.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | include_guard(GLOBAL) 8 | 9 | # ------------------------------------------------------------------------------ 10 | # Set a common set of compile definitions. 11 | # 12 | # Compile definitions can be removed from the default set by passing REMOVE 13 | # followed by a list of symbols, eg: 14 | # 15 | # asap_set_compile_definitions(sample-target REMOVE _CRT_SECURE_NO_WARNINGS) 16 | # 17 | # will prevent `_CRT_SECURE_NO_WARNINGS` from being passed to the compiler as a 18 | # defined symbol for sample-target only. 19 | # 20 | # Similarly extra definitions can be added by passing ADD followed by a list of 21 | # symbols (or definitions in the form of symbol=value), eg: 22 | # 23 | # asap_set_compile_definitions(sample-target ADD SUPER HERO=2) 24 | # 25 | # will pass SUPER and HERO=2 to the compiler as definitions for sample-target 26 | # only. 27 | # 28 | # When linking against the contract checking and enforcement library 29 | # `asap-contract` (https://github.com/asap-projects/asap-contract), it is 30 | # possible to control the contract checking mode by passing a value for the 31 | # `CONTRACTS` option to this function as follows: 32 | # 33 | # * CONTRACTS OFF : set contract checking mode to OFF 34 | # * CONTRACTS AUDIT : set contract checking mode to AUDIT 35 | # * CONTRACTS DEFAULT : set contract checking mode to DEFAULT 36 | # 37 | # * CONTRACTS AUTO : set contract checking mode using as a first priority the 38 | # value passed in the cmake option `OPTION_CONTRACT_MODE`. If none is present, 39 | # automatically set the mode based on the build configuration. For Debug -> 40 | # AUDIT, For Release and RelMinSize -> OFF, and for RelWithDebInfo -> DEFAULT. 41 | # 42 | # * CONTRACTS TESTING : indicates that contracts are being testing and the 43 | # target needs to have full control on the contract checking mode. Nothing 44 | # will be done here. 45 | # 46 | # The default setting is AUTO. 47 | # ------------------------------------------------------------------------------ 48 | 49 | function(asap_set_compile_definitions target) 50 | set(argOption "") 51 | set(argSingle "CONTRACTS") 52 | set(argMulti "ADD" "REMOVE") 53 | 54 | unset(x_CONTRACTS) 55 | unset(x_ADD) 56 | unset(x_REMOVE) 57 | 58 | cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN}) 59 | if(NOT DEFINED x_CONTRACTS OR x_CONTRACTS STREQUAL "") 60 | set(x_CONTRACTS "AUTO") 61 | endif() 62 | 63 | set(all_definitions) 64 | 65 | # Provide a way to distinguish between debug and release builds via 66 | # preprocessor define 67 | list(APPEND all_definitions "$<$:ASAP_IS_DEBUG_BUILD>") 68 | 69 | if(MSVC) 70 | list(APPEND all_definitions "NOMINMAX" "WIN32_LEAN_AND_MEAN=1" 71 | "_WIN32_WINNT=0x0600") 72 | # Disabling warning for not using "secure-but-not-standard" STL algos 73 | list(APPEND all_definitions "_CRT_SECURE_NO_WARNINGS" 74 | "_SCL_SECURE_NO_WARNINGS") 75 | endif() 76 | 77 | if(x_REMOVE) 78 | foreach(definition ${x_REMOVE}) 79 | list(FIND all_definitions ${definition} found) 80 | if(found EQUAL -1) 81 | message( 82 | FATAL_ERROR 83 | "Compiler definition '${definition}' specified for removal is not " 84 | "part of the set of common compiler definitions.") 85 | endif() 86 | endforeach() 87 | list(REMOVE_ITEM all_definitions ${x_REMOVE}) 88 | endif() 89 | 90 | list(APPEND all_definitions ${x_ADD}) 91 | 92 | target_compile_definitions(${target} PRIVATE ${all_definitions}) 93 | 94 | # If linking against asap_contract, set the contract checking mode. Use 95 | # generator expressions only, do not check for CMAKE_BUILD_TYPE which is not 96 | # friendly with multi-config generators. 97 | if(NOT x_CONTRACTS STREQUAL "TESTING") 98 | if(x_CONTRACTS MATCHES "OFF|AUDIT|DEFAULT") 99 | target_compile_definitions(${target} 100 | PRIVATE "ASAP_CONTRACT_${x_CONTRACTS}") 101 | elseif(x_CONTRACTS STREQUAL "AUTO") 102 | if(NOT DEFINED OPTION_CONTRACT_MODE) 103 | target_compile_definitions( 104 | ${target} 105 | PRIVATE $<$:ASAP_CONTRACT_AUDIT> 106 | $<$:ASAP_CONTRACT_DEFAULT> 107 | $<$:ASAP_CONTRACT_OFF>) 108 | else() 109 | target_compile_definitions( 110 | ${target} PRIVATE "ASAP_CONTRACT_${OPTION_CONTRACT_MODE}") 111 | endif() 112 | else() 113 | message( 114 | FATAL_ERROR "Contract mode '${x_CONTRACTS}' is not valid." 115 | "Valid values are: OFF, DEFAULT, AUDIT, AUTO and TESTING.") 116 | endif() 117 | endif() 118 | endfunction() 119 | -------------------------------------------------------------------------------- /cmake/CompileOptions.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # ------------------------------------------------------------------------------ 8 | # Set additional common compiler options and warning flags 9 | # ------------------------------------------------------------------------------ 10 | # 11 | # Refer to swift_set_compile_options() for additional detailed information on 12 | # accepted options for this function, which forwards all options. 13 | # 14 | # In addition to relaying the call, this function adds common compiler options 15 | # and overrides the default behavior of swift with regard to exceptions and 16 | # RTTI. By default, both are enabled. 17 | 18 | function(asap_set_compile_options) 19 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 20 | # using Clang 21 | swift_set_compile_options( 22 | ADD 23 | -Weverything 24 | -Wno-c++98-compat 25 | -Wno-c++98-compat-pedantic 26 | -Wno-c++98-c++11-compat-pedantic 27 | -Wno-padded 28 | -Wno-documentation-unknown-command) 29 | # -Wno-switch-enum -Wno-unused-macros -Wno-disabled-macro-expansion) 30 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 31 | # using GCC 32 | swift_set_compile_options( 33 | ADD 34 | -Wctor-dtor-privacy 35 | -Winit-self 36 | -Wmissing-declarations 37 | -Wold-style-cast 38 | -Woverloaded-virtual 39 | -Wsign-conversion 40 | -Wsign-promo 41 | -Wundef) 42 | if(NOT DEFINED CMAKE_CXX_CLANG_TIDY) 43 | swift_set_compile_options(ADD -Wlogical-op -Wstrict-null-sentinel) 44 | endif() 45 | elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 46 | # using Visual Studio C++ 47 | set(argOption "WARNING") 48 | set(argSingle "") 49 | set(argMulti "") 50 | 51 | cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN}) 52 | 53 | set(targets ${x_UNPARSED_ARGUMENTS}) 54 | 55 | foreach(target ${targets}) 56 | target_compile_options(${target} PRIVATE /EHsc /MP /W4) 57 | if(NOT x_WARNING) 58 | target_compile_options(${target} PRIVATE /WX) 59 | endif() 60 | # Enable coverage profiling in Debug builds 61 | # (see https://github.com/abdes/asap/issues/22) 62 | target_link_options(${target} PRIVATE $<$:/PROFILE>) 63 | endforeach() 64 | endif() 65 | 66 | endfunction() 67 | 68 | # ------------------------------------------------------------------------------ 69 | # Clean compiler settings and options 70 | # ------------------------------------------------------------------------------ 71 | 72 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC") 73 | # remove default warning level from CMAKE_CXX_FLAGS_INIT CMake adds compiler 74 | # warning levels by default and for MSVC, it uses /W3 which we want to 75 | # override with /W4. The override does make MSVC complain though, so we just 76 | # strip any argument already added by cmake before we set ours. 77 | string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 78 | endif() 79 | -------------------------------------------------------------------------------- /cmake/ComponentInstall.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # Execute cmake_install.cmake wrapper that allows to pass both DESTDIR and 8 | # COMPONENT environment variable 9 | 10 | execute_process(COMMAND ${CMAKE_COMMAND} -DCOMPONENT=$ENV{COMPONENT} -P 11 | cmake_install.cmake) 12 | -------------------------------------------------------------------------------- /cmake/FasterBuild.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # ------------------------------------------------------------------------------ 8 | # Reduce build time by using ccache when available 9 | # ------------------------------------------------------------------------------ 10 | 11 | # Only do the following if we have not already done it in this project or in in 12 | # its parent hierarchy of projects. 13 | if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER OR NOT DEFINED 14 | CMAKE_C_COMPILER_LAUNCHER) 15 | find_program(CCACHE_TOOL_PATH ccache) 16 | 17 | if(NOT WIN32 18 | AND USE_CCACHE 19 | AND CCACHE_TOOL_PATH) 20 | message(STATUS "Using ccache (${CCACHE_TOOL_PATH}) (via wrapper).") 21 | # see https://github.com/TheLartians/Ccache.cmake enables CCACHE support 22 | # through the USE_CCACHE flag possible values are: YES, NO or equivalent 23 | cpmaddpackage("gh:TheLartians/Ccache.cmake@1.2.3") 24 | elseif( 25 | WIN32 26 | AND USE_CCACHE 27 | AND CCACHE_TOOL_PATH) 28 | set(CMAKE_C_COMPILER_LAUNCHER 29 | ${CCACHE_TOOL_PATH} 30 | CACHE STRING "" FORCE) 31 | set(CMAKE_CXX_COMPILER_LAUNCHER 32 | ${CCACHE_TOOL_PATH} 33 | CACHE STRING "" FORCE) 34 | message(STATUS "Using ccache (${CCACHE_TOOL_PATH}).") 35 | endif() 36 | endif() 37 | -------------------------------------------------------------------------------- /cmake/FindSphinx.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # * This module looks for Sphinx Find the Sphinx documentation generator 8 | # 9 | # This modules defines SPHINX_EXECUTABLE SPHINX_FOUND 10 | 11 | find_program( 12 | SPHINX_EXECUTABLE 13 | NAMES sphinx-build 14 | HINTS $ENV{SPHINX_DIR} 15 | PATH_SUFFIXES bin 16 | DOC "Sphinx documentation generator") 17 | 18 | include(FindPackageHandleStandardArgs) 19 | 20 | find_package_handle_standard_args(Sphinx DEFAULT_MSG SPHINX_EXECUTABLE) 21 | 22 | mark_as_advanced(SPHINX_EXECUTABLE) 23 | -------------------------------------------------------------------------------- /cmake/FindValgrind.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | include(common/FindValgrind) 8 | -------------------------------------------------------------------------------- /cmake/Format.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | macro(asap_create_format_targets) 8 | cpmaddpackage(NAME Format.cmake VERSION 1.7.3 GITHUB_REPOSITORY 9 | TheLartians/Format.cmake) 10 | endmacro() 11 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake: -------------------------------------------------------------------------------- 1 | # * Returns a version string from Git 2 | # 3 | # These functions force a re-configure on each git commit so that you can trust 4 | # the values of the variables in your build system. 5 | # 6 | # get_git_head_revision( [ ...]) 8 | # 9 | # Returns the refspec and sha hash of the current head revision 10 | # 11 | # git_describe( [ ...]) 12 | # 13 | # Returns the results of git describe on the source tree, and adjusting the 14 | # output so that it tests false if an error occurs. 15 | # 16 | # git_get_exact_tag( [ ...]) 17 | # 18 | # Returns the results of git describe --exact-match on the source tree, and 19 | # adjusting the output so that it tests false if there was no exact matching 20 | # tag. 21 | # 22 | # Requires CMake 2.6 or newer (uses the 'function' command) 23 | # 24 | # Original Author: 2009-2010 Ryan Pavlik 25 | # http://academic.cleardefinition.com Iowa State University 26 | # HCI Graduate Program/VRAC 27 | # 28 | # Copyright Iowa State University 2009-2010. Distributed under the Boost 29 | # Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy 30 | # at http://www.boost.org/LICENSE_1_0.txt) 31 | 32 | if(__get_git_revision_description) 33 | return() 34 | endif() 35 | set(__get_git_revision_description YES) 36 | 37 | # We must run the following at "include" time, not at function call time, to 38 | # find the path to this module rather than the path to a calling list file 39 | get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) 40 | 41 | function(get_git_head_revision _refspecvar _hashvar) 42 | set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 43 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 44 | while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories 45 | set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") 46 | get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) 47 | if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) 48 | # We have reached the root directory, we are not in git 49 | set(${_refspecvar} 50 | "GITDIR-NOTFOUND" 51 | PARENT_SCOPE) 52 | set(${_hashvar} 53 | "GITDIR-NOTFOUND" 54 | PARENT_SCOPE) 55 | return() 56 | endif() 57 | set(GIT_DIR "${GIT_PARENT_DIR}/.git") 58 | endwhile() 59 | # check if this is a submodule 60 | if(NOT IS_DIRECTORY ${GIT_DIR}) 61 | file(READ ${GIT_DIR} submodule) 62 | string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) 63 | get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) 64 | get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} 65 | ABSOLUTE) 66 | endif() 67 | set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") 68 | if(NOT EXISTS "${GIT_DATA}") 69 | file(MAKE_DIRECTORY "${GIT_DATA}") 70 | endif() 71 | 72 | if(NOT EXISTS "${GIT_DIR}/HEAD") 73 | return() 74 | endif() 75 | set(HEAD_FILE "${GIT_DATA}/HEAD") 76 | configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) 77 | 78 | configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" 79 | "${GIT_DATA}/grabRef.cmake" @ONLY) 80 | include("${GIT_DATA}/grabRef.cmake") 81 | 82 | set(${_refspecvar} 83 | "${HEAD_REF}" 84 | PARENT_SCOPE) 85 | set(${_hashvar} 86 | "${HEAD_HASH}" 87 | PARENT_SCOPE) 88 | endfunction() 89 | 90 | function(git_describe _var) 91 | if(NOT GIT_FOUND) 92 | find_package(Git QUIET) 93 | endif() 94 | get_git_head_revision(refspec hash) 95 | if(NOT GIT_FOUND) 96 | set(${_var} 97 | "GIT-NOTFOUND" 98 | PARENT_SCOPE) 99 | return() 100 | endif() 101 | if(NOT hash) 102 | set(${_var} 103 | "HEAD-HASH-NOTFOUND" 104 | PARENT_SCOPE) 105 | return() 106 | endif() 107 | 108 | execute_process( 109 | COMMAND "${GIT_EXECUTABLE}" describe ${hash} ${ARGN} 110 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 111 | RESULT_VARIABLE res 112 | OUTPUT_VARIABLE out 113 | ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) 114 | if(NOT res EQUAL 0) 115 | set(out "${out}-${res}-NOTFOUND") 116 | endif() 117 | 118 | set(${_var} 119 | "${out}" 120 | PARENT_SCOPE) 121 | endfunction() 122 | 123 | function(git_get_exact_tag _var) 124 | git_describe(out --exact-match ${ARGN}) 125 | set(${_var} 126 | "${out}" 127 | PARENT_SCOPE) 128 | endfunction() 129 | -------------------------------------------------------------------------------- /cmake/GetGitRevisionDescription.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # Internal file for GetGitRevisionDescription.cmake 3 | # 4 | # Requires CMake 2.6 or newer (uses the 'function' command) 5 | # 6 | # Original Author: 7 | # 2009-2010 Ryan Pavlik 8 | # http://academic.cleardefinition.com 9 | # Iowa State University HCI Graduate Program/VRAC 10 | # 11 | # Copyright Iowa State University 2009-2010. 12 | # Distributed under the Boost Software License, Version 1.0. 13 | # (See accompanying file LICENSE_1_0.txt or copy at 14 | # http://www.boost.org/LICENSE_1_0.txt) 15 | 16 | set(HEAD_HASH) 17 | set(HEAD_REF) 18 | 19 | if (NOT EXISTS "@HEAD_FILE@") 20 | return() 21 | endif() 22 | 23 | file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) 24 | 25 | string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) 26 | if(HEAD_CONTENTS MATCHES "ref") 27 | # named branch 28 | string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") 29 | if(EXISTS "@GIT_DIR@/${HEAD_REF}") 30 | configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) 31 | elseif(EXISTS "@GIT_DIR@/packed-refs") 32 | configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) 33 | file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) 34 | if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") 35 | set(HEAD_HASH "${CMAKE_MATCH_1}") 36 | endif() 37 | endif() 38 | else() 39 | # detached HEAD 40 | configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) 41 | endif() 42 | 43 | if(NOT HEAD_HASH AND EXISTS "@GIT_DATA@/head-ref") 44 | file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) 45 | string(STRIP "${HEAD_HASH}" HEAD_HASH) 46 | endif() 47 | -------------------------------------------------------------------------------- /cmake/LanguageStandards.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | include(common/LanguageStandards) 8 | 9 | function(asap_set_language_standards) 10 | swift_set_language_standards(${ARGV}) 11 | endfunction() 12 | -------------------------------------------------------------------------------- /cmake/ListTargets.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | include(common/ListTargets) 8 | 9 | function(asap_get_all_targets result dir) 10 | get_all_targets(${result} ${dir} ${ARGM}) 11 | endfunction() 12 | 13 | function(asap_list_targets out_var) 14 | swift_list_targets(${out_var}, ${ARGN}) 15 | endfunction() 16 | 17 | function(asap_list_compilable_targets out_var) 18 | swift_list_compilable_targets(${out_var}, ${ARGN}) 19 | endfunction() 20 | -------------------------------------------------------------------------------- /cmake/LogHelpers.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # ------------------------------------------------------------------------------ 8 | # Helpers to enhance progress reporting in the cmake output log. 9 | # 10 | # This module defines a global variable: `ASAP_LOG_PROJECT_HIERARCHY` that holds 11 | # a string with the current project/module nesting hierarchy. It can be used in 12 | # cmake `message` calls. 13 | # 14 | # Maintenance of the nesting hierarchy is done with the following macros: 15 | # 16 | # * asap_push_project(project_name) 17 | # * asap_pop_project(project_name) 18 | # * asap_push_module(module_name) 19 | # * asap_pop_module(module_name) 20 | # 21 | # They must be called at the start(push) and end(pop) of a project/module cmake 22 | # script to keep the hierarchy correct. 23 | # ------------------------------------------------------------------------------ 24 | 25 | if(NOT DEFINED ASAP_LOG_PROJECT_HIERARCHY) 26 | set(ASAP_LOG_PROJECT_HIERARCHY_STACK "") 27 | set(ASAP_LOG_PROJECT_HIERARCHY "") 28 | endif() 29 | 30 | macro(asap_push_project project_name) 31 | list(APPEND ASAP_LOG_PROJECT_HIERARCHY_STACK "[${project_name}]") 32 | list(JOIN ASAP_LOG_PROJECT_HIERARCHY_STACK " > " ASAP_LOG_PROJECT_HIERARCHY) 33 | list(LENGTH ASAP_LOG_PROJECT_HIERARCHY_STACK depth) 34 | if(${META_PROJECT_ID}_IS_MASTER_PROJECT) 35 | message("=> [${depth}] in project ${ASAP_LOG_PROJECT_HIERARCHY} (master)") 36 | else() 37 | message( 38 | "=> [${depth}] in project ${ASAP_LOG_PROJECT_HIERARCHY} (sub-project)") 39 | endif() 40 | endmacro() 41 | 42 | macro(asap_pop_project project_name) 43 | list(POP_BACK ASAP_LOG_PROJECT_HIERARCHY_STACK removed) 44 | if(NOT removed STREQUAL "[${project_name}]") 45 | message( 46 | FATAL_ERROR 47 | "Project [${removed}] was pushed but not popped, please fix this") 48 | endif() 49 | list(JOIN ASAP_LOG_PROJECT_HIERARCHY_STACK " > " ASAP_LOG_PROJECT_HIERARCHY) 50 | list(LENGTH ASAP_LOG_PROJECT_HIERARCHY_STACK depth) 51 | if(NOT ${depth} EQUAL 0) 52 | message(".. [${depth}] back to ${ASAP_LOG_PROJECT_HIERARCHY}") 53 | endif() 54 | endmacro() 55 | 56 | macro(asap_push_module module_name) 57 | list(APPEND ASAP_LOG_PROJECT_HIERARCHY_STACK "(${module_name})") 58 | list(JOIN ASAP_LOG_PROJECT_HIERARCHY_STACK " > " ASAP_LOG_PROJECT_HIERARCHY) 59 | list(LENGTH ASAP_LOG_PROJECT_HIERARCHY_STACK depth) 60 | message("=> [${depth}] in module ${ASAP_LOG_PROJECT_HIERARCHY}") 61 | endmacro() 62 | 63 | macro(asap_pop_module module_name) 64 | list(POP_BACK ASAP_LOG_PROJECT_HIERARCHY_STACK removed) 65 | if(NOT removed STREQUAL "(${module_name})") 66 | message( 67 | FATAL_ERROR 68 | "Module [${removed}] was pushed but not popped, please fix this") 69 | endif() 70 | list(JOIN ASAP_LOG_PROJECT_HIERARCHY_STACK " > " ASAP_LOG_PROJECT_HIERARCHY) 71 | list(LENGTH ASAP_LOG_PROJECT_HIERARCHY_STACK depth) 72 | message(".. [${depth}] back to ${ASAP_LOG_PROJECT_HIERARCHY}") 73 | endmacro() 74 | -------------------------------------------------------------------------------- /cmake/ResetInitialCompilerOptions.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # This module is loaded by `cmake` while enabling support for each language from 8 | # either the project() or enable_language() commands. It is loaded after CMake's 9 | # builtin compiler and platform information modules have been loaded but before 10 | # the information is used. The file may set platform information variables to 11 | # override CMake's defaults. 12 | # 13 | # To load this module, set the variable `CMAKE_USER_MAKE_RULES_OVERRIDE` before 14 | # you declare the project or enable a language: 15 | # ~~~ 16 | # set(CMAKE_USER_MAKE_RULES_OVERRIDE "ResetInitialCompilerOptions") 17 | # ~~~ 18 | 19 | # We use this module to strip compiler options that are not really needed but 20 | # will cause compatibility issues with `ccache`. 21 | if(MSVC AND USE_CCACHE) 22 | # As of ccache 4.6, /Zi option automatically added by cmake is unsupported. 23 | # Given that we are doing ccache only in development environments (USE_CCACHE 24 | # controls if ccache is enabled), we can just strip that option. 25 | macro(strip_unwanted_options_from cmake_flags) 26 | if(${cmake_flags} MATCHES "/Zi") 27 | string(REPLACE "/Zi" "/Z7" ${cmake_flags} ${${cmake_flags}}) 28 | endif() 29 | endmacro() 30 | strip_unwanted_options_from(CMAKE_CXX_FLAGS_DEBUG_INIT) 31 | strip_unwanted_options_from(CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT) 32 | strip_unwanted_options_from(CMAKE_C_FLAGS_DEBUG_INIT) 33 | strip_unwanted_options_from(CMAKE_C_FLAGS_RELWITHDEBINFO_INIT) 34 | set(first_time FALSE) 35 | endif() 36 | -------------------------------------------------------------------------------- /cmake/TestTargets.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | include(common/TestTargets) 8 | 9 | macro(asap_add_test target) 10 | set(argOption) 11 | set(argSingle CONTRACTS) 12 | set(argMulti) 13 | 14 | cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN}) 15 | 16 | # Contrarily to swift default, we enable exceptions and RTTI for all targets 17 | swift_add_test("${target}" ${warning_flag} ${x_UNPARSED_ARGUMENTS}) 18 | # Set some common private compiler defines 19 | asap_set_compile_definitions(${target} CONTRACTS ${x_CONTRACTS}) 20 | # Set common compiler options 21 | asap_set_compile_options(${target}) 22 | if(TARGET gtest AND BUILD_SHARED_LIBS) 23 | target_compile_definitions(${target} PRIVATE GTEST_LINKED_AS_SHARED_LIBRARY) 24 | if(MSVC) 25 | target_compile_options(${target} PRIVATE /wd4251) 26 | endif() 27 | if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 28 | asap_set_compile_options( 29 | ${target} ADD "-Wno-used-but-marked-unused" "-Wno-global-constructors" 30 | "-Wno-unused-member-function") 31 | endif() 32 | endif() 33 | set_target_properties(${target} PROPERTIES FOLDER "Unit Tests") 34 | endmacro() 35 | 36 | macro(asap_add_test_runner target) 37 | swift_add_test_runner("${target}" ${ARGN}) 38 | endmacro() 39 | 40 | function(asap_add_test_library target) 41 | set(argOption) 42 | set(argSingle CONTRACTS) 43 | set(argMulti) 44 | 45 | cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN}) 46 | 47 | # Contrarily to swift default, we enable exceptions and RTTI for all targets 48 | swift_add_test_library("${target}" ${x_UNPARSED_ARGUMENTS}) 49 | # Set some common private compiler defines 50 | asap_set_compile_definitions(${target} CONTRACTS ${x_CONTRACTS}) 51 | # Set some common compiler options 52 | asap_set_compile_options(${target}) 53 | set_target_properties( 54 | ${target} 55 | PROPERTIES FOLDER "Test Libraries" 56 | VERSION ${META_MODULE_VERSION} 57 | SOVERSION ${META_MODULE_VERSION_MAJOR} 58 | DEBUG_POSTFIX "d") 59 | endfunction() 60 | -------------------------------------------------------------------------------- /cmake/Valgrind.cmake: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | mark_as_advanced(${PROJECT_NAME}_ENABLE_PROFILING) 8 | set(${PROJECT_NAME}_ENABLE_PROFILING ${ASAP_WITH_VALGRIND}) 9 | 10 | include(common/Valgrind) 11 | -------------------------------------------------------------------------------- /cmake/scripts/standard-version-updater.js: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | // ----------------------------------------------------------------------------- 8 | // Detect the dominant newline character of a string, from 'detect-newline' 9 | // https://github.com/sindresorhus/detect-newline 10 | // 11 | // MIT License 12 | // ----------------------------------------------------------------------------- 13 | function detectNewline(string) { 14 | if (typeof string !== 'string') { 15 | throw new TypeError('Expected a string'); 16 | } 17 | 18 | const newlines = string.match(/(?:\r?\n)/g) || []; 19 | 20 | if (newlines.length === 0) { 21 | return; 22 | } 23 | 24 | const crlf = newlines.filter(newline => newline === '\r\n').length; 25 | const lf = newlines.length - crlf; 26 | 27 | return crlf > lf ? '\r\n' : '\n'; 28 | } 29 | 30 | function detectNewlineGraceful(string) { 31 | return (typeof string === 'string' && detectNewline(string)) || '\n'; 32 | } 33 | // ----------------------------------------------------------------------------- 34 | 35 | // ----------------------------------------------------------------------------- 36 | // Version reader/updated for standard-version that uses the mETA information in 37 | // the CmakeLists.txt file 38 | // ----------------------------------------------------------------------------- 39 | 40 | const major_rex = /set\(META_VERSION_MAJOR\s+\"(\d+)\"\)/; 41 | const minor_rex = /set\(META_VERSION_MINOR\s+\"(\d+)\"\)/; 42 | const patch_rex = /set\(META_VERSION_PATCH\s+\"(\d+)\"\)/; 43 | 44 | module.exports.readVersion = 45 | function(contents) { 46 | var major = null, minor = null, patch = null; 47 | 48 | const lines = contents.split(/\r?\n/); 49 | for (let index in lines) { 50 | let line = lines[index]; 51 | var match = null; 52 | if (major == null) { 53 | var match = major_rex.exec(line); 54 | if (match != null) { 55 | major = match[1]; 56 | } 57 | } 58 | if (match == null && minor == null) { 59 | var match = minor_rex.exec(line); 60 | if (match != null) { 61 | minor = match[1]; 62 | } 63 | } 64 | if (match == null && patch == null) { 65 | var match = patch_rex.exec(line); 66 | if (match != null) { 67 | patch = match[1]; 68 | } 69 | } 70 | if (major != null && minor != null && patch != null) break; 71 | }; 72 | 73 | if (major == null) 74 | console.error( 75 | 'Your CmakeLists.txt is missing META_VERSION_MAJOR variable!'); 76 | if (minor == null) 77 | console.error( 78 | 'Your CmakeLists.txt is missing META_VERSION_MINOR variable!'); 79 | if (patch == null) 80 | console.error( 81 | 'Your CmakeLists.txt is missing META_VERSION_PATCH variable!'); 82 | 83 | return major + '.' + minor + '.' + patch; 84 | } 85 | 86 | module.exports.writeVersion = function(contents, version) { 87 | var [major, minor, patch] = version.split('.'); 88 | var newContents = []; 89 | 90 | const lines = contents.split(/\r?\n/); 91 | lines.forEach(line => { 92 | var newLine = 93 | line.replace(major_rex, 'set(META_VERSION_MAJOR "' + major + '")') 94 | .replace(minor_rex, 'set(META_VERSION_MINOR "' + minor + '")') 95 | .replace( 96 | patch_rex, 'set(META_VERSION_PATCH "' + patch + '")'); 97 | newContents.push(newLine); 98 | }); 99 | 100 | let newline = detectNewlineGraceful(contents) 101 | return newContents.join(newline); 102 | } 103 | -------------------------------------------------------------------------------- /codec/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files inside source tree 2 | doc/conf.py 3 | -------------------------------------------------------------------------------- /codec/README.md: -------------------------------------------------------------------------------- 1 | # Encoding/Decoding utilities for blocxxi 2 | -------------------------------------------------------------------------------- /codec/config.cmake.in: -------------------------------------------------------------------------------- 1 | set(@MODULE_TARGET_NAME@_VERSION @META_MODULE_VERSION@) 2 | 3 | @PACKAGE_INIT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 6 | 7 | check_required_components(@MODULE_TARGET_NAME@) 8 | -------------------------------------------------------------------------------- /codec/config.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@ASAP_INSTALL_PREFIX_FULL_PATH@ 2 | libdir=${prefix}/@ASAP_INSTALL_LIB@ 3 | includedir=${prefix}/@ASAP_INSTALL_INCLUDE@ 4 | 5 | Name: @MODULE_TARGET_NAME@ 6 | URL: @META_MODULE_GITHUB_REPO@ 7 | Description: @META_MODULE_DESCRIPTION@ 8 | Version: @META_MODULE_VERSION@ 9 | Requires.private: Microsoft.GSL asap_common 10 | Requires: 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} @MODULE_LINK_LIBS@ 13 | -------------------------------------------------------------------------------- /codec/doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/codec/doc/_static/favicon.ico -------------------------------------------------------------------------------- /codec/doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/codec/doc/_static/logo.png -------------------------------------------------------------------------------- /codec/doc/api.rst: -------------------------------------------------------------------------------- 1 | .. asap_common documentation master file, created by 2 | sphinx-quickstart on Tue Sep 11 14:51:58 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | API reference 7 | ============= 8 | 9 | .. |date| date:: 10 | 11 | Last Updated on |date| 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | :hidden: 16 | 17 | CommandLine 18 | -------------------------------------------------------------------------------- /codec/doc/api/codec.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | *********** 10 | CommandLine 11 | *********** 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. todo:: 18 | 19 | Documentation is to be completed 20 | -------------------------------------------------------------------------------- /codec/doc/conf.py.in: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'@META_PROJECT_NAME@/@META_MODULE_NAME@' 23 | copyright = u'2022, The Authors' 24 | 25 | # The short X.Y version 26 | version = u'@META_MODULE_VERSION@' 27 | 28 | rst_prolog = """ 29 | .. |version| replace:: {0} 30 | """.format(version) 31 | 32 | 33 | # -- General configuration --------------------------------------------------- 34 | 35 | # If your documentation needs a minimal Sphinx version, state it here. 36 | # 37 | # needs_sphinx = '1.0' 38 | 39 | # Add any Sphinx extension module names here, as strings. They can be 40 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 41 | # ones. 42 | extensions = [ 43 | 'sphinx.ext.intersphinx', 44 | 'sphinx.ext.todo', 45 | 'sphinx.ext.coverage', 46 | 'sphinx.ext.viewcode', 47 | 'sphinx-prompt', 48 | 'sphinx_copybutton', 49 | 'breathe', 50 | ] 51 | 52 | # Setup the breathe extension 53 | breathe_projects = { 54 | "@META_PROJECT_NAME@_@META_MODULE_NAME@": "@DOXYGEN_BUILD_DIR@/@META_PROJECT_NAME@_@META_MODULE_NAME@/xml" 55 | } 56 | breathe_default_project = "@META_PROJECT_NAME@_@META_MODULE_NAME@" 57 | 58 | # Tell sphinx what the primary language being documented is. 59 | primary_domain = 'cpp' 60 | 61 | # Tell sphinx what the pygments highlight language should be. 62 | highlight_language = 'cpp' 63 | 64 | # Add any paths that contain templates here, relative to this directory. 65 | templates_path = ['_templates'] 66 | 67 | # Add any paths that contain custom static files (such as style sheets) here, 68 | # relative to this directory. They are copied after the builtin static files, so 69 | # a file named "default.css" will overwrite the builtin "default.css". 70 | html_static_path = ["_static"] 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. This pattern also affects 74 | # html_static_path and html_extra_path. 75 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".sphinx"] 76 | 77 | # The suffix(es) of source filenames. 78 | # You can specify multiple suffix as a list of string: 79 | # 80 | # source_suffix = ['.rst', '.md'] 81 | source_suffix = '.rst' 82 | 83 | # The master toctree document. 84 | master_doc = 'index' 85 | 86 | # The language for content autogenerated by Sphinx. Refer to documentation 87 | # for a list of supported languages. 88 | # 89 | # This is also used if you do content translation via gettext catalogs. 90 | # Usually you set "language" from the command line for these cases. 91 | language = "en" 92 | 93 | # The name of the Pygments (syntax highlighting) style to use. 94 | pygments_style = 'sphinx' 95 | 96 | 97 | # -- Options for HTML output ------------------------------------------------- 98 | 99 | # The theme to use for HTML and HTML Help pages. See the documentation for 100 | # a list of builtin themes. 101 | # 102 | html_theme = 'sphinx_book_theme' 103 | 104 | html_title = u'Module: @META_MODULE_NAME@' 105 | html_logo = "_static/logo.png" 106 | html_favicon = "_static/favicon.ico" 107 | 108 | # If this is not None, a ‘Last updated on:’ timestamp is inserted at every page 109 | # bottom, using the given strftime() format. The empty string is equivalent to 110 | # '%b %d, %Y' (or a locale-dependent equivalent). 111 | html_last_updated_fmt = None 112 | 113 | html_theme_options = { 114 | "repository_url": '@META_GITHUB_REPO@', 115 | "use_repository_button": True, 116 | "use_issues_button": True, 117 | "use_edit_page_button": False, 118 | "use_download_button": True, 119 | "use_fullscreen_button": True, 120 | # We don't want the default navigation bar footer to be displayed on every 121 | # page. Mention of the book theme will be added in the home page. 122 | "extra_footer": "" 123 | } 124 | 125 | # -- Extension configuration ------------------------------------------------- 126 | 127 | # -- Options for intersphinx extension --------------------------------------- 128 | 129 | # Example configuration for intersphinx: refer to the Python standard library. 130 | #intersphinx_mapping = {'https://docs.python.org/': None} 131 | 132 | # -- Options for todo extension ---------------------------------------------- 133 | 134 | # If true, `todo` and `todoList` produce output, else they produce nothing. 135 | todo_include_todos = True 136 | -------------------------------------------------------------------------------- /codec/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ################################### 10 | BLOCXXI encoding/decoding utilities 11 | ################################### 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :hidden: 20 | 21 | API 22 | License 23 | Version 24 | 25 | Welcome! This is the documentation for the *codec* module, part of the *blocxxi* 26 | project. It contains encoding/decoding utilities needed for the implementation 27 | of the DHT and blockchain. 28 | 29 | Parts of the documentation 30 | ========================== 31 | 32 | :doc:`API reference ` 33 | ------------------------------ 34 | *check this out to see the documentation of classes, macros, etc. offered by 35 | this module* 36 | -------------------------------------------------------------------------------- /codec/doc/license.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | License 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. include:: ../../LICENSE 18 | 19 | -------------------------------------------------------------------------------- /codec/doc/version.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | Version 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | |release| 18 | -------------------------------------------------------------------------------- /codec/include/codec/base16.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | /*! 8 | * \file 9 | * 10 | * \brief Base16 encoding/decoding routines. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | 22 | /// Hexadecimal (base16) encoding/decoding utilities. 23 | namespace blocxxi::codec::hex { 24 | 25 | /*! 26 | * \brief Encode buffer to an hexadecimal/base16 string, as per 27 | * [RFC-4648](https://www.rfc-editor.org/rfc/rfc4648). The result is an 28 | * hexadecimal/base16 encoded UTF-8 string. 29 | * 30 | * \param [in] src data to be encoded. 31 | * \param [in] reverse when `true`, the encoding will start from the end of the 32 | * buffer instead of the beginning. Default is `false`. 33 | * \param [in] lower_case when `true`, the encoded string will use lower case 34 | * letters for the hex digits. Default is `false`. 35 | * \return A string containing the hex-encoded data. 36 | */ 37 | BLOCXXI_CODEC_API auto Encode(gsl::span src, 38 | bool reverse = false, bool lower_case = false) -> std::string; 39 | 40 | /*! 41 | * \brief Decode an hexadecimal/base16 encoded string, as per 42 | * [RFC-4648](https://www.rfc-editor.org/rfc/rfc4648). Input data is assumed to 43 | * be an hexadecimal/base16 encoded UTF-8 string. 44 | * 45 | * \param [in] src buffer containing encoded data. 46 | * \param [out] dest buffer to receive the decoded data. Must be large enough to 47 | * receive all of the decoded data. 48 | * \param [in] reverse when `true`, the decoding will start from the end of the 49 | * buffer instead of the beginning. Default is `false`. 50 | * 51 | * \throw std::domain_error if the input data contains characters not part of 52 | * the valid alphabet for Base 16 encoding. 53 | * 54 | * \note Providing a `dest` buffer that is smaller than what is needed will 55 | * abort the program. It is the responsibility of the caller to ensure the 56 | * provided range is enough for the input data. 57 | */ 58 | BLOCXXI_CODEC_API void Decode( 59 | gsl::span src, gsl::span dest, bool reverse = false); 60 | 61 | } // namespace blocxxi::codec::hex 62 | -------------------------------------------------------------------------------- /codec/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===------------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===------------------------------------------------------------------------===# 6 | 7 | # ============================================================================== 8 | # Build instructions 9 | # ============================================================================== 10 | 11 | set(MAIN_TEST_TARGET_NAME ${MODULE_TARGET_NAME}_test) 12 | 13 | asap_add_test( 14 | ${MAIN_TEST_TARGET_NAME} 15 | UNIT_TEST 16 | VALGRIND_MEMCHECK 17 | SRCS 18 | "base16_test.cpp" 19 | "main.cpp" 20 | LINK 21 | asap::common 22 | asap::contract-ut 23 | GSL 24 | blocxxi::codec 25 | gtest 26 | gmock 27 | COMMENT 28 | "Blocxxi codec unit tests") 29 | 30 | target_include_directories(${MAIN_TEST_TARGET_NAME} PRIVATE "../src") 31 | 32 | gtest_discover_tests(${MAIN_TEST_TARGET_NAME} NO_PRETTY_VALUES) 33 | 34 | # Add support for (optional) code quality tools 35 | asap_add_sanitizers(${MAIN_TEST_TARGET_NAME}) 36 | swift_add_valgrind_massif(${MAIN_TEST_TARGET_NAME}) 37 | swift_add_valgrind_callgrind(${MAIN_TEST_TARGET_NAME}) 38 | -------------------------------------------------------------------------------- /codec/test/main.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | auto main(int argc, char *argv[]) -> int { 12 | // We're doing unit tests with contract checks which require initializing the 13 | // asap::contract library before running the tests. 14 | asap::contract::PrepareForTesting(); 15 | 16 | testing::InitGoogleTest(&argc, argv); 17 | return RUN_ALL_TESTS(); 18 | } 19 | -------------------------------------------------------------------------------- /crypto/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files inside source tree 2 | doc/conf.py 3 | -------------------------------------------------------------------------------- /crypto/README.md: -------------------------------------------------------------------------------- 1 | # Crypto utilities for blocxxi 2 | -------------------------------------------------------------------------------- /crypto/config.cmake.in: -------------------------------------------------------------------------------- 1 | set(@MODULE_TARGET_NAME@_VERSION @META_MODULE_VERSION@) 2 | 3 | @PACKAGE_INIT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 6 | 7 | check_required_components(@MODULE_TARGET_NAME@) 8 | -------------------------------------------------------------------------------- /crypto/config.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@ASAP_INSTALL_PREFIX_FULL_PATH@ 2 | libdir=${prefix}/@ASAP_INSTALL_LIB@ 3 | includedir=${prefix}/@ASAP_INSTALL_INCLUDE@ 4 | 5 | Name: @MODULE_TARGET_NAME@ 6 | URL: @META_MODULE_GITHUB_REPO@ 7 | Description: @META_MODULE_DESCRIPTION@ 8 | Version: @META_MODULE_VERSION@ 9 | Requires.private: asap::codec cryptopp-static Boost::endian 10 | Requires: asap::common 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} @MODULE_LINK_LIBS@ 13 | -------------------------------------------------------------------------------- /crypto/doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/crypto/doc/_static/favicon.ico -------------------------------------------------------------------------------- /crypto/doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/crypto/doc/_static/logo.png -------------------------------------------------------------------------------- /crypto/doc/api.rst: -------------------------------------------------------------------------------- 1 | .. asap_common documentation master file, created by 2 | sphinx-quickstart on Tue Sep 11 14:51:58 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | API reference 7 | ============= 8 | 9 | .. |date| date:: 10 | 11 | Last Updated on |date| 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | :hidden: 16 | 17 | Crypto 18 | -------------------------------------------------------------------------------- /crypto/doc/api/codec.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | *********** 10 | CommandLine 11 | *********** 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. todo:: 18 | 19 | Documentation is to be completed 20 | -------------------------------------------------------------------------------- /crypto/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ######################## 10 | Blocxxi crypto utilities 11 | ######################## 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :hidden: 20 | 21 | API 22 | License 23 | Version 24 | 25 | Welcome! This is the documentation for the *crypto* module, part of the *blocxxi* 26 | project. It contains cryptography utilities needed for the implementation 27 | of the DHT and blockchain. 28 | 29 | Parts of the documentation 30 | ========================== 31 | 32 | :doc:`API reference ` 33 | ------------------------------ 34 | *check this out to see the documentation of classes, macros, etc. offered by 35 | this module* 36 | -------------------------------------------------------------------------------- /crypto/doc/license.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | License 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. include:: ../../LICENSE 18 | 19 | -------------------------------------------------------------------------------- /crypto/doc/version.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | Version 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | |release| 18 | -------------------------------------------------------------------------------- /crypto/include/crypto/config.h.in: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #cmakedefine01 BLOCXXI_HAS_BUILTIN_CLZ 10 | #cmakedefine01 BLOCXXI_HAS_BITSCAN_REVERSE 11 | -------------------------------------------------------------------------------- /crypto/include/crypto/keypair.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace blocxxi::crypto { 14 | 15 | class KeyPair { 16 | public: 17 | using PrivateKey = blocxxi::crypto::Hash256; 18 | using PublicKey = blocxxi::crypto::Hash512; 19 | 20 | BLOCXXI_CRYPTO_API KeyPair(); 21 | 22 | explicit BLOCXXI_CRYPTO_API KeyPair(const std::string &secret_hex); 23 | 24 | explicit BLOCXXI_CRYPTO_API KeyPair(const PrivateKey &secret); 25 | 26 | BLOCXXI_CRYPTO_API KeyPair(const KeyPair &) = default; 27 | 28 | BLOCXXI_CRYPTO_API auto operator=(const KeyPair &rhs) -> KeyPair & = default; 29 | 30 | BLOCXXI_CRYPTO_API KeyPair(KeyPair &&) = default; 31 | 32 | BLOCXXI_CRYPTO_API auto operator=(KeyPair &&rhs) -> KeyPair & = default; 33 | 34 | BLOCXXI_CRYPTO_API ~KeyPair() { 35 | secret_.Clear(); 36 | } 37 | 38 | [[nodiscard]] BLOCXXI_CRYPTO_API auto Secret() const -> const PrivateKey & { 39 | return secret_; 40 | } 41 | 42 | [[nodiscard]] BLOCXXI_CRYPTO_API auto Public() const -> const PublicKey & { 43 | return public_; 44 | } 45 | 46 | private: 47 | PrivateKey secret_; 48 | PublicKey public_; 49 | }; 50 | 51 | } // namespace blocxxi::crypto 52 | -------------------------------------------------------------------------------- /crypto/include/crypto/random.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include // for std::size_t 12 | #include // for uint8_t 13 | 14 | namespace blocxxi::crypto::random { 15 | 16 | BLOCXXI_CRYPTO_API void GenerateBlock(std::uint8_t *output, std::size_t size); 17 | 18 | } // namespace blocxxi::crypto::random 19 | -------------------------------------------------------------------------------- /crypto/src/hash.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | ASAP_DIAGNOSTIC_PUSH 13 | #if defined(ASAP_GNUC_VERSION) 14 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" 15 | #endif 16 | #if defined(ASAP_CLANG_VERSION) && \ 17 | ASAP_HAS_WARNING("-Wreserved-macro-identifier") 18 | #pragma clang diagnostic ignored "-Wreserved-macro-identifier" 19 | #endif 20 | #if defined(ASAP_CLANG_VERSION) && ASAP_HAS_WARNING("-Wreserved-identifier") 21 | #pragma clang diagnostic ignored "-Wreserved-identifier" 22 | #endif 23 | #include 24 | ASAP_DIAGNOSTIC_POP 25 | 26 | namespace blocxxi::crypto::detail { 27 | 28 | auto HostToNetwork(std::uint32_t number) -> std::uint32_t { 29 | return boost::endian::native_to_big(number); 30 | } 31 | 32 | auto NetworkToHost(std::uint32_t number) -> std::uint32_t { 33 | return boost::endian::big_to_native(number); 34 | } 35 | 36 | ///@{ 37 | /// Find first set functions. 38 | /// For details on the algorithms and options refer to 39 | /// https://en.wikipedia.org/wiki/Find_first_set 40 | /// 41 | /// These functions expect the range to be in big-endian byte order. 42 | 43 | inline auto CountLeadingZeroBits_SW(gsl::span buf) 44 | -> size_t { 45 | auto const num = buf.size(); 46 | std::uint32_t const *ptr = buf.data(); 47 | 48 | for (size_t i = 0; i < num; i++) { 49 | if (ptr[i] == 0) { 50 | continue; 51 | } 52 | std::uint32_t v = NetworkToHost(ptr[i]); 53 | 54 | // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious 55 | constexpr size_t MultiplyDeBruijnBitPosition[32] = {0, 9, 1, 10, 13, 21, 2, 56 | 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 57 | 23, 6, 26, 5, 4, 31}; 58 | 59 | v |= v >> 1; // first round down to one less than a power of 2 60 | v |= v >> 2; 61 | v |= v >> 4; 62 | v |= v >> 8; 63 | v |= v >> 16; 64 | 65 | // clang-format off 66 | return i * 32 + 31 - MultiplyDeBruijnBitPosition[static_cast(v * 0x07C4ACDDU) >> 27]; 67 | // clang-format on 68 | } 69 | 70 | return num * 32; 71 | } 72 | 73 | inline auto CountLeadingZeroBits_HW(gsl::span buf) 74 | -> size_t { 75 | auto const num = buf.size(); 76 | std::uint32_t const *ptr = buf.data(); 77 | 78 | for (size_t i = 0; i < num; i++) { 79 | if (ptr[i] == 0) { 80 | continue; 81 | } 82 | std::uint32_t v = NetworkToHost(ptr[i]); 83 | 84 | #if BLOCXXI_HAS_BUILTIN_CLZ 85 | return i * 32 + static_cast(__builtin_clz(v)); 86 | #elif BLOCXXI_HAS_BITSCAN_REVERSE 87 | unsigned long pos; 88 | _BitScanReverse(&pos, v); 89 | return i * 32 + 31 - pos; 90 | #endif 91 | } 92 | 93 | return num * 32; 94 | } 95 | 96 | auto CountLeadingZeroBits(gsl::span buf) -> size_t { 97 | #if BLOCXXI_HAS_BUILTIN_CLZ || BLOCXXI_HAS_BITSCAN_REVERSE 98 | return CountLeadingZeroBits_HW(buf); 99 | #else 100 | return CountLeadingZeroBits_SW(buf); 101 | #endif 102 | } 103 | 104 | ///@} 105 | 106 | } // namespace blocxxi::crypto::detail 107 | -------------------------------------------------------------------------------- /crypto/src/keypair.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include // TODO(Abdessattar): remove only for debug 10 | 11 | #include 12 | 13 | ASAP_DIAGNOSTIC_PUSH 14 | #if defined(ASAP_GNUC_VERSION) 15 | #pragma GCC diagnostic ignored "-Wshadow" 16 | #endif 17 | #include // for cryptopp ECC encryption 18 | #include // for cryptopp ECC curve function 19 | #include // for cryptopp random number generation 20 | ASAP_DIAGNOSTIC_POP 21 | 22 | namespace blocxxi::crypto { 23 | 24 | namespace cr = CryptoPP; 25 | 26 | namespace { 27 | using PrivateKeyType = cr::ECDSA::PrivateKey; 28 | using PublicKeyType = cr::ECDSA::PublicKey; 29 | 30 | void MakeRandomPrivateKey(PrivateKeyType &private_key) { 31 | // Generate a new random private key 32 | cr::AutoSeededRandomPool prng; 33 | 34 | do { 35 | private_key.Initialize(prng, cr::ASN1::secp256k1()); 36 | // Level denotes the level of thoroughness: 0 - using this object won't 37 | // cause a crash or exception (rng is ignored); 1 - this object will 38 | // probably function (encrypt, sign, etc.) correctly (but may not check for 39 | // weak keys and such); 2 - make sure this object will function correctly, 40 | // and do reasonable security checks; 3 - do checks that may take a long 41 | // time. 42 | } while (!private_key.Validate(prng, 3)); 43 | } 44 | 45 | void MakePrivateKeyFromSecret( 46 | PrivateKeyType &private_key, const KeyPair::PrivateKey &secret) { 47 | // Initialize the PrivateKey from the given private exponent 48 | const cr::Integer privateExponent(secret.Data(), KeyPair::PrivateKey::Size(), 49 | cr::Integer::UNSIGNED, cr::ByteOrder::BIG_ENDIAN_ORDER); 50 | private_key.Initialize(cr::ASN1::secp256k1(), privateExponent); 51 | } 52 | 53 | void DerivePublicKey( 54 | PublicKeyType &public_key, const PrivateKeyType &private_key) { 55 | // Derive the public key 56 | private_key.MakePublicKey(public_key); 57 | } 58 | 59 | void UpdateSecret( 60 | KeyPair::PrivateKey &hash, const PrivateKeyType &private_key) { 61 | // Save the private exponent part of the key in our secret part 62 | auto const &pex = private_key.GetPrivateExponent(); 63 | constexpr std::size_t c_secret_length = 32; 64 | pex.Encode(hash.Data(), c_secret_length); 65 | } 66 | 67 | void UpdatePublic(KeyPair::PublicKey &hash, const PublicKeyType &public_key) { 68 | // Save the public key in our public part (which must be 64 bytes long) 69 | const auto &pk_ecp = public_key.GetPublicElement(); 70 | const auto pk_ecp_x = pk_ecp.x; 71 | const auto pk_ecp_y = pk_ecp.y; 72 | constexpr std::size_t c_public_part_length = 32; 73 | pk_ecp_x.Encode(hash.Data(), c_public_part_length); 74 | pk_ecp_y.Encode(hash.Data() + c_public_part_length, c_public_part_length); 75 | } 76 | 77 | } // namespace 78 | 79 | KeyPair::KeyPair() { 80 | PrivateKeyType private_key; 81 | PublicKeyType public_key; 82 | try { 83 | MakeRandomPrivateKey(private_key); 84 | DerivePublicKey(public_key, private_key); 85 | } catch (std::exception &ex) { 86 | // Change to log 87 | std::cerr << "Failed to initialize KeyPair: " << ex.what() << std::endl; 88 | throw; 89 | } 90 | 91 | // Non exception throwing code 92 | UpdateSecret(secret_, private_key); 93 | UpdatePublic(public_, public_key); 94 | } 95 | 96 | KeyPair::KeyPair(const KeyPair::PrivateKey &secret) { 97 | PublicKeyType public_key; 98 | try { 99 | PrivateKeyType private_key; 100 | MakePrivateKeyFromSecret(private_key, secret); 101 | DerivePublicKey(public_key, private_key); 102 | } catch (std::exception &ex) { 103 | // Change to log 104 | std::cerr << "Failed to initialize KeyPair: " << ex.what() << std::endl; 105 | throw; 106 | } 107 | 108 | // Non exception throwing code 109 | secret_ = secret; 110 | UpdatePublic(public_, public_key); 111 | } 112 | 113 | KeyPair::KeyPair(const std::string &secret_hex) { 114 | PrivateKeyType private_key; 115 | PublicKeyType public_key; 116 | try { 117 | // Don't reverse so that the encoded data is big endian 118 | const auto secret = KeyPair::PrivateKey::FromHex(secret_hex, false); 119 | MakePrivateKeyFromSecret(private_key, secret); 120 | DerivePublicKey(public_key, private_key); 121 | } catch (const std::exception &ex) { 122 | // Change to log 123 | std::cerr << "Failed to initialize KeyPair: " << ex.what() << std::endl; 124 | throw; 125 | } 126 | 127 | // Non exception throwing code 128 | // Use the clean secret from the private key 129 | UpdateSecret(secret_, private_key); 130 | UpdatePublic(public_, public_key); 131 | } 132 | 133 | } // namespace blocxxi::crypto 134 | -------------------------------------------------------------------------------- /crypto/src/random.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include // for random number generation 10 | 11 | namespace blocxxi::crypto::random { 12 | 13 | void GenerateBlock(std::uint8_t *output, std::size_t size) { 14 | CryptoPP::AutoSeededRandomPool rng; 15 | rng.GenerateBlock(output, size); 16 | } 17 | 18 | } // namespace blocxxi::crypto::random 19 | -------------------------------------------------------------------------------- /crypto/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===------------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===------------------------------------------------------------------------===# 6 | 7 | # ============================================================================== 8 | # Build instructions 9 | # ============================================================================== 10 | 11 | set(MAIN_TEST_TARGET_NAME ${MODULE_TARGET_NAME}_test) 12 | 13 | asap_add_test( 14 | ${MAIN_TEST_TARGET_NAME} 15 | UNIT_TEST 16 | VALGRIND_MEMCHECK 17 | SRCS 18 | "hash_test.cpp" 19 | "keypair_test.cpp" 20 | "main.cpp" 21 | LINK 22 | asap::common 23 | GSL 24 | blocxxi::codec 25 | blocxxi::crypto 26 | gtest 27 | gmock 28 | COMMENT 29 | "Blocxxi crypto unit tests") 30 | 31 | target_include_directories(${MAIN_TEST_TARGET_NAME} PRIVATE "../src") 32 | 33 | gtest_discover_tests(${MAIN_TEST_TARGET_NAME}) 34 | 35 | # Add support for (optional) code quality tools 36 | asap_add_sanitizers(${MAIN_TEST_TARGET_NAME}) 37 | swift_add_valgrind_massif(${MAIN_TEST_TARGET_NAME}) 38 | swift_add_valgrind_callgrind(${MAIN_TEST_TARGET_NAME}) 39 | -------------------------------------------------------------------------------- /crypto/test/keypair_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | // Disable compiler and linter warnings originating from the unit test framework 14 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 15 | // usage must be preceded by a '// NOLINTNEXTLINE'. 16 | ASAP_DIAGNOSTIC_PUSH 17 | #if defined(ASAP_CLANG_VERSION) 18 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 19 | #pragma clang diagnostic ignored "-Wglobal-constructors" 20 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 21 | #pragma clang diagnostic ignored "-Wweak-vtables" 22 | #endif 23 | 24 | namespace blocxxi::crypto { 25 | 26 | // NOLINTNEXTLINE 27 | TEST(KeyPairTest, NewKeyPair) { 28 | auto kpair = KeyPair(); 29 | 30 | std::cout << kpair.Secret() << std::endl; 31 | std::cout << kpair.Public() << std::endl; 32 | 33 | kpair = KeyPair( 34 | "40C756697E6F60AC839FE53DD403F0B254D49A26243A196300CD4D515EE28062"); 35 | std::cout << kpair.Secret() << std::endl; 36 | // 1D26A437CB485CF1789FBBD8188D588DE8CE4FBD2F97629AB0319794B676519BD5587FC71CC14D30731C0C0CDAAF8DD04C088FEF475254B9731DC77094AB2B9B 37 | std::cout << kpair.Public() << std::endl; 38 | } 39 | 40 | } // namespace blocxxi::crypto 41 | ASAP_DIAGNOSTIC_POP 42 | -------------------------------------------------------------------------------- /crypto/test/main.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | // #include 8 | // #include 9 | 10 | #include 11 | 12 | auto main(int argc, char *argv[]) -> int { 13 | // asap::logging::Registry::instance().SetLogLevel( 14 | // asap::logging::Logger::Level::off); 15 | 16 | // asap::contract::PrepareForTesting(); 17 | 18 | testing::InitGoogleTest(&argc, argv); 19 | testing::InitGoogleMock(&argc, argv); 20 | return RUN_ALL_TESTS(); 21 | } 22 | -------------------------------------------------------------------------------- /data/REPLACE_WITH_REAL_DATA: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/data/REPLACE_WITH_REAL_DATA -------------------------------------------------------------------------------- /doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/doc/_static/favicon.ico -------------------------------------------------------------------------------- /doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/doc/_static/logo.png -------------------------------------------------------------------------------- /doc/changelog.md: -------------------------------------------------------------------------------- 1 | ```{include} ../CHANGELOG.md 2 | ``` 3 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 30 | 31 | 32 | 33 | 34 |

35 | LogoRedirecting you automatically in 38 | to the 39 | master documentation starting page... 40 |

41 |

Or you can instead go one of the modules documentation:

42 | 43 |

codec

44 |

crypto

45 |

nat

46 |

p2p

47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ############################################################ 10 | Blocxxi implementation of Kademlia DHT and Blockchain in C++ 11 | ############################################################ 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :titlesonly: 20 | :hidden: 21 | 22 | tools/index 23 | license 24 | changelog.md 25 | version 26 | 27 | Welcome! This is the documentation for the 28 | `blocxxi `_ |version| project. 29 | 30 | This project uses the `asap `_ integrated build 31 | system and follows its development workflow. 32 | 33 | Parts of the documentation 34 | ========================== 35 | 36 | :doc:`codec ` 37 | ------------------------ 38 | *start here to understand the codec utility module APIs.* 39 | 40 | :doc:`crypto ` 41 | -------------------------- 42 | *start here to understand the crypto utility module APIs.* 43 | 44 | :doc:`nat ` 45 | -------------------- 46 | *start here to understand the NAT and port mapping utility module APIs.* 47 | 48 | :doc:`p2p ` 49 | -------------------- 50 | *start here to understand the core of the blocxxi project: its implementation 51 | of a Kademlia based DHT.* 52 | 53 | `Developer Guides `_ 54 | -------------------------------------------------------------------------------------------------- 55 | *head over to the `asap` project documentation for detailed guides on how to 56 | build and maintain the different targets in this project.* 57 | 58 | :doc:`Project Tools ` 59 | ---------------------------------- 60 | *get an introduction to the programs and scripts under the `tools` folder, 61 | specifically made for the `asap` project. These can simplify recurring tasks and 62 | provide additional insights into the project, and sometimes examples of how to 63 | use the project artifacts.* 64 | 65 | Acknowledgements 66 | ================ 67 | 68 | .. figure:: https://executablebooks.org/en/latest/_static/logo-wide.svg 69 | :figclass: margin 70 | :alt: Executable Books Project 71 | :name: executable_book_logo 72 | 73 | This documentation uses the theme provided by the `Executable Books Project 74 | `_ Project. 75 | -------------------------------------------------------------------------------- /doc/license.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | License 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. include:: ../LICENSE 18 | 19 | -------------------------------------------------------------------------------- /doc/tools/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ############# 10 | Project Tools 11 | ############# 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :titlesonly: 20 | :hidden: 21 | 22 | The `tools` directory under the project root holds project-specific tools. 23 | Currently we have: 24 | 25 | * Project version info tool: a simple executable written as a C++ program, 26 | using the generated `version.h` include file to print the project meta-data 27 | defined in the project's cmake file. 28 | -------------------------------------------------------------------------------- /doc/version.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | Version 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | |release| 18 | -------------------------------------------------------------------------------- /doxygen/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 19 | 20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /nat/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files inside source tree 2 | doc/conf.py 3 | -------------------------------------------------------------------------------- /nat/README.md: -------------------------------------------------------------------------------- 1 | # NAT and UPNP utilities for blocxxi 2 | -------------------------------------------------------------------------------- /nat/config.cmake.in: -------------------------------------------------------------------------------- 1 | set(@MODULE_TARGET_NAME@_VERSION @META_MODULE_VERSION@) 2 | 3 | @PACKAGE_INIT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 6 | 7 | check_required_components(@MODULE_TARGET_NAME@) 8 | -------------------------------------------------------------------------------- /nat/config.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@ASAP_INSTALL_PREFIX_FULL_PATH@ 2 | libdir=${prefix}/@ASAP_INSTALL_LIB@ 3 | includedir=${prefix}/@ASAP_INSTALL_INCLUDE@ 4 | 5 | Name: @MODULE_TARGET_NAME@ 6 | URL: @META_MODULE_GITHUB_REPO@ 7 | Description: @META_MODULE_DESCRIPTION@ 8 | Version: @META_MODULE_VERSION@ 9 | Requires.private: asap::codec cryptopp-static Boost::endian 10 | Requires: asap::common 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} @MODULE_LINK_LIBS@ 13 | -------------------------------------------------------------------------------- /nat/doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/nat/doc/_static/favicon.ico -------------------------------------------------------------------------------- /nat/doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/nat/doc/_static/logo.png -------------------------------------------------------------------------------- /nat/doc/api.rst: -------------------------------------------------------------------------------- 1 | .. asap_common documentation master file, created by 2 | sphinx-quickstart on Tue Sep 11 14:51:58 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | API reference 7 | ============= 8 | 9 | .. |date| date:: 10 | 11 | Last Updated on |date| 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | :hidden: 16 | 17 | Port mapping 18 | -------------------------------------------------------------------------------- /nat/doc/api/nat.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | *********** 10 | CommandLine 11 | *********** 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. todo:: 18 | 19 | Documentation is to be completed 20 | -------------------------------------------------------------------------------- /nat/doc/conf.py.in: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'@META_PROJECT_NAME@/@META_MODULE_NAME@' 23 | copyright = u'2022, The Authors' 24 | 25 | # The short X.Y version 26 | version = u'@META_MODULE_VERSION@' 27 | 28 | rst_prolog = """ 29 | .. |version| replace:: {0} 30 | """.format(version) 31 | 32 | 33 | # -- General configuration --------------------------------------------------- 34 | 35 | # If your documentation needs a minimal Sphinx version, state it here. 36 | # 37 | # needs_sphinx = '1.0' 38 | 39 | # Add any Sphinx extension module names here, as strings. They can be 40 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 41 | # ones. 42 | extensions = [ 43 | 'sphinx.ext.intersphinx', 44 | 'sphinx.ext.todo', 45 | 'sphinx.ext.coverage', 46 | 'sphinx.ext.viewcode', 47 | 'sphinx-prompt', 48 | 'sphinx_copybutton', 49 | 'breathe', 50 | ] 51 | 52 | # Setup the breathe extension 53 | breathe_projects = { 54 | "@META_PROJECT_NAME@_@META_MODULE_NAME@": "@DOXYGEN_BUILD_DIR@/@META_PROJECT_NAME@_@META_MODULE_NAME@/xml" 55 | } 56 | breathe_default_project = "@META_PROJECT_NAME@_@META_MODULE_NAME@" 57 | 58 | # Tell sphinx what the primary language being documented is. 59 | primary_domain = 'cpp' 60 | 61 | # Tell sphinx what the pygments highlight language should be. 62 | highlight_language = 'cpp' 63 | 64 | # Add any paths that contain templates here, relative to this directory. 65 | templates_path = ['_templates'] 66 | 67 | # Add any paths that contain custom static files (such as style sheets) here, 68 | # relative to this directory. They are copied after the builtin static files, so 69 | # a file named "default.css" will overwrite the builtin "default.css". 70 | html_static_path = ["_static"] 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. This pattern also affects 74 | # html_static_path and html_extra_path. 75 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".sphinx"] 76 | 77 | # The suffix(es) of source filenames. 78 | # You can specify multiple suffix as a list of string: 79 | # 80 | # source_suffix = ['.rst', '.md'] 81 | source_suffix = '.rst' 82 | 83 | # The master toctree document. 84 | master_doc = 'index' 85 | 86 | # The language for content autogenerated by Sphinx. Refer to documentation 87 | # for a list of supported languages. 88 | # 89 | # This is also used if you do content translation via gettext catalogs. 90 | # Usually you set "language" from the command line for these cases. 91 | language = "en" 92 | 93 | # The name of the Pygments (syntax highlighting) style to use. 94 | pygments_style = 'sphinx' 95 | 96 | 97 | # -- Options for HTML output ------------------------------------------------- 98 | 99 | # The theme to use for HTML and HTML Help pages. See the documentation for 100 | # a list of builtin themes. 101 | # 102 | html_theme = 'sphinx_book_theme' 103 | 104 | html_title = u'Module: @META_MODULE_NAME@' 105 | html_logo = "_static/logo.png" 106 | html_favicon = "_static/favicon.ico" 107 | 108 | # If this is not None, a ‘Last updated on:’ timestamp is inserted at every page 109 | # bottom, using the given strftime() format. The empty string is equivalent to 110 | # '%b %d, %Y' (or a locale-dependent equivalent). 111 | html_last_updated_fmt = None 112 | 113 | html_theme_options = { 114 | "repository_url": '@META_GITHUB_REPO@', 115 | "use_repository_button": True, 116 | "use_issues_button": True, 117 | "use_edit_page_button": False, 118 | "use_download_button": True, 119 | "use_fullscreen_button": True, 120 | # We don't want the default navigation bar footer to be displayed on every 121 | # page. Mention of the book theme will be added in the home page. 122 | "extra_footer": "" 123 | } 124 | 125 | # -- Extension configuration ------------------------------------------------- 126 | 127 | # -- Options for intersphinx extension --------------------------------------- 128 | 129 | # Example configuration for intersphinx: refer to the Python standard library. 130 | #intersphinx_mapping = {'https://docs.python.org/': None} 131 | 132 | # -- Options for todo extension ---------------------------------------------- 133 | 134 | # If true, `todo` and `todoList` produce output, else they produce nothing. 135 | todo_include_todos = True 136 | -------------------------------------------------------------------------------- /nat/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ############################## 10 | Blocxxi NAT and UPNP utilities 11 | ############################## 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :hidden: 20 | 21 | API 22 | License 23 | Version 24 | 25 | Welcome! This is the documentation for the *nat* module, part of the *blocxxi* 26 | project. It contains port mapping and upnp utilities needed for the 27 | implementation of the DHT and blockchain. 28 | 29 | Parts of the documentation 30 | ========================== 31 | 32 | :doc:`API reference ` 33 | ------------------------------ 34 | *check this out to see the documentation of classes, macros, etc. offered by 35 | this module* 36 | -------------------------------------------------------------------------------- /nat/doc/license.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | License 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. include:: ../../LICENSE 18 | 19 | -------------------------------------------------------------------------------- /nat/doc/version.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | Version 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | |release| 18 | -------------------------------------------------------------------------------- /nat/include/nat/error.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | /*! 8 | * \file 9 | * 10 | * \brief Platform independent error codes for the nat module. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include 18 | 19 | namespace blocxxi::nat { 20 | 21 | /// All NAT module error codes. 22 | enum error_type { 23 | /// An unknown error. 24 | UNKNOWN_ERROR = 1, 25 | DISCOVERY_NOT_DONE, 26 | UPNP_COMMAND_ERROR 27 | }; 28 | 29 | /** 30 | * @brief Create a library error condition. 31 | * 32 | * @return The created error condition. 33 | */ 34 | BLOCXXI_NAT_API auto make_error_condition(error_type condition) 35 | -> std::error_condition; 36 | 37 | } // namespace blocxxi::nat 38 | 39 | template <> 40 | struct std::is_error_condition_enum : true_type {}; 41 | -------------------------------------------------------------------------------- /nat/include/nat/nat.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | /*! 8 | * \file 9 | * 10 | * \brief Port mapping and upnp support for blocxxi. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include // for unique_ptr 18 | 19 | #include 20 | 21 | namespace blocxxi::nat { 22 | 23 | /*! 24 | * @brief Implements the PortMapper interface for situations where no port 25 | * forwarding is needed. 26 | */ 27 | class BLOCXXI_NAT_API NoPortMapper : public PortMapper { 28 | public: 29 | /// @name Constructors etc. 30 | //@{ 31 | /*! 32 | * @brief Create a NoPortMapper instance and initialize it with the provided 33 | * external and internal addresses. 34 | * 35 | * This port mapper can be used for two scenarios: 36 | * - when we already have an external IP address (internal_ip is the same 37 | * than external_ip 38 | * - when port forwarding has already been statically setup at the gateway 39 | * (logically internal_ip and external_ip would be different) 40 | * 41 | * @param [in] external_ip the external (internet facing) IP address 42 | * @param [in] internal_ip the internal (LAN facing) IP address 43 | */ 44 | NoPortMapper(std::string const &external_ip, std::string const &internal_ip) 45 | : PortMapper(external_ip, internal_ip) { 46 | } 47 | /// Not copyable 48 | NoPortMapper(NoPortMapper const &) = delete; 49 | /// Not assignable 50 | auto operator=(NoPortMapper const &) -> NoPortMapper & = delete; 51 | /// Move copyable 52 | NoPortMapper(NoPortMapper &&) = default; 53 | /// Move assignable 54 | auto operator=(NoPortMapper &&) -> NoPortMapper & = default; 55 | /// Default 56 | ~NoPortMapper() override; 57 | //@} 58 | 59 | /// Does nothing. 60 | auto AddMapping(Mapping /*mapping*/, std::chrono::seconds /*lease_time*/) 61 | -> std::error_condition override { 62 | return {}; 63 | } 64 | 65 | /// Does nothing. 66 | auto DeleteMapping(Protocol /*protocol*/, unsigned /*external_port*/) 67 | -> std::error_condition override { 68 | return {}; 69 | } 70 | 71 | [[nodiscard]] auto MapperType() const -> std::string override { 72 | return "nomap"; 73 | } 74 | }; 75 | 76 | /*! 77 | * @brief Factory that creates and returns the suitable PortMapper instance to 78 | * meet the nat spec passed as an argument. 79 | * 80 | * The currently supported formats for the spec are: 81 | * - "upnp" : attempt to dicover the IGD using UPNP and dynamically setup 82 | * the port mapping and obtain the internal and external addresses through 83 | * UPNP. 84 | * - "extip:1.2.3.4" : Use the address provided as both the internal and 85 | * external address. No port mapping is required. 86 | * - "extip:1.2.3.4:192.168.1.42" : Use the first address as the external 87 | * address and the second one as the internal address. Assume port 88 | * forwarding has already been separately done. 89 | * - "" : attempt to discover the environment automatically. If UPNP is 90 | * available it will be used, otherwise some best effort heuristics will be 91 | * used to detect the available interfaces and select the most suitable 92 | * address to use. Preference goes for an external IP address, if not, it 93 | * goes for the most likely internal IP address to be associated with the main 94 | * interface. 95 | * 96 | * @param [in] spec a string specifying the requested nat environment as per 97 | * the format described in the details above. 98 | * @return a unique_ptr to a suitable PortMapper if one has been successfully 99 | * made; nullptr otherwise. 100 | */ 101 | BLOCXXI_NAT_API auto GetPortMapper(std::string const &spec) 102 | -> std::unique_ptr; 103 | 104 | } // namespace blocxxi::nat 105 | -------------------------------------------------------------------------------- /nat/include/nat/upnp_port_mapper.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include // for unique_ptr 12 | 13 | #include 14 | #include 15 | 16 | /// @name Forward declaration of types from miniupnp library. 17 | //@{ 18 | struct UPNPUrls; 19 | struct IGDdatas; 20 | //@} 21 | 22 | namespace blocxxi::nat { 23 | 24 | /*! 25 | * Implements port mapping following the UPNP method. 26 | */ 27 | class BLOCXXI_NAT_API UpnpPortMapper final 28 | : protected PortMapper, 29 | asap::logging::Loggable { 30 | public: 31 | /// The logger id used for logging within this class. 32 | static constexpr const char *LOGGER_NAME = "nat"; 33 | 34 | static auto Discover(std::chrono::milliseconds timeout) 35 | -> std::unique_ptr; 36 | 37 | /// @name Constructors etc. 38 | //@{ 39 | private: 40 | /// Default constructor 41 | UpnpPortMapper(); 42 | 43 | public: 44 | /// Not copyable 45 | UpnpPortMapper(UpnpPortMapper const &) = delete; 46 | /// Not assignable 47 | auto operator=(UpnpPortMapper const &) -> UpnpPortMapper & = delete; 48 | /// Move copyable 49 | UpnpPortMapper(UpnpPortMapper &&) noexcept; 50 | /// Move assignable 51 | auto operator=(UpnpPortMapper &&) noexcept -> UpnpPortMapper &; 52 | /// Destructor 53 | ~UpnpPortMapper() override; 54 | /// Swap 55 | void Swap(UpnpPortMapper &other) noexcept; 56 | //@} 57 | 58 | /// @copydoc PortMapper::AddMapping() 59 | auto AddMapping(Mapping mapping, std::chrono::seconds lease_time) 60 | -> std::error_condition override; 61 | 62 | /// @copydoc PortMapper::DeleteMapping() 63 | auto DeleteMapping(Protocol protocol, unsigned external_port) 64 | -> std::error_condition override; 65 | 66 | /// Always returns "upnp". 67 | [[nodiscard]] auto MapperType() const -> std::string override { 68 | return "upnp"; 69 | } 70 | 71 | private: 72 | /// miniupnpc data structure holding the UPNP device URLs 73 | struct UPNPUrls *urls_; 74 | /// miniupnpc data structure holding data about the UPNP device 75 | struct IGDdatas *data_; 76 | }; 77 | 78 | /*! 79 | * @brief Helper factory to synchronously create an instance of the 80 | * UpnpPortMapper. UPNP discovery will be done in a blocking mode. 81 | * 82 | * @param timeout maximum time in milliseconds to allow the UPNP discovery 83 | * to run before aborting it and returning with a failure. 84 | * @return a unique_ptr to a suitable PortMapper if one has been successfully 85 | * made; nullptr otherwise. 86 | */ 87 | inline auto DiscoverUPNP(std::chrono::milliseconds timeout) 88 | -> std::unique_ptr { 89 | return UpnpPortMapper::Discover(timeout); 90 | } 91 | 92 | } // namespace blocxxi::nat 93 | -------------------------------------------------------------------------------- /nat/src/error.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace blocxxi::nat { 12 | 13 | namespace detail { 14 | 15 | namespace { 16 | 17 | /// Error category implementation for the NAT system errors. 18 | struct nat_error_category : std::error_category { 19 | [[nodiscard]] auto name() const noexcept -> char const * override { 20 | return "nat"; 21 | } 22 | 23 | [[nodiscard]] auto message(int condition) const noexcept 24 | -> std::string override { 25 | switch (condition) { 26 | case UNKNOWN_ERROR: 27 | return "unknown error"; 28 | case DISCOVERY_NOT_DONE: 29 | return "UPNP discovery not done or did not produce any usable results"; 30 | case UPNP_COMMAND_ERROR: 31 | return "UPNP command issued to IGD returned an error"; 32 | default: 33 | return "unknown error code"; 34 | } 35 | } 36 | }; 37 | 38 | } // namespace 39 | 40 | inline auto error_category() -> std::error_category const & { 41 | static const nat_error_category category_{}; 42 | return category_; 43 | } 44 | 45 | inline auto make_error_code(error_type code) -> std::error_code { 46 | return std::error_code{static_cast(code), error_category()}; 47 | } 48 | 49 | } // namespace detail 50 | 51 | auto make_error_condition(error_type condition) -> std::error_condition { 52 | return std::error_condition{ 53 | static_cast(condition), detail::error_category()}; 54 | } 55 | 56 | } // namespace blocxxi::nat 57 | -------------------------------------------------------------------------------- /nat/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===------------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===------------------------------------------------------------------------===# 6 | 7 | # ============================================================================== 8 | # Build instructions 9 | # ============================================================================== 10 | 11 | set(MAIN_TEST_TARGET_NAME ${MODULE_TARGET_NAME}_test) 12 | 13 | asap_add_test( 14 | ${MAIN_TEST_TARGET_NAME} 15 | UNIT_TEST 16 | VALGRIND_MEMCHECK 17 | SRCS 18 | "portfwd_test.cpp" 19 | "main.cpp" 20 | LINK 21 | asap::logging 22 | blocxxi::nat 23 | gtest 24 | gmock 25 | COMMENT 26 | "Blocxxi nat unit tests") 27 | 28 | target_include_directories(${MAIN_TEST_TARGET_NAME} PRIVATE "../src") 29 | 30 | gtest_discover_tests(${MAIN_TEST_TARGET_NAME}) 31 | 32 | # Add support for (optional) code quality tools 33 | asap_add_sanitizers(${MAIN_TEST_TARGET_NAME}) 34 | swift_add_valgrind_massif(${MAIN_TEST_TARGET_NAME}) 35 | swift_add_valgrind_callgrind(${MAIN_TEST_TARGET_NAME}) 36 | -------------------------------------------------------------------------------- /nat/test/main.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | // #include 8 | // #include 9 | 10 | #include 11 | 12 | auto main(int argc, char *argv[]) -> int { 13 | // asap::logging::Registry::instance().SetLogLevel( 14 | // asap::logging::Logger::Level::off); 15 | 16 | // asap::contract::PrepareForTesting(); 17 | 18 | testing::InitGoogleTest(&argc, argv); 19 | testing::InitGoogleMock(&argc, argv); 20 | return RUN_ALL_TESTS(); 21 | } 22 | -------------------------------------------------------------------------------- /nat/test/portfwd_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | // Disable compiler and linter warnings originating from the unit test framework 15 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 16 | // usage must be preceded by a '// NOLINTNEXTLINE'. 17 | ASAP_DIAGNOSTIC_PUSH 18 | #if defined(ASAP_CLANG_VERSION) 19 | #pragma clang diagnostic ignored "-Wglobal-constructors" 20 | #endif 21 | 22 | using asap::logging::Registry; 23 | using blocxxi::nat::GetPortMapper; 24 | using blocxxi::nat::PortMapper; 25 | 26 | // NOLINTNEXTLINE 27 | TEST(PortFwdTest, Example) { 28 | auto &logger = Registry::GetLogger("testing"); 29 | 30 | const auto mapper = GetPortMapper(""); 31 | if (!mapper) { 32 | ASLOG_TO_LOGGER(logger, debug, "port forwarder init failed."); 33 | } else { 34 | ASLOG_TO_LOGGER(logger, info, "External IP : {}", mapper->ExternalIP()); 35 | ASLOG_TO_LOGGER(logger, info, "Internal IP : {}", mapper->InternalIP()); 36 | 37 | constexpr uint16_t c_port = 7272; 38 | if (mapper->AddMapping({PortMapper::Protocol::UDP, c_port, c_port, "test"}, 39 | std::chrono::seconds(0))) { 40 | ASLOG_TO_LOGGER(logger, debug, "port ({}) forwarding failed.", c_port); 41 | } else { 42 | if (mapper->DeleteMapping(PortMapper::Protocol::UDP, c_port)) { 43 | ASLOG_TO_LOGGER( 44 | logger, debug, "port ({}) forwarding removal failed.", c_port); 45 | } 46 | } 47 | } 48 | } 49 | ASAP_DIAGNOSTIC_POP 50 | -------------------------------------------------------------------------------- /p2p/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files inside source tree 2 | doc/conf.py 3 | -------------------------------------------------------------------------------- /p2p/config.cmake.in: -------------------------------------------------------------------------------- 1 | set(@MODULE_TARGET_NAME@_VERSION @META_MODULE_VERSION@) 2 | 3 | @PACKAGE_INIT@ 4 | 5 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") 6 | 7 | check_required_components(@MODULE_TARGET_NAME@) 8 | -------------------------------------------------------------------------------- /p2p/config.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@ASAP_INSTALL_PREFIX_FULL_PATH@ 2 | libdir=${prefix}/@ASAP_INSTALL_LIB@ 3 | includedir=${prefix}/@ASAP_INSTALL_INCLUDE@ 4 | 5 | Name: @MODULE_TARGET_NAME@ 6 | URL: @META_MODULE_GITHUB_REPO@ 7 | Description: @META_MODULE_DESCRIPTION@ 8 | Version: @META_MODULE_VERSION@ 9 | Requires.private: asap::codec cryptopp-static Boost::endian 10 | Requires: asap::common 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} @MODULE_LINK_LIBS@ 13 | -------------------------------------------------------------------------------- /p2p/doc/_static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/p2p/doc/_static/favicon.ico -------------------------------------------------------------------------------- /p2p/doc/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdes/blocxxi/715007c9ce5700c0a191dddc1fd077d4f2b8102a/p2p/doc/_static/logo.png -------------------------------------------------------------------------------- /p2p/doc/api.rst: -------------------------------------------------------------------------------- 1 | .. asap_common documentation master file, created by 2 | sphinx-quickstart on Tue Sep 11 14:51:58 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | API reference 7 | ============= 8 | 9 | .. |date| date:: 10 | 11 | Last Updated on |date| 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | :hidden: 16 | 17 | P2P 18 | -------------------------------------------------------------------------------- /p2p/doc/api/p2p.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | *********** 10 | CommandLine 11 | *********** 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. todo:: 18 | 19 | Documentation is to be completed 20 | -------------------------------------------------------------------------------- /p2p/doc/conf.py.in: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'@META_PROJECT_NAME@/@META_MODULE_NAME@' 23 | copyright = u'2022, The Authors' 24 | 25 | # The short X.Y version 26 | version = u'@META_MODULE_VERSION@' 27 | 28 | rst_prolog = """ 29 | .. |version| replace:: {0} 30 | """.format(version) 31 | 32 | 33 | # -- General configuration --------------------------------------------------- 34 | 35 | # If your documentation needs a minimal Sphinx version, state it here. 36 | # 37 | # needs_sphinx = '1.0' 38 | 39 | # Add any Sphinx extension module names here, as strings. They can be 40 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 41 | # ones. 42 | extensions = [ 43 | 'sphinx.ext.intersphinx', 44 | 'sphinx.ext.todo', 45 | 'sphinx.ext.coverage', 46 | 'sphinx.ext.viewcode', 47 | 'sphinx-prompt', 48 | 'sphinx_copybutton', 49 | 'breathe', 50 | ] 51 | 52 | # Setup the breathe extension 53 | breathe_projects = { 54 | "@META_PROJECT_NAME@_@META_MODULE_NAME@": "@DOXYGEN_BUILD_DIR@/@META_PROJECT_NAME@_@META_MODULE_NAME@/xml" 55 | } 56 | breathe_default_project = "@META_PROJECT_NAME@_@META_MODULE_NAME@" 57 | 58 | # Tell sphinx what the primary language being documented is. 59 | primary_domain = 'cpp' 60 | 61 | # Tell sphinx what the pygments highlight language should be. 62 | highlight_language = 'cpp' 63 | 64 | # Add any paths that contain templates here, relative to this directory. 65 | templates_path = ['_templates'] 66 | 67 | # Add any paths that contain custom static files (such as style sheets) here, 68 | # relative to this directory. They are copied after the builtin static files, so 69 | # a file named "default.css" will overwrite the builtin "default.css". 70 | html_static_path = ["_static"] 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. This pattern also affects 74 | # html_static_path and html_extra_path. 75 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".sphinx"] 76 | 77 | # The suffix(es) of source filenames. 78 | # You can specify multiple suffix as a list of string: 79 | # 80 | # source_suffix = ['.rst', '.md'] 81 | source_suffix = '.rst' 82 | 83 | # The master toctree document. 84 | master_doc = 'index' 85 | 86 | # The language for content autogenerated by Sphinx. Refer to documentation 87 | # for a list of supported languages. 88 | # 89 | # This is also used if you do content translation via gettext catalogs. 90 | # Usually you set "language" from the command line for these cases. 91 | language = "en" 92 | 93 | # The name of the Pygments (syntax highlighting) style to use. 94 | pygments_style = 'sphinx' 95 | 96 | 97 | # -- Options for HTML output ------------------------------------------------- 98 | 99 | # The theme to use for HTML and HTML Help pages. See the documentation for 100 | # a list of builtin themes. 101 | # 102 | html_theme = 'sphinx_book_theme' 103 | 104 | html_title = u'Module: @META_MODULE_NAME@' 105 | html_logo = "_static/logo.png" 106 | html_favicon = "_static/favicon.ico" 107 | 108 | # If this is not None, a ‘Last updated on:’ timestamp is inserted at every page 109 | # bottom, using the given strftime() format. The empty string is equivalent to 110 | # '%b %d, %Y' (or a locale-dependent equivalent). 111 | html_last_updated_fmt = None 112 | 113 | html_theme_options = { 114 | "repository_url": '@META_GITHUB_REPO@', 115 | "use_repository_button": True, 116 | "use_issues_button": True, 117 | "use_edit_page_button": False, 118 | "use_download_button": True, 119 | "use_fullscreen_button": True, 120 | # We don't want the default navigation bar footer to be displayed on every 121 | # page. Mention of the book theme will be added in the home page. 122 | "extra_footer": "" 123 | } 124 | 125 | # -- Extension configuration ------------------------------------------------- 126 | 127 | # -- Options for intersphinx extension --------------------------------------- 128 | 129 | # Example configuration for intersphinx: refer to the Python standard library. 130 | #intersphinx_mapping = {'https://docs.python.org/': None} 131 | 132 | # -- Options for todo extension ---------------------------------------------- 133 | 134 | # If true, `todo` and `todoList` produce output, else they produce nothing. 135 | todo_include_todos = True 136 | -------------------------------------------------------------------------------- /p2p/doc/index.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ############### 10 | Blocxxi P2P DHT 11 | ############### 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | :hidden: 20 | 21 | API 22 | License 23 | Version 24 | 25 | Welcome! This is the documentation for the *p2p* module, part of the *blocxxi* 26 | project. It contains the implementation of the DHT and blockchain. 27 | 28 | Parts of the documentation 29 | ========================== 30 | 31 | :doc:`API reference ` 32 | ------------------------------ 33 | *check this out to see the documentation of classes, macros, etc. offered by 34 | this module* 35 | -------------------------------------------------------------------------------- /p2p/doc/license.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | License 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | .. include:: ../../LICENSE 18 | 19 | -------------------------------------------------------------------------------- /p2p/doc/version.rst: -------------------------------------------------------------------------------- 1 | .. Structure conventions 2 | # with overline, for parts 3 | * with overline, for chapters 4 | = for sections 5 | - for subsections 6 | ^ for sub-subsections 7 | " for paragraphs 8 | 9 | ******* 10 | Version 11 | ******* 12 | 13 | .. |date| date:: 14 | 15 | Last Updated on |date| 16 | 17 | |release| 18 | -------------------------------------------------------------------------------- /p2p/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | add_subdirectory(simple-node) 8 | -------------------------------------------------------------------------------- /p2p/examples/simple-node/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===-----------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===-----------------------------------------------------------------------===# 6 | 7 | # ============================================================================== 8 | # Build instructions 9 | # ============================================================================== 10 | 11 | cpmaddpackage( 12 | NAME 13 | boost_algorithm 14 | GIT_TAG 15 | "boost-1.79.0" 16 | GITHUB_REPOSITORY 17 | boostorg/boost_algorithm 18 | OPTIONS 19 | "BUILD_TESTING OFF") 20 | 21 | cpmaddpackage( 22 | NAME 23 | boost_any 24 | GIT_TAG 25 | "boost-1.79.0" 26 | GITHUB_REPOSITORY 27 | boostorg/any 28 | OPTIONS 29 | "BUILD_TESTING OFF") 30 | 31 | cpmaddpackage( 32 | NAME 33 | boost_program_options 34 | GIT_TAG 35 | "boost-1.79.0" 36 | GITHUB_REPOSITORY 37 | boostorg/program_options 38 | OPTIONS 39 | "BUILD_TESTING OFF") 40 | 41 | cpmaddpackage( 42 | NAME 43 | boost_atomic 44 | GIT_TAG 45 | "boost-1.79.0" 46 | GITHUB_REPOSITORY 47 | boostorg/atomic 48 | OPTIONS 49 | "BUILD_TESTING OFF") 50 | 51 | cpmaddpackage( 52 | NAME 53 | boost_thread 54 | GIT_TAG 55 | "boost-1.79.0" 56 | GITHUB_REPOSITORY 57 | boostorg/thread 58 | OPTIONS 59 | "BUILD_TESTING OFF") 60 | 61 | asap_add_executable( 62 | simple-node 63 | WARNING 64 | SOURCES 65 | "main.cpp" 66 | "../utils/console_runner.cpp" 67 | "../utils/console_runner.h" 68 | "../utils/runner_base.h") 69 | target_link_libraries( 70 | simple-node 71 | PRIVATE asap::logging 72 | blocxxi::nat 73 | blocxxi::p2p 74 | Boost::algorithm 75 | Boost::program_options 76 | Boost::asio 77 | Boost::thread) 78 | -------------------------------------------------------------------------------- /p2p/examples/utils/console_runner.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include "console_runner.h" 8 | 9 | namespace blocxxi { 10 | 11 | ConsoleRunner::ConsoleRunner( 12 | RunnerBase::shutdown_function_type shutdown_function) 13 | : RunnerBase(std::move(shutdown_function)), io_context_(1), 14 | signals_(io_context_) { 15 | // Register to handle the signals that indicate when the server should exit. 16 | // It is safe to register for the same signal multiple times in a program, 17 | // provided all registration for the specified signal is made through Asio. 18 | signals_.add(SIGINT); 19 | signals_.add(SIGTERM); 20 | } 21 | ConsoleRunner::~ConsoleRunner() { 22 | if (!io_context_.stopped()) { 23 | io_context_.stop(); 24 | } 25 | } 26 | 27 | void ConsoleRunner::Run() { 28 | signals_.async_wait([this](boost::system::error_code /*ec*/, int /*signo*/) { 29 | ASLOG(info, "Signal caught"); 30 | // The server is stopped by cancelling all outstanding asynchronous 31 | // operations. 32 | CallShutdownFunction(); 33 | // Once all operations have finished the io_context::run() call will 34 | // exit. 35 | io_context_.stop(); 36 | }); 37 | io_context_.run(); 38 | } 39 | 40 | } // namespace blocxxi 41 | -------------------------------------------------------------------------------- /p2p/examples/utils/console_runner.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include "./runner_base.h" 10 | 11 | #include 12 | 13 | namespace blocxxi { 14 | 15 | class ConsoleRunner : public RunnerBase { 16 | public: 17 | explicit ConsoleRunner(shutdown_function_type shutdown_function); 18 | 19 | ~ConsoleRunner() override; 20 | ConsoleRunner(const ConsoleRunner &) = delete; 21 | auto operator=(const ConsoleRunner &) -> ConsoleRunner & = delete; 22 | 23 | ConsoleRunner(ConsoleRunner &&) = delete; 24 | auto operator=(ConsoleRunner &&) -> ConsoleRunner & = delete; 25 | 26 | void Run() override; 27 | 28 | private: 29 | boost::asio::io_context io_context_; 30 | /// The signal_set is used to register for process termination notifications. 31 | boost::asio::signal_set signals_; 32 | }; 33 | 34 | } // namespace blocxxi 35 | -------------------------------------------------------------------------------- /p2p/examples/utils/runner_base.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include // for std::function 10 | #include // for std::move 11 | 12 | #include 13 | 14 | namespace blocxxi { 15 | 16 | class RunnerBase : public asap::logging::Loggable { 17 | public: 18 | /// The logger id used for logging within this class. 19 | static constexpr const char *LOGGER_NAME = "simple-node"; 20 | 21 | using shutdown_function_type = std::function; 22 | 23 | explicit RunnerBase(shutdown_function_type func) 24 | : shutdown_function_(std::move(func)) { 25 | } 26 | 27 | virtual ~RunnerBase() = default; 28 | 29 | RunnerBase(const RunnerBase &) = delete; 30 | auto operator=(const RunnerBase &) -> RunnerBase & = delete; 31 | 32 | RunnerBase(RunnerBase &&) = delete; 33 | auto operator=(RunnerBase &&) -> RunnerBase & = delete; 34 | 35 | virtual void Run() = 0; 36 | 37 | protected: 38 | void CallShutdownFunction() const { 39 | shutdown_function_(); 40 | } 41 | 42 | private: 43 | shutdown_function_type shutdown_function_; 44 | }; 45 | 46 | } // namespace blocxxi 47 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/boost_asio.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | ASAP_DIAGNOSTIC_PUSH 13 | #if defined(ASAP_GNUC_VERSION) 14 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" 15 | #pragma GCC diagnostic ignored "-Woverloaded-virtual" 16 | #pragma GCC diagnostic ignored "-Wsign-conversion" 17 | #pragma GCC diagnostic ignored "-Wold-style-cast" 18 | #pragma GCC diagnostic ignored "-Wredundant-decls" 19 | #endif 20 | #if defined(ASAP_CLANG_VERSION) 21 | #pragma clang diagnostic ignored "-Wcovered-switch-default" 22 | #pragma clang diagnostic ignored "-Wdeprecated" 23 | #pragma clang diagnostic ignored "-Wdocumentation" 24 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 25 | #pragma clang diagnostic ignored "-Wglobal-constructors" 26 | #pragma clang diagnostic ignored "-Wimplicit-fallthrough" 27 | #pragma clang diagnostic ignored "-Wmissing-noreturn" 28 | #pragma clang diagnostic ignored "-Wshadow" 29 | #pragma clang diagnostic ignored "-Wshorten-64-to-32" 30 | #pragma clang diagnostic ignored "-Wsuggest-destructor-override" 31 | #pragma clang diagnostic ignored "-Wsuggest-override" 32 | #pragma clang diagnostic ignored "-Wswitch-enum" 33 | #pragma clang diagnostic ignored "-Wundef" 34 | #pragma clang diagnostic ignored "-Wweak-vtables" 35 | #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" 36 | #endif 37 | #if defined(ASAP_CLANG_VERSION) && \ 38 | ASAP_HAS_WARNING("-Wreserved-macro-identifier") 39 | #pragma clang diagnostic ignored "-Wreserved-macro-identifier" 40 | #endif 41 | #if defined(ASAP_GNUC_VERSION) 42 | #pragma GCC diagnostic ignored "-Wconversion" 43 | #pragma GCC diagnostic ignored "-Wswitch-enum" 44 | #endif 45 | #include 46 | ASAP_DIAGNOSTIC_POP 47 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/buffer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include // for gsl::span 10 | 11 | #include // for std::uint8_t 12 | #include // for std::vector 13 | 14 | namespace blocxxi::p2p::kademlia { 15 | 16 | /// Represents an output buffer to which headers and message bodies can be 17 | /// serialized. Whatever type is used, it needs to be able to expand as needed. 18 | using Buffer = std::vector; 19 | 20 | /// Represents a read-only view over the input buffer used to deserialize 21 | /// headers and message bodies. 22 | using BufferReader = gsl::span; 23 | 24 | } // namespace blocxxi::p2p::kademlia 25 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/detail/error_impl.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | // #include 13 | 14 | namespace blocxxi::p2p::kademlia::detail { 15 | 16 | BLOCXXI_P2P_API auto error_category() -> std::error_category const &; 17 | 18 | BLOCXXI_P2P_API auto make_error_code(error_type code) -> std::error_code; 19 | 20 | // TODO(Abdessattar): permanently delete this 21 | // inline auto BoostToStdError(boost::system::error_code const &failure) 22 | // -> std::error_code { 23 | // if (failure.category() == boost::system::generic_category()) { 24 | // return std::error_code{failure.value(), std::generic_category()}; 25 | // } 26 | // if (failure.category() == boost::system::system_category()) { 27 | // return std::error_code{failure.value(), std::system_category()}; 28 | // } 29 | // return make_error_code(UNKNOWN_ERROR); 30 | // } 31 | 32 | } // namespace blocxxi::p2p::kademlia::detail 33 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/detail/ping_node_task.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace blocxxi::p2p::kademlia::detail { 17 | 18 | /// 19 | template 21 | class PingNodeTask final 22 | : protected asap::logging::Loggable< 23 | PingNodeTask> { 24 | public: 25 | /// The logger id used for logging within this class. 26 | static constexpr const char *LOGGER_NAME = "p2p-kademlia"; 27 | 28 | // We need to import the internal logger retrieval method symbol in this 29 | // context to avoid g++ complaining about the method not being declared before 30 | // being used. THis is due to the fact that the current class is a template 31 | // class and that method does not take any template argument that will enable 32 | // the compiler to resolve it unambiguously. 33 | using asap::logging::Loggable>::internal_log_do_not_use_read_comment; 35 | 36 | using NetworkType = TNetwork; 37 | using RoutingTableType = TRoutingTable; 38 | using EndpointType = typename NetworkType::EndpointType; 39 | using OnCompleteCallbackType = TOnCompleteCallback; 40 | 41 | /** 42 | * 43 | */ 44 | static void Start(Node const &node, NetworkType &network, 45 | RoutingTableType &routing_table, OnCompleteCallbackType on_complete, 46 | std::string const &task_name) { 47 | ASLOG(debug, "[{}] starting a new task", task_name); 48 | 49 | std::shared_ptr task; 50 | task.reset( 51 | new PingNodeTask(node, network, routing_table, on_complete, task_name)); 52 | 53 | SendPingRequest(task); 54 | } 55 | 56 | constexpr static char const *TASK_NAME = "PING_NODE"; 57 | 58 | /// Get a string representing the task for debugging 59 | auto Name() const -> std::string { 60 | return std::string("[").append(task_name_).append("]"); 61 | } 62 | 63 | private: 64 | PingNodeTask(Node const &node, NetworkType &network, 65 | RoutingTableType &routing_table, OnCompleteCallbackType on_complete, 66 | std::string task_name) 67 | : task_name_(std::move(task_name)), peer_(node), network_(network), 68 | routing_table_(routing_table), on_complete_(on_complete) { 69 | ASLOG(debug, "{} ping node task peer={}", this->Name(), node.ToString()); 70 | } 71 | 72 | /** 73 | * 74 | */ 75 | static void SendPingRequest(std::shared_ptr task) { 76 | auto on_message_received = [task](EndpointType const &sender, 77 | Header const & /*header*/, 78 | BufferReader const & /*buffer*/) { 79 | // Nothing special to do - the peer is alive 80 | ASLOG(debug, "{} received ping response peer={}", task->Name(), 81 | sender.ToString()); 82 | task->on_complete_(); 83 | }; 84 | 85 | auto on_error = [task](std::error_code const &) { 86 | ASLOG(debug, "{} ping failed {}", task->Name(), task->peer_.ToString()); 87 | // Also increment the number of failed requests in the routing table node 88 | auto evicted = task->routing_table_.PeerTimedOut(task->peer_); 89 | if (!evicted) { 90 | // Ping again 91 | SendPingRequest(task); 92 | } 93 | }; 94 | 95 | task->network_.SendConvRequest(Header::MessageType::PING_REQUEST, 96 | task->peer_.Endpoint(), REQUEST_TIMEOUT, on_message_received, on_error); 97 | } 98 | 99 | std::string task_name_; 100 | Node peer_; 101 | NetworkType &network_; 102 | RoutingTableType &routing_table_; 103 | OnCompleteCallbackType on_complete_; 104 | }; 105 | 106 | /** 107 | * 108 | */ 109 | template 111 | void StartPingNodeTask(Node const &node, TNetwork &network, 112 | TRoutingTable &routing_table, TOnCompleteCallback on_complete, 113 | std::string const &task_name = 114 | PingNodeTask::TASK_NAME) { 115 | 116 | using TaskType = PingNodeTask; 117 | TaskType::Start(node, network, routing_table, on_complete, task_name); 118 | } 119 | 120 | } // namespace blocxxi::p2p::kademlia::detail 121 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/endpoint.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | namespace blocxxi::p2p::kademlia { 16 | 17 | class BLOCXXI_P2P_API IpEndpoint final { 18 | public: 19 | using AddressType = boost::asio::ip::address; 20 | 21 | IpEndpoint() = default; 22 | IpEndpoint(AddressType address, unsigned short port) 23 | : address_(std::move(address)), port_(port) { 24 | } 25 | 26 | IpEndpoint(const std::string &address, unsigned short port) 27 | : address_(boost::asio::ip::address::from_string(address)), port_(port) { 28 | } 29 | 30 | IpEndpoint(IpEndpoint const &) = default; 31 | auto operator=(IpEndpoint const &) -> IpEndpoint & = default; 32 | 33 | IpEndpoint(IpEndpoint &&) = default; 34 | auto operator=(IpEndpoint &&) -> IpEndpoint & = default; 35 | 36 | ~IpEndpoint() = default; 37 | 38 | [[nodiscard]] auto Address() const -> AddressType const & { 39 | return address_; 40 | } 41 | void Address(const AddressType &address) { 42 | address_ = address; 43 | } 44 | [[nodiscard]] auto Port() const -> std::uint16_t { 45 | return port_; 46 | } 47 | void Port(std::uint16_t port) { 48 | port_ = port; 49 | } 50 | 51 | [[nodiscard]] auto ToString() const -> std::string { 52 | return address_.to_string() + ":" + 53 | std::to_string(static_cast(port_)); 54 | } 55 | 56 | boost::asio::ip::address address_; 57 | std::uint16_t port_{0}; 58 | }; 59 | 60 | inline auto operator==(IpEndpoint const &lhs, IpEndpoint const &rhs) -> bool { 61 | return lhs.address_ == rhs.address_ && lhs.port_ == rhs.port_; 62 | } 63 | 64 | inline auto operator!=(IpEndpoint const &lhs, IpEndpoint const &rhs) -> bool { 65 | return !(lhs == rhs); 66 | } 67 | 68 | inline auto operator<<(std::ostream &out, IpEndpoint const &endpoint) 69 | -> std::ostream & { 70 | out << endpoint.Address().to_string() << ":" << endpoint.Port(); 71 | return out; 72 | } 73 | 74 | } // namespace blocxxi::p2p::kademlia 75 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/error.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace blocxxi::p2p::kademlia { 14 | 15 | /// This enum list all library specific errors. 16 | enum error_type { 17 | /// An unknown error. 18 | UNKNOWN_ERROR = 1, 19 | /// The session failed to contact a valid peer upon creation. 20 | INITIAL_PEER_FAILED_TO_RESPOND, 21 | /// An unexpected response has been received. 22 | UNASSOCIATED_MESSAGE_ID, 23 | /// The provided IPv4 address is invalid. 24 | INVALID_IPV4_ADDRESS, 25 | /// The provided IPv6 address is invalid. 26 | INVALID_IPV6_ADDRESS, 27 | /// The value associated with the requested key has not been found. 28 | VALUE_NOT_FOUND, 29 | /// The internal timer failed to tick. 30 | TIMER_MALFUNCTION 31 | }; 32 | 33 | /** 34 | * @brief Create a library error condition. 35 | * 36 | * @return The created error condition. 37 | */ 38 | BLOCXXI_P2P_API auto make_error_condition(error_type condition) 39 | -> std::error_condition; 40 | 41 | } // namespace blocxxi::p2p::kademlia 42 | 43 | template <> 44 | struct std::is_error_condition_enum 45 | : true_type {}; 46 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/key.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | namespace blocxxi::p2p::kademlia { 12 | 13 | /// Hash 160 key type used for value keys and response correlation id. 14 | using KeyType = blocxxi::crypto::Hash160; 15 | 16 | } // namespace blocxxi::p2p::kademlia 17 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/message_serializer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | namespace blocxxi::p2p::kademlia { 13 | 14 | /*! 15 | * @brief Offers serialization helpers for the Kademlia protocol messages. 16 | */ 17 | class BLOCXXI_P2P_API MessageSerializer { 18 | public: 19 | /// @name Constructors etc. 20 | //@{ 21 | /*! 22 | * @brief Create a MessageSerializer instance which will use the given node 23 | * id as this node's id during message header serialization. 24 | * 25 | * @param my_id this node's id, which will be automatically added to headers. 26 | */ 27 | explicit MessageSerializer(Node::IdType my_id); 28 | 29 | /// Not copyable 30 | MessageSerializer(MessageSerializer const &) = delete; 31 | /// Not copyable 32 | auto operator=(MessageSerializer const &) -> MessageSerializer & = delete; 33 | 34 | /// Movable (default) 35 | MessageSerializer(MessageSerializer &&) noexcept = default; 36 | /// Movable (default) 37 | auto operator=(MessageSerializer &&) noexcept 38 | -> MessageSerializer & = default; 39 | 40 | ~MessageSerializer() = default; 41 | //@} 42 | 43 | /*! 44 | * Serialize a Kademlia protocol message body. 45 | * 46 | * @tparam TMessage type of messages to serialize. 47 | * @param message the message body to serialize. 48 | * @param token the random correlation token to be used in the header. 49 | * @return a buffer containing the serialized message body. 50 | */ 51 | template 52 | auto Serialize(TMessage const &message, blocxxi::crypto::Hash160 const &token) 53 | -> Buffer; 54 | 55 | /*! 56 | * Serialize a Kademlia protocol message header for the given message type. 57 | * 58 | * @param type message type. 59 | * @param token the random correlation token to be used in the header. 60 | * @return a buffer containing the serialized message header. 61 | */ 62 | auto Serialize(Header::MessageType const &type, 63 | blocxxi::crypto::Hash160 const &token) -> Buffer; 64 | 65 | private: 66 | /*! 67 | * Make a header for the given message type and using the random correlation 68 | * token. 69 | * 70 | * @param type message type. 71 | * @param token the random correlation token to be used in the header. 72 | * @return a fully populated Header object. 73 | */ 74 | auto MakeHeader(Header::MessageType const &type, 75 | blocxxi::crypto::Hash160 const &token) -> Header; 76 | 77 | /// This node's id, used in serialized headers. 78 | Node::IdType my_id_; 79 | }; 80 | 81 | template 82 | inline auto MessageSerializer::Serialize( 83 | TMessage const &message, blocxxi::crypto::Hash160 const &token) -> Buffer { 84 | auto const type = MessageTraits::TYPE_ID; 85 | auto const header = MakeHeader(type, token); 86 | 87 | Buffer buffer; 88 | blocxxi::p2p::kademlia::Serialize(header, buffer); 89 | blocxxi::p2p::kademlia::Serialize(message, buffer); 90 | 91 | return buffer; 92 | } 93 | 94 | } // namespace blocxxi::p2p::kademlia 95 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/parameters.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include // for timeout value 10 | 11 | // TODO:(Abdessattar) rename constants to c_... 12 | namespace blocxxi::p2p::kademlia { 13 | 14 | constexpr unsigned int DEPTH_B = 5; 15 | constexpr unsigned int CONCURRENCY_K = 8; 16 | constexpr unsigned int PARALLELISM_ALPHA = 3; 17 | constexpr unsigned int KEYSIZE_BITS = 160; 18 | constexpr unsigned int REDUNDANT_SAVE_COUNT = 3; 19 | 20 | constexpr unsigned int NODE_FAILED_COMMS_BEFORE_STALE = 2; 21 | constexpr auto NODE_INACTIVE_TIME_BEFORE_QUESTIONABLE = 22 | std::chrono::minutes(15); 23 | 24 | constexpr auto PERIODIC_REFRESH_TIMER = std::chrono::seconds(6); 25 | constexpr auto BUCKET_INACTIVE_TIME_BEFORE_REFRESH = std::chrono::seconds(1200); 26 | constexpr auto REQUEST_TIMEOUT = std::chrono::seconds(2); 27 | 28 | } // namespace blocxxi::p2p::kademlia 29 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/session.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | namespace blocxxi::p2p::kademlia { 18 | 19 | template 20 | class Session final : asap::logging::Loggable> { 21 | public: 22 | /// The logger id used for logging within this class. 23 | static constexpr const char *LOGGER_NAME = "p2p-kademlia"; 24 | 25 | // We need to import the internal logger retrieval method symbol in this 26 | // context to avoid g++ complaining about the method not being declared before 27 | // being used. THis is due to the fact that the current class is a template 28 | // class and that method does not take any template argument that will enable 29 | // the compiler to resolve it unambiguously. 30 | using asap::logging::Loggable< 31 | Session>::internal_log_do_not_use_read_comment; 32 | 33 | using EngineType = TEngine; 34 | /// 35 | using DataType = std::vector; 36 | /// 37 | using StoreHandlerType = std::function; 38 | /// 39 | using LoadHandlerType = 40 | std::function; 41 | 42 | explicit Session(boost::asio::io_context &io_context, EngineType &&engine) 43 | : io_context_(io_context), engine_(std::move(engine)) { 44 | ASLOG(debug, "Creating Session DONE"); 45 | } 46 | 47 | Session(Session const &) = delete; 48 | auto operator=(Session const &) -> Session & = delete; 49 | 50 | Session(Session &&) noexcept = default; 51 | auto operator=(Session &&) noexcept -> Session & = default; 52 | 53 | ~Session() { 54 | ASLOG(debug, "Destroy Session"); 55 | } 56 | 57 | auto GetEngine() const -> EngineType const & { 58 | return engine_; 59 | } 60 | 61 | void Start() { 62 | ASLOG(debug, "Session Start"); 63 | engine_.Start(); 64 | } 65 | 66 | /* void RunOne() { 67 | engine_.RunOne(); 68 | } 69 | 70 | void RunAll() { 71 | engine_.RunAll(); 72 | } 73 | */ 74 | void Stop() { 75 | ASLOG(debug, "Session Stop"); 76 | engine_.Stop(); 77 | } 78 | 79 | void StoreValue( 80 | KeyType const &key, DataType const &data, StoreHandlerType handler) { 81 | engine_.AsyncStoreValue(key, data, handler); 82 | } 83 | 84 | void FindValue(KeyType const &key, LoadHandlerType handler) { 85 | engine_.AsyncFindValue(key, handler); 86 | } 87 | 88 | private: 89 | /// 90 | boost::asio::io_context &io_context_; 91 | /// 92 | EngineType engine_; 93 | }; 94 | 95 | } // namespace blocxxi::p2p::kademlia 96 | -------------------------------------------------------------------------------- /p2p/include/p2p/kademlia/value_store.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace blocxxi::p2p::kademlia { 15 | 16 | template struct ValueStoreKeyHasher { 17 | using ArgumentType = TContainer; 18 | using ResultType = std::size_t; 19 | 20 | auto operator()(ArgumentType const &key) const -> ResultType { 21 | return boost::hash_range(key.begin(), key.end()); 22 | } 23 | }; 24 | 25 | // TODO(Abdessattar): Republish key-value pairs after once per hour 26 | template 27 | using ValueStore = std::unordered_map>; 28 | 29 | } // namespace blocxxi::p2p::kademlia 30 | -------------------------------------------------------------------------------- /p2p/src/kademlia/error.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | namespace blocxxi::p2p::kademlia { 10 | 11 | auto make_error_condition(error_type condition) -> std::error_condition { 12 | return std::error_condition{ 13 | static_cast(condition), detail::error_category()}; 14 | } 15 | 16 | } // namespace blocxxi::p2p::kademlia 17 | -------------------------------------------------------------------------------- /p2p/src/kademlia/error_impl.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace blocxxi::p2p::kademlia::detail { 12 | 13 | namespace { 14 | 15 | /// Error category implementation for the kademlia system errors. 16 | struct kademlia_error_category : std::error_category { 17 | [[nodiscard]] auto name() const noexcept -> char const * override { 18 | return "kademlia"; 19 | } 20 | 21 | [[nodiscard]] auto message(int condition) const noexcept 22 | -> std::string override { 23 | switch (condition) { 24 | case INITIAL_PEER_FAILED_TO_RESPOND: 25 | return "initial peer failed to respond"; 26 | case UNASSOCIATED_MESSAGE_ID: 27 | return "unassociated message id"; 28 | case INVALID_IPV4_ADDRESS: 29 | return "invalid IPv4 address"; 30 | case INVALID_IPV6_ADDRESS: 31 | return "invalid IPv6 address"; 32 | case VALUE_NOT_FOUND: 33 | return "value not found"; 34 | case TIMER_MALFUNCTION: 35 | return "timer malfunction"; 36 | default: 37 | return "unknown error"; 38 | } 39 | } 40 | }; 41 | 42 | } // namespace 43 | 44 | auto error_category() -> std::error_category const & { 45 | static const kademlia_error_category category_{}; 46 | return category_; 47 | } 48 | 49 | auto make_error_code(error_type code) -> std::error_code { 50 | return std::error_code{static_cast(code), error_category()}; 51 | } 52 | 53 | } // namespace blocxxi::p2p::kademlia::detail 54 | -------------------------------------------------------------------------------- /p2p/src/kademlia/message_serializer.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | namespace blocxxi::p2p::kademlia { 10 | 11 | MessageSerializer::MessageSerializer(Node::IdType my_id) 12 | : my_id_(std::move(my_id)) { 13 | } 14 | 15 | auto MessageSerializer::MakeHeader(Header::MessageType const &type, 16 | blocxxi::crypto::Hash160 const &token) -> Header { 17 | return Header{Header::Version::V1, type, my_id_, token}; 18 | } 19 | 20 | auto MessageSerializer::Serialize(Header::MessageType const &type, 21 | blocxxi::crypto::Hash160 const &token) -> Buffer { 22 | auto const header = MakeHeader(type, token); 23 | 24 | Buffer buffer; 25 | blocxxi::p2p::kademlia::Serialize(header, buffer); 26 | 27 | return buffer; 28 | } 29 | 30 | } // namespace blocxxi::p2p::kademlia 31 | -------------------------------------------------------------------------------- /p2p/src/kademlia/node.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | namespace blocxxi::p2p::kademlia { 10 | 11 | namespace { 12 | // table of leading zero counts for bytes [0..255] 13 | constexpr unsigned int lzcount[256]{ 14 | // clang-format off 15 | 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 16 | 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 18 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | // clang-format on 27 | }; 28 | } // anonymous namespace 29 | 30 | // Find the number of common prefix bits in the id of the nodes within the given 31 | // iterator range. 32 | inline auto SharedPrefixSize(const Node &a, const Node &b) -> unsigned int { 33 | auto lz = 0U; 34 | auto ida = a.Id(); 35 | auto idb = b.Id(); 36 | constexpr auto size = Node::IdType::Size(); 37 | for (auto i = 0U; i < size; ++i) { 38 | const auto x = ida[i] ^ idb[i]; 39 | if (x == 0) { 40 | lz += 8; 41 | } else { 42 | lz += lzcount[x]; 43 | break; 44 | } 45 | } 46 | return lz; 47 | } 48 | 49 | auto Node::LogDistanceTo(blocxxi::crypto::Hash160 const &hash) const -> size_t { 50 | const auto dist = DistanceTo(hash); 51 | const auto lzc = dist.LeadingZeroBits(); 52 | return (Node::IdType::BitSize() - 1 - lzc); 53 | } 54 | 55 | auto Node::ToString() const -> std::string const & { 56 | // TODO(Abdessattar): use std::optional instead of a pointer 57 | if (url_) { 58 | return *url_; 59 | } 60 | 61 | url_ = new std::string(); 62 | url_->append("knode://") 63 | .append(node_id_.ToHex()) 64 | .append("@") 65 | .append(endpoint_.Address().to_string()) 66 | .append(":") 67 | .append(std::to_string(static_cast(endpoint_.Port()))); 68 | return *url_; 69 | } 70 | 71 | auto Node::FromUrlString(const std::string &url) -> Node { 72 | // Validate the URL string and extract the different parts out of it 73 | auto pos = url.find("://"); 74 | if (pos != std::string::npos) { 75 | size_t start = 0; 76 | const auto url_type = url.substr(start, pos - start); 77 | if (url_type == "knode") { 78 | start = pos + 3; 79 | pos = url.find('@', start); 80 | if (pos != std::string::npos) { 81 | const auto id = url.substr(start, pos - start); 82 | if (id.length() == 40) { 83 | start = pos + 1; 84 | pos = url.rfind(':'); 85 | if (pos != std::string::npos) { 86 | auto address = url.substr(start, pos - start); 87 | const auto port = url.substr(pos + 1); 88 | 89 | return {IdType::FromHex(id), address, 90 | static_cast(std::stoi(port))}; 91 | } 92 | } 93 | } 94 | } 95 | } 96 | throw std::invalid_argument("bad node url: " + url); 97 | } 98 | 99 | } // namespace blocxxi::p2p::kademlia 100 | -------------------------------------------------------------------------------- /p2p/src/kademlia/timer.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace blocxxi::p2p::kademlia { 12 | 13 | void Timer::ScheduleNextTick(TimePointType const &expiration_time) { 14 | // This will cancel any pending task. 15 | timer_.expires_at(expiration_time); 16 | 17 | timer_.async_wait([this](boost::system::error_code const &failure) { 18 | // If the deadline timer has been cancelled, just stop right there. 19 | if (failure == boost::asio::error::operation_aborted) { 20 | return; 21 | } 22 | 23 | if (failure) { 24 | throw std::system_error{detail::make_error_code(TIMER_MALFUNCTION)}; 25 | } 26 | 27 | // Call the user callbacks. 28 | // The callbacks to execute are the first n callbacks expiring at a time 29 | // before now(). 30 | const auto begin = timeouts_.begin(); 31 | const auto end = timeouts_.upper_bound(ClockType::now()); 32 | for (auto entry = begin; entry != end; ++entry) { 33 | ASLOG(trace, "invoke callback for timer expiring at {}", 34 | entry->first.time_since_epoch().count()); 35 | entry->second(); 36 | } 37 | 38 | // And remove the timeout. 39 | auto count = std::distance(begin, end); 40 | timeouts_.erase(begin, end); 41 | 42 | ASLOG(debug, "remove {} expired timer(s), remaining {}", count, 43 | timeouts_.size()); 44 | 45 | // If there is a remaining timeout, schedule it. 46 | if (!timeouts_.empty()) { 47 | ScheduleNextTick(timeouts_.begin()->first); 48 | } else { 49 | ASLOG(debug, "no more timers to schedule"); 50 | } 51 | }); 52 | } 53 | 54 | } // namespace blocxxi::p2p::kademlia 55 | -------------------------------------------------------------------------------- /p2p/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===------------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===------------------------------------------------------------------------===# 6 | 7 | # ============================================================================== 8 | # Build instructions 9 | # ============================================================================== 10 | 11 | set(MAIN_TEST_TARGET_NAME ${MODULE_TARGET_NAME}_test) 12 | 13 | asap_add_test( 14 | ${MAIN_TEST_TARGET_NAME} 15 | UNIT_TEST 16 | VALGRIND_MEMCHECK 17 | SRCS 18 | "node_test.cpp" 19 | "kbucket_test.cpp" 20 | "routingtable_test.cpp" 21 | "channel_test.cpp" 22 | "network_test.cpp" 23 | "timer_test.cpp" 24 | "response_dispatcher_test.cpp" 25 | "main.cpp" 26 | LINK 27 | blocxxi::p2p 28 | Boost::asio 29 | Boost::multiprecision 30 | gtest 31 | gmock 32 | COMMENT 33 | "Blocxxi nat unit tests") 34 | 35 | target_include_directories(${MAIN_TEST_TARGET_NAME} PRIVATE "../src") 36 | 37 | gtest_discover_tests(${MAIN_TEST_TARGET_NAME}) 38 | 39 | # Add support for (optional) code quality tools 40 | asap_add_sanitizers(${MAIN_TEST_TARGET_NAME}) 41 | swift_add_valgrind_massif(${MAIN_TEST_TARGET_NAME}) 42 | swift_add_valgrind_callgrind(${MAIN_TEST_TARGET_NAME}) 43 | -------------------------------------------------------------------------------- /p2p/test/channel_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | 13 | // Disable compiler and linter warnings originating from the unit test framework 14 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 15 | // usage must be preceded by a '// NOLINTNEXTLINE'. 16 | ASAP_DIAGNOSTIC_PUSH 17 | #if defined(ASAP_CLANG_VERSION) 18 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 19 | #pragma clang diagnostic ignored "-Wglobal-constructors" 20 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 21 | #pragma clang diagnostic ignored "-Wweak-vtables" 22 | #endif 23 | 24 | using namespace boost::asio; 25 | using namespace boost::asio::ip; 26 | 27 | using UdpSocket = udp::socket; 28 | 29 | namespace blocxxi::p2p::kademlia { 30 | 31 | // NOLINTNEXTLINE 32 | TEST(ChannelTest, CreateV4) { 33 | boost::asio::io_context io_context; 34 | // NOLINTNEXTLINE 35 | ASSERT_NO_THROW(AsyncUdpChannel::ipv4(io_context, "127.0.0.1", "30000")); 36 | 37 | // NOLINTNEXTLINE 38 | ASSERT_THROW( 39 | AsyncUdpChannel::ipv4(io_context, "bad@bad", "30000"), std::system_error); 40 | } // namespace detailTEST(ChannelTest,CreateV4) 41 | 42 | // TODO(Abdessattar): testing IPV6 does not work inside containers 43 | // TEST(ChannelTest, CreateV6) { 44 | // boost::asio::io_context io_context; 45 | // ASSERT_NO_THROW(AsyncUdpChannel::ipv6(io_context, "::1", "30000")); 46 | 47 | // ASSERT_THROW( 48 | // AsyncUdpChannel::ipv6(io_context, "bad@bad", "30000"), 49 | // std::system_error); 50 | // ASSERT_THROW(AsyncUdpChannel::ipv6(io_context, "127.0.0.1", "30000"), 51 | // std::system_error); 52 | // } 53 | 54 | // NOLINTNEXTLINE 55 | TEST(ChannelTest, SendReceive) { 56 | boost::asio::io_context io_context; 57 | const auto receiver = AsyncUdpChannel::ipv4(io_context, "127.0.0.1", "30001"); 58 | const auto sender = AsyncUdpChannel::ipv4(io_context, "127.0.0.1", "30002"); 59 | std::string str("Hello"); 60 | 61 | auto received = false; 62 | receiver->AsyncReceive( 63 | [&received, str](std::error_code errc, const IpEndpoint &endpoint, 64 | BufferReader const &buffer) { 65 | ASSERT_FALSE(errc); 66 | ASSERT_EQ("127.0.0.1", endpoint.address_.to_string()); 67 | ASSERT_EQ(30002, endpoint.port_); 68 | received = true; 69 | const auto received_str = 70 | std::string(std::cbegin(buffer), std::cend(buffer)); 71 | ASSERT_EQ(str, received_str); 72 | }); 73 | 74 | const Buffer buf(str.begin(), str.end()); 75 | auto sent = false; 76 | sender->AsyncSend(buf, IpEndpoint{make_address_v4("127.0.0.1"), 30001}, 77 | [&sent](std::error_code errc) { 78 | ASSERT_FALSE(errc); 79 | sent = true; 80 | }); 81 | io_context.run(); 82 | ASSERT_TRUE(sent); 83 | ASSERT_TRUE(received); 84 | } 85 | 86 | } // namespace blocxxi::p2p::kademlia 87 | ASAP_DIAGNOSTIC_POP 88 | -------------------------------------------------------------------------------- /p2p/test/kbucket_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | // Disable compiler and linter warnings originating from the unit test framework 16 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 17 | // usage must be preceded by a '// NOLINTNEXTLINE'. 18 | ASAP_DIAGNOSTIC_PUSH 19 | #if defined(ASAP_CLANG_VERSION) 20 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 21 | #pragma clang diagnostic ignored "-Wglobal-constructors" 22 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 23 | #pragma clang diagnostic ignored "-Wweak-vtables" 24 | #endif 25 | 26 | namespace blocxxi::p2p::kademlia { 27 | 28 | // NOLINTNEXTLINE 29 | TEST(KBucketTest, AddNode) { 30 | auto bucket = KBucket(Node(Node::IdType::RandomHash(), "::1", 0), 0, 4); 31 | ASSERT_EQ(0U, bucket.Size().first); 32 | 33 | auto first = Node(Node::IdType::RandomHash(), "::1", 0); 34 | auto node_id = first.Id(); 35 | 36 | // Adding nodes while k-bucket not full succeeds and increments the number of 37 | // nodes in the bucket 38 | ASSERT_TRUE(bucket.AddNode(std::move(first))); 39 | ASSERT_EQ(1, bucket.Size().first); 40 | ASSERT_TRUE(bucket.AddNode(Node(Node::IdType::RandomHash(), "::1", 1))); 41 | ASSERT_EQ(2, bucket.Size().first); 42 | ASSERT_TRUE(bucket.AddNode(Node(Node::IdType::RandomHash(), "::1", 2))); 43 | ASSERT_EQ(3, bucket.Size().first); 44 | ASSERT_TRUE(bucket.AddNode(Node(Node::IdType::RandomHash(), "::1", 3))); 45 | ASSERT_EQ(4, bucket.Size().first); 46 | 47 | // Adding a node when bucket has ksize nodes returns false and the node is 48 | // added to the replacement cache instead 49 | ASSERT_FALSE(bucket.AddNode(Node(Node::IdType::RandomHash(), "::1", 4))); 50 | ASSERT_EQ(4, bucket.Size().first); 51 | // TODO(Abdessattar): assert replacement size increased 52 | 53 | // Adding a node with an id that is already in k-bucket will replace the 54 | // existing node 55 | ASSERT_TRUE(bucket.AddNode(Node(node_id, "::", 5))); 56 | ASSERT_EQ(4, bucket.Size().first); 57 | ASSERT_TRUE(bucket.AddNode(Node(node_id, "::", 6))); 58 | ASSERT_EQ(4, bucket.Size().first); 59 | 60 | ASSERT_FALSE(bucket.AddNode(Node(Node::IdType::RandomHash(), "::1", 7))); 61 | ASSERT_EQ(bucket.Size().first, 4); 62 | } 63 | 64 | // NOLINTNEXTLINE 65 | TEST(KBucketTest, RemoveNode) { 66 | auto bucket = KBucket(Node(Node::IdType::RandomHash(), "::1", 0), 0, 3); 67 | ASSERT_EQ(bucket.Size().first, 0); 68 | 69 | // Remove from empty bucket has no effect 70 | bucket.RemoveNode(Node(Node::IdType::RandomHash(), "::1", 0)); 71 | 72 | // Add then remove - no replacement cache 73 | Node::IdType ids[4]; 74 | auto node = Node(Node::IdType::RandomHash(), "::1", 0); 75 | ids[0] = node.Id(); 76 | bucket.AddNode(std::move(node)); 77 | ASSERT_EQ(1, bucket.Size().first); 78 | bucket.RemoveNode(Node(ids[0], "::", 0)); 79 | ASSERT_EQ(0, bucket.Size().first); 80 | 81 | // Create a replacement cache with 1 item 82 | for (uint16_t i = 0; i < 4; ++i) { 83 | node = Node(Node::IdType::RandomHash(), "::1", i); 84 | ids[i] = node.Id(); 85 | bucket.AddNode(std::move(node)); 86 | } 87 | ASSERT_EQ(3, bucket.Size().first); 88 | 89 | // Remove a node will get it replaced by the cached node 90 | bucket.RemoveNode(Node(ids[0], "::", 0)); 91 | ASSERT_EQ(3, bucket.Size().first); 92 | bucket.RemoveNode(Node(ids[3], "::", 3)); 93 | ASSERT_EQ(2, bucket.Size().first); 94 | 95 | // Remove the rest now until k-bucket is empty 96 | bucket.RemoveNode(Node(ids[1], "::", 1)); 97 | ASSERT_EQ(1, bucket.Size().first); 98 | bucket.RemoveNode(Node(ids[2], "::", 2)); 99 | ASSERT_EQ(0, bucket.Size().first); 100 | } 101 | 102 | } // namespace blocxxi::p2p::kademlia 103 | ASAP_DIAGNOSTIC_POP 104 | -------------------------------------------------------------------------------- /p2p/test/main.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | // #include 8 | // #include 9 | 10 | #include 11 | 12 | auto main(int argc, char *argv[]) -> int { 13 | // asap::logging::Registry::instance().SetLogLevel( 14 | // asap::logging::Logger::Level::off); 15 | 16 | // asap::contract::PrepareForTesting(); 17 | 18 | testing::InitGoogleTest(&argc, argv); 19 | testing::InitGoogleMock(&argc, argv); 20 | return RUN_ALL_TESTS(); 21 | } 22 | -------------------------------------------------------------------------------- /p2p/test/network_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using testing::_; // NOLINT 16 | using testing::AtLeast; 17 | using testing::NiceMock; 18 | using testing::Return; 19 | 20 | // Disable compiler and linter warnings originating from the unit test framework 21 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 22 | // usage must be preceded by a '// NOLINTNEXTLINE'. 23 | ASAP_DIAGNOSTIC_PUSH 24 | #if defined(ASAP_CLANG_VERSION) 25 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 26 | #pragma clang diagnostic ignored "-Wglobal-constructors" 27 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 28 | #pragma clang diagnostic ignored "-Wweak-vtables" 29 | #endif 30 | 31 | namespace blocxxi::p2p::kademlia { 32 | 33 | class MockChannel { 34 | public: 35 | using RecvCallBackType = std::function; 37 | 38 | using SendCallbackType = std::function; 39 | 40 | // NOLINTNEXTLINE 41 | MOCK_METHOD1(AsyncReceive, void(RecvCallBackType)); 42 | // NOLINTNEXTLINE 43 | MOCK_METHOD3(AsyncSend, 44 | void(std::vector const &, IpEndpoint const &, SendCallbackType)); 45 | // NOLINTNEXTLINE 46 | MOCK_CONST_METHOD0(LocalEndpoint, IpEndpoint()); 47 | }; 48 | 49 | // NOLINTNEXTLINE 50 | TEST(NetworkTest, Simple) { 51 | boost::asio::io_context context; 52 | auto v4_chan = AsyncUdpChannel::ipv4(context, "127.0.0.1", "4242"); 53 | // TODO(Abdessattar): testing IPV6 does not work inside containers 54 | // auto v6 = AsyncUdpChannel::ipv6(context, "::1", "4242"); 55 | auto serializer = 56 | std::make_unique(Node::IdType::RandomHash()); 57 | 58 | Network network( 59 | context, std::move(serializer), std::move(v4_chan)); 60 | context.run(); 61 | } 62 | 63 | // TODO(Abdessattar) this test relies on assertion failure 64 | // TEST(NetworkTest, CallingStartWithNoReceiveHandlerIsFatal) { 65 | // boost::asio::io_context context; 66 | // auto v4 = std::make_unique>(); 67 | // auto v6 = std::make_unique>(); 68 | // auto serializer = 69 | // std::make_unique(Node::IdType::RandomHash()); 70 | // Network network( 71 | // context, std::move(serializer), std::move(v4), std::move(v6)); 72 | // /* 73 | // Assertion failed. Please file a bugreport at ... 74 | 75 | // file: '/Users/abdessattar/Projects/blocxxi/p2p ... 76 | // line: 118 77 | // function: void blocxxi::p2p::kademlia::Network>(); 92 | auto v6_chan = std::make_unique>(); 93 | 94 | ON_CALL(*v4_chan, LocalEndpoint()) 95 | .WillByDefault(Return(IpEndpoint{"127.0.0.1", 4242})); 96 | ON_CALL(*v6_chan, LocalEndpoint()) 97 | .WillByDefault(Return(IpEndpoint{"::1", 4242})); 98 | 99 | EXPECT_CALL(*v4_chan, AsyncReceive(_)).Times(AtLeast(1)); 100 | EXPECT_CALL(*v6_chan, AsyncReceive(_)).Times(AtLeast(1)); 101 | 102 | auto serializer = 103 | std::make_unique(Node::IdType::RandomHash()); 104 | Network network( 105 | context, std::move(serializer), std::move(v4_chan), std::move(v6_chan)); 106 | 107 | network.OnMessageReceived([](IpEndpoint const &, BufferReader const &) {}); 108 | network.Start(); 109 | } 110 | 111 | } // namespace blocxxi::p2p::kademlia 112 | ASAP_DIAGNOSTIC_POP 113 | -------------------------------------------------------------------------------- /p2p/test/node_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | ASAP_DIAGNOSTIC_PUSH 15 | #if defined(ASAP_GNUC_VERSION) 16 | #pragma GCC diagnostic ignored "-Wsign-conversion" 17 | #pragma GCC diagnostic ignored "-Wold-style-cast" 18 | #endif 19 | #if defined(ASAP_CLANG_VERSION) 20 | #pragma clang diagnostic ignored "-Wextra-semi-stmt" 21 | #pragma clang diagnostic ignored "-Wmissing-noreturn" 22 | #endif 23 | #include 24 | ASAP_DIAGNOSTIC_POP 25 | 26 | // Disable compiler and linter warnings originating from the unit test framework 27 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 28 | // usage must be preceded by a '// NOLINTNEXTLINE'. 29 | ASAP_DIAGNOSTIC_PUSH 30 | #if defined(ASAP_CLANG_VERSION) 31 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 32 | #pragma clang diagnostic ignored "-Wglobal-constructors" 33 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 34 | #pragma clang diagnostic ignored "-Wweak-vtables" 35 | #endif 36 | 37 | namespace blocxxi::p2p::kademlia { 38 | 39 | namespace { 40 | 41 | using uint256_t = 42 | boost::multiprecision::number>; 45 | 46 | } // anonymous namespace 47 | 48 | // NOLINTNEXTLINE 49 | TEST(NodeTest, Construction) { 50 | auto node_1 = Node(Node::IdType::RandomHash(), "1.1.1.1", 3030); 51 | auto node_2 = Node(node_1); 52 | ASSERT_EQ(node_1.Id(), node_2.Id()); 53 | ASSERT_EQ(node_1.Endpoint(), node_2.Endpoint()); 54 | ASSERT_EQ(node_1.ToString(), node_2.ToString()); 55 | 56 | auto node_3 = std::move(node_1); 57 | ASSERT_EQ(node_2.Id(), node_3.Id()); 58 | ASSERT_EQ(node_2.Endpoint(), node_3.Endpoint()); 59 | ASSERT_EQ(node_2.ToString(), node_3.ToString()); 60 | 61 | auto node_4(std::move(node_3)); 62 | ASSERT_EQ(node_2.Id(), node_4.Id()); 63 | ASSERT_EQ(node_2.Endpoint(), node_4.Endpoint()); 64 | ASSERT_EQ(node_2.ToString(), node_4.ToString()); 65 | 66 | auto node_5 = node_4; 67 | ASSERT_EQ(node_4.Id(), node_5.Id()); 68 | ASSERT_EQ(node_4.Endpoint(), node_5.Endpoint()); 69 | ASSERT_EQ(node_4.ToString(), node_5.ToString()); 70 | } 71 | 72 | // NOLINTNEXTLINE 73 | TEST(NodeTest, LogDistance) { 74 | // LogDistance same id is -1 75 | auto a_node_hash = Node::IdType::RandomHash(); 76 | auto a_node = Node(a_node_hash, "::1", 1); 77 | auto dist = LogDistance(a_node, a_node); 78 | ASSERT_EQ(-1, dist); 79 | 80 | // LogDistance first bits are different = 159 81 | auto b_node_hash = a_node_hash; 82 | b_node_hash[0] = a_node_hash[0] ^ 0x80; 83 | auto b_node = Node(b_node_hash, "::1", 2); 84 | dist = LogDistance(a_node, b_node); 85 | ASSERT_EQ(159, dist); 86 | 87 | for (int i = 0; i < 10; ++i) { 88 | a_node = Node(Node::IdType::RandomHash(), "::1", 0); 89 | b_node = Node(Node::IdType::RandomHash(), "::1", 0); 90 | 91 | auto logdist = LogDistance(a_node, b_node); 92 | 93 | auto distanceRaw = Distance(a_node, b_node); 94 | uint256_t distance; 95 | import_bits(distance, distanceRaw.begin(), distanceRaw.end()); 96 | 97 | auto kbucket = logdist; 98 | 99 | uint256_t two_k; 100 | bit_set(two_k, kbucket); 101 | ASSERT_TRUE(two_k < distance); 102 | bit_unset(two_k, kbucket); 103 | bit_set(two_k, kbucket + 1); 104 | ASSERT_TRUE(two_k > distance); 105 | } 106 | } 107 | 108 | // NOLINTNEXTLINE 109 | TEST(NodeTest, FromUrlString) { 110 | const auto node_id = Node::IdType::RandomHash().ToHex(); 111 | const auto *address = "192.168.1.35"; 112 | const auto *port = "4242"; 113 | const auto str = std::string("knode://") 114 | .append(node_id) 115 | .append("@") 116 | .append(address) 117 | .append(":") 118 | .append(port); 119 | 120 | Node node; 121 | // NOLINTNEXTLINE 122 | ASSERT_NO_THROW(node = Node::FromUrlString(str)); 123 | ASSERT_EQ(node_id, node.Id().ToHex()); 124 | ASSERT_EQ(address, node.Endpoint().Address().to_string()); 125 | ASSERT_EQ( 126 | port, std::to_string(static_cast(node.Endpoint().Port()))); 127 | } 128 | 129 | } // namespace blocxxi::p2p::kademlia 130 | ASAP_DIAGNOSTIC_POP 131 | -------------------------------------------------------------------------------- /p2p/test/response_dispatcher_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | // Disable compiler and linter warnings originating from the unit test framework 13 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 14 | // usage must be preceded by a '// NOLINTNEXTLINE'. 15 | ASAP_DIAGNOSTIC_PUSH 16 | #if defined(ASAP_CLANG_VERSION) 17 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 18 | #pragma clang diagnostic ignored "-Wglobal-constructors" 19 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 20 | #pragma clang diagnostic ignored "-Wweak-vtables" 21 | #endif 22 | 23 | namespace blocxxi::p2p::kademlia { 24 | 25 | // NOLINTNEXTLINE 26 | TEST(ResponseDispatcherTest, BasicOperation) { 27 | boost::asio::io_context io_context; 28 | auto dispatcher = ResponseDispatcher(io_context); 29 | auto hash = KeyType::RandomHash(); 30 | { 31 | dispatcher.RegisterCallbackWithTimeout( 32 | hash, std::chrono::seconds(5), 33 | [hash](ResponseDispatcher::EndpointType const &sender, 34 | Header const &header, BufferReader const &) { 35 | ASSERT_EQ(hash, header.random_token_); 36 | ASSERT_EQ("92.54.32.1", sender.Address().to_string()); 37 | ASSERT_EQ(4242, sender.Port()); 38 | }, 39 | [](std::error_code const &failure) { 40 | FAIL() << "unexpected error: " << failure.message(); 41 | }); 42 | } 43 | 44 | Header header; 45 | header.random_token_ = hash; 46 | Buffer buffer; 47 | dispatcher.HandleResponse( 48 | ResponseDispatcher::EndpointType( 49 | ResponseDispatcher::EndpointType::AddressType::from_string( 50 | "92.54.32.1"), 51 | 4242), 52 | header, BufferReader(buffer)); 53 | } 54 | 55 | // NOLINTNEXTLINE 56 | TEST(ResponseDispatcherTest, CallbackTimeout) { 57 | boost::asio::io_context io_context; 58 | { 59 | auto dispatcher = ResponseDispatcher(io_context); 60 | const auto hash = KeyType::RandomHash(); 61 | dispatcher.RegisterCallbackWithTimeout( 62 | hash, std::chrono::seconds(5), 63 | [](ResponseDispatcher::EndpointType const &, Header const &, 64 | BufferReader const &) { FAIL() << "should have timed out"; }, 65 | [](std::error_code const &) { SUCCEED(); }); 66 | } 67 | 68 | io_context.run(); 69 | } 70 | 71 | } // namespace blocxxi::p2p::kademlia 72 | ASAP_DIAGNOSTIC_POP 73 | -------------------------------------------------------------------------------- /p2p/test/routingtable_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | // Disable compiler and linter warnings originating from the unit test framework 13 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 14 | // usage must be preceded by a '// NOLINTNEXTLINE'. 15 | ASAP_DIAGNOSTIC_PUSH 16 | #if defined(ASAP_CLANG_VERSION) 17 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 18 | #pragma clang diagnostic ignored "-Wglobal-constructors" 19 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 20 | #pragma clang diagnostic ignored "-Wweak-vtables" 21 | #endif 22 | 23 | namespace blocxxi::p2p::kademlia { 24 | 25 | // NOLINTNEXTLINE 26 | TEST(RoutingTableTest, AddContact) { 27 | auto rt_node = Node(Node::IdType::RandomHash(), "::1", 3030); 28 | 29 | auto routing_table = RoutingTable(std::move(rt_node), 3); 30 | 31 | routing_table.AddPeer(Node(Node::IdType::RandomHash(), "::1", 1)); 32 | } 33 | 34 | // NOLINTNEXTLINE 35 | TEST(RoutingTableTest, FindNeighborsReturnsEmptyIfRoutingTableIsEmpty) { 36 | auto rt_node = Node(Node::IdType::RandomHash(), "::1", 3030); 37 | const auto routing_table = RoutingTable(std::move(rt_node), 20); 38 | /* 39 | for (auto i = 0U; i < 19; ++i) { 40 | rt.AddContact(Node(Node::IdType::RandomHash(), "::1", i)); 41 | } 42 | */ 43 | const auto neighbors = 44 | routing_table.FindNeighbors(Node::IdType::RandomHash(), 20); 45 | 46 | ASSERT_EQ(0, neighbors.size()); 47 | } 48 | 49 | // NOLINTNEXTLINE 50 | TEST(RoutingTableTest, FindNeighborsReturnsAllNodesIfNotEnoughAvailable) { 51 | auto rt_node = Node(Node::IdType::RandomHash(), "::1", 3030); 52 | auto routing_table = RoutingTable(std::move(rt_node), 20); 53 | for (uint16_t i = 0U; i < 4; ++i) { 54 | routing_table.AddPeer(Node(Node::IdType::RandomHash(), "::1", i)); 55 | } 56 | const auto neighbors = 57 | routing_table.FindNeighbors(Node::IdType::RandomHash(), 7); 58 | 59 | ASSERT_EQ(4, neighbors.size()); 60 | } 61 | 62 | // NOLINTNEXTLINE 63 | TEST(RoutingTableTest, FindNeighborsReturnsRequestedNodesIfAvailable) { 64 | auto rt_node = Node(Node::IdType::RandomHash(), "::1", 3030); 65 | auto routing_table = RoutingTable(std::move(rt_node), 5); 66 | for (uint16_t i = 0U; i < 30; ++i) { 67 | routing_table.AddPeer(Node(Node::IdType::RandomHash(), "::1", i)); 68 | } 69 | routing_table.DumpToLog(); 70 | auto neighbors10 = 71 | routing_table.FindNeighbors(Node::IdType::RandomHash(), 10); 72 | ASSERT_EQ(10, neighbors10.size()); 73 | auto neighbors7 = routing_table.FindNeighbors(Node::IdType::RandomHash(), 7); 74 | ASSERT_EQ(7, neighbors7.size()); 75 | } 76 | 77 | } // namespace blocxxi::p2p::kademlia 78 | ASAP_DIAGNOSTIC_POP 79 | -------------------------------------------------------------------------------- /p2p/test/timer_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace blocxxi::p2p::kademlia { 13 | 14 | // Disable compiler and linter warnings originating from the unit test framework 15 | // and for which we cannot do anything. Additionally, every TEST or TEST_X macro 16 | // usage must be preceded by a '// NOLINTNEXTLINE'. 17 | ASAP_DIAGNOSTIC_PUSH 18 | #if defined(ASAP_CLANG_VERSION) 19 | #pragma clang diagnostic ignored "-Wused-but-marked-unused" 20 | #pragma clang diagnostic ignored "-Wglobal-constructors" 21 | #pragma clang diagnostic ignored "-Wexit-time-destructors" 22 | #pragma clang diagnostic ignored "-Wweak-vtables" 23 | #endif 24 | 25 | // NOLINTNEXTLINE 26 | TEST(TimerTest, OneTimer) { 27 | boost::asio::io_context io_context; 28 | auto timer = Timer(io_context); 29 | 30 | auto fired = false; 31 | timer.ExpiresFromNow(std::chrono::seconds(1), [&fired]() { fired = true; }); 32 | io_context.run(); 33 | ASSERT_TRUE(fired); 34 | } 35 | 36 | // NOLINTNEXTLINE 37 | TEST(TimerTest, MultipleTimersFireInOrder) { 38 | boost::asio::io_context io_context; 39 | auto timer = Timer(io_context); 40 | 41 | auto fired = 0; 42 | timer.ExpiresFromNow(std::chrono::milliseconds(1000), [&fired]() { 43 | ASSERT_EQ(0, fired); 44 | ++fired; 45 | }); 46 | timer.ExpiresFromNow(std::chrono::milliseconds(1200), [&fired]() { 47 | ASSERT_EQ(1, fired); 48 | ++fired; 49 | }); 50 | timer.ExpiresFromNow(std::chrono::milliseconds(1300), [&fired]() { 51 | ASSERT_EQ(2, fired); 52 | ++fired; 53 | }); 54 | io_context.run(); 55 | ASSERT_EQ(3, fired); 56 | } 57 | 58 | // NOLINTNEXTLINE 59 | TEST(TimerTest, ShorterTimeoutFiresBeforeOthers) { 60 | boost::asio::io_context io_context; 61 | auto timer = Timer(io_context); 62 | 63 | auto shorter = false; 64 | auto later = false; 65 | // First schedule a long timeout 66 | timer.ExpiresFromNow(std::chrono::seconds(2), [&shorter, &later]() { 67 | ASSERT_TRUE(shorter); 68 | later = true; 69 | }); 70 | 71 | // Schedule a shorter timeout - it must fire before the later one 72 | timer.ExpiresFromNow(std::chrono::seconds(1), [&shorter, &later]() { 73 | ASSERT_FALSE(later); 74 | shorter = true; 75 | }); 76 | io_context.run(); 77 | ASSERT_TRUE(shorter); 78 | ASSERT_TRUE(later); 79 | } 80 | 81 | // NOLINTNEXTLINE 82 | TEST(TimerTest, MultipleTimeoutsWithSameDuration) { 83 | boost::asio::io_context io_context; 84 | auto timer = Timer(io_context); 85 | 86 | auto one = false; 87 | auto two = false; 88 | auto three = false; 89 | auto four = false; 90 | timer.ExpiresFromNow( 91 | std::chrono::milliseconds(1000), [&one]() { one = true; }); 92 | timer.ExpiresFromNow( 93 | std::chrono::microseconds(1000), [&two]() { two = true; }); 94 | timer.ExpiresFromNow( 95 | std::chrono::milliseconds(1100), [&three]() { three = true; }); 96 | timer.ExpiresFromNow( 97 | std::chrono::milliseconds(1050), [&four]() { four = true; }); 98 | io_context.run(); 99 | ASSERT_TRUE(one); 100 | ASSERT_TRUE(two); 101 | ASSERT_TRUE(three); 102 | ASSERT_TRUE(four); 103 | } 104 | 105 | // NOLINTNEXTLINE 106 | TEST(TimerTest, MoveConstructorMovesTimers) { 107 | boost::asio::io_context io_context; 108 | auto moved = Timer(io_context); 109 | auto fired = 0; 110 | moved.ExpiresFromNow(std::chrono::seconds(1), [&fired]() { ++fired; }); 111 | 112 | // Move the timer (copy) 113 | auto copied_timer(std::move(moved)); 114 | io_context.run(); 115 | ASSERT_EQ(1, fired); 116 | } 117 | 118 | // NOLINTNEXTLINE 119 | TEST(TimerTest, MoveAssignmentMovesTimers) { 120 | boost::asio::io_context io_context; 121 | auto moved = Timer(io_context); 122 | auto fired = 0; 123 | moved.ExpiresFromNow(std::chrono::seconds(1), [&fired]() { ++fired; }); 124 | 125 | // Move the timer (copy) 126 | auto timer = Timer(io_context); 127 | timer = std::move(moved); 128 | io_context.run(); 129 | ASSERT_EQ(1, fired); 130 | } 131 | 132 | } // namespace blocxxi::p2p::kademlia 133 | ASAP_DIAGNOSTIC_POP 134 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | autopep8 2 | bandit 3 | breathe 4 | cmakelang 5 | docutils 6 | esbonio 7 | myst-parser 8 | pygments 9 | rstcheck 10 | sphinx 11 | sphinx-autobuild 12 | sphinx-book-theme 13 | sphinx-copybutton 14 | sphinx-prompt 15 | -------------------------------------------------------------------------------- /templates/version.h.in: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #pragma once 8 | 9 | namespace @META_PROJECT_ID_LOWER@ { 10 | namespace info { 11 | 12 | constexpr auto cProjectName = "@META_PROJECT_NAME@"; 13 | constexpr auto cProjectDescription = "@META_PROJECT_DESCRIPTION@"; 14 | 15 | constexpr auto cAuthorOrganization = "@META_AUTHOR_ORGANIZATION@"; 16 | constexpr auto cAuthorDomain = "@META_AUTHOR_DOMAIN@"; 17 | constexpr auto cAuthor = "@META_AUTHOR_MAINTAINER@"; 18 | 19 | constexpr auto cVersionMajor = "@META_VERSION_MAJOR@"; 20 | constexpr auto cVersionMinor = "@META_VERSION_MINOR@"; 21 | constexpr auto cVersionPatch = "@META_VERSION_PATCH@"; 22 | constexpr auto cVersionRevision = "@META_VERSION_REVISION@"; 23 | 24 | constexpr auto cVersion = "@META_VERSION@"; 25 | constexpr auto cNameVersion = "@META_NAME_VERSION@"; 26 | 27 | } // namespace info 28 | } // Namespace @META_PROJECT_ID_LOWER@ 29 | -------------------------------------------------------------------------------- /tools/version-info/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated files inside source tree 2 | src/main.cpp 3 | -------------------------------------------------------------------------------- /tools/version-info/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ===------------------------------------------------------------------------===# 2 | # Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | # copy at https://opensource.org/licenses/BSD-3-Clause). 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # ===------------------------------------------------------------------------===# 6 | 7 | set(my_name "version-info") 8 | asap_push_module("${my_name}") 9 | 10 | # ------------------------------------------------------------------------------ 11 | # Meta information about the this module 12 | # ------------------------------------------------------------------------------ 13 | 14 | asap_declare_module( 15 | MODULE_NAME 16 | "${my_name}" 17 | DESCRIPTION 18 | "Print the project's version information." 19 | GITHUB_REPO 20 | "${META_GITHUB_REPO}" 21 | AUTHOR_MAINTAINER 22 | "${META_AUTHOR_MAINTAINER}" 23 | VERSION_MAJOR 24 | "1" 25 | VERSION_MINOR 26 | "0" 27 | VERSION_PATCH 28 | "0") 29 | 30 | # ============================================================================== 31 | # Build instructions 32 | # ============================================================================== 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Code generation 36 | # ------------------------------------------------------------------------------ 37 | 38 | # Generate version-header 39 | configure_file(src/main.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp) 40 | 41 | # ------------------------------------------------------------------------------ 42 | # Main module target 43 | # ------------------------------------------------------------------------------ 44 | 45 | set(MODULE_TARGET_NAME "${META_PROJECT_NAME}-${META_MODULE_NAME}") 46 | 47 | asap_add_executable(${MODULE_TARGET_NAME} WARNING SOURCES "src/main.cpp") 48 | 49 | target_compile_features(${MODULE_TARGET_NAME} PUBLIC cxx_constexpr) 50 | 51 | target_compile_features(${MODULE_TARGET_NAME} PUBLIC cxx_constexpr) 52 | cmake_path(SET version_include_dir ${CMAKE_CURRENT_BINARY_DIR}/../../include 53 | NORMALIZE) 54 | target_include_directories( 55 | ${MODULE_TARGET_NAME} 56 | PUBLIC $ $ 57 | PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) 58 | 59 | # ------------------------------------------------------------------------------ 60 | # Run executable test 61 | # ------------------------------------------------------------------------------ 62 | 63 | if(ASAP_BUILD_TESTS) 64 | add_test( 65 | NAME version-info 66 | COMMAND ${MODULE_TARGET_NAME} 67 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) 68 | endif() 69 | 70 | # ============================================================================== 71 | # Deployment instructions 72 | # ============================================================================== 73 | 74 | if(${META_PROJECT_ID}_INSTALL) 75 | set(TARGETS_EXPORT_NAME "${MODULE_TARGET_NAME}Targets") 76 | set(runtime "${MODULE_TARGET_NAME}_runtime") 77 | set(dev "${MODULE_TARGET_NAME}_dev") 78 | 79 | # Binaries 80 | install( 81 | TARGETS ${MODULE_TARGET_NAME} 82 | EXPORT "${TARGETS_EXPORT_NAME}" 83 | COMPONENT runtime 84 | RUNTIME DESTINATION ${ASAP_INSTALL_BIN} COMPONENT ${runtime} 85 | LIBRARY DESTINATION ${ASAP_INSTALL_SHARED} COMPONENT ${runtime} 86 | ARCHIVE DESTINATION ${ASAP_INSTALL_LIB} COMPONENT ${dev}) 87 | 88 | # Docs 89 | if(EXISTS ${SPHINX_BUILD_DIR}/${MODULE_TARGET_NAME}) 90 | install( 91 | DIRECTORY ${SPHINX_BUILD_DIR}/${MODULE_TARGET_NAME} 92 | DESTINATION ${ASAP_INSTALL_DOC} 93 | COMPONENT ${MODULE_TARGET_NAME}_docs) 94 | endif() 95 | endif() 96 | 97 | asap_pop_module("${my_name}") 98 | -------------------------------------------------------------------------------- /tools/version-info/README.md: -------------------------------------------------------------------------------- 1 | # Project version information 2 | 3 | This is a small executable tool that uses the generated `version.h` C++ include 4 | file to print the project meta data on the standard output. 5 | 6 | Here is an example output: 7 | 8 | ```text 9 | asap v4.4.8 (cb228e8af73f) 10 | By Abdessattar Sassi @ The Authors (https://github.com/abdes/asap). 11 | 12 | Instantly start with a fully loaded CMake project 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /tools/version-info/src/main.cpp.in: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // Distributed under the 3-Clause BSD License. See accompanying file LICENSE or 3 | // copy at https://opensource.org/licenses/BSD-3-Clause). 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | //===----------------------------------------------------------------------===// 6 | 7 | #include 8 | 9 | #include <@META_PROJECT_ID_LOWER@/version.h> 10 | 11 | // clang-format off 12 | using namespace @META_PROJECT_ID_LOWER@::info; 13 | // clang-format on 14 | 15 | auto main(int /*argc*/, char ** /*argv*/) -> int { 16 | std::cout << cNameVersion << "\n" 17 | << "By " << cAuthor << " @ " << cAuthorOrganization << " (" 18 | << cAuthorDomain << ").\n" 19 | << std::endl; 20 | 21 | std::cout << cProjectDescription << "\n" << std::endl; 22 | 23 | return 0; 24 | } 25 | --------------------------------------------------------------------------------