early-access version 2862
This commit is contained in:
9
externals/CMakeLists.txt
vendored
9
externals/CMakeLists.txt
vendored
@@ -73,6 +73,10 @@ if (YUZU_USE_EXTERNAL_SDL2)
|
||||
add_library(SDL2 ALIAS SDL2-static)
|
||||
endif()
|
||||
|
||||
# ENet
|
||||
add_subdirectory(enet)
|
||||
target_include_directories(enet INTERFACE ./enet/include)
|
||||
|
||||
# Cubeb
|
||||
if(ENABLE_CUBEB)
|
||||
set(BUILD_TESTS OFF CACHE BOOL "")
|
||||
@@ -112,6 +116,11 @@ if (ENABLE_WEB_SERVICE)
|
||||
if (WIN32)
|
||||
target_link_libraries(httplib INTERFACE crypt32 cryptui ws2_32)
|
||||
endif()
|
||||
|
||||
# cpp-jwt
|
||||
add_library(cpp-jwt INTERFACE)
|
||||
target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
|
||||
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
|
56
externals/cpp-jwt/.github/workflows/main.yml
vendored
Executable file
56
externals/cpp-jwt/.github/workflows/main.yml
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
name: CMake
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Debug
|
||||
CMAKE_ARGS: '-DCMAKE_BUILD_TYPE=Debug -DCPP_JWT_USE_VENDORED_NLOHMANN_JSON=off'
|
||||
VCPKG_ARGUMENTS: 'nlohmann-json openssl gtest'
|
||||
VCPKG_VERSION: '6be82cfac67649a31d4c3eba56d2fafa9dc6736a' # May 13, 2022
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: 'Windows/2019/MSVC-19.30.30528.0',
|
||||
os: windows-2019,
|
||||
triplet: x64-windows,
|
||||
parallel: 2,
|
||||
}
|
||||
- {
|
||||
name: 'MacOSX/11/AppleClang-12.0.5.12050022',
|
||||
os: macos-11,
|
||||
triplet: x64-osx,
|
||||
parallel: 3,
|
||||
}
|
||||
- {
|
||||
name: 'Ubuntu/20.04/GCC-9.3.0',
|
||||
os: ubuntu-20.04,
|
||||
triplet: x64-linux,
|
||||
parallel: 2,
|
||||
}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: Install vcpkg
|
||||
uses: lukka/run-vcpkg@v7
|
||||
with:
|
||||
vcpkgDirectory: ${{ runner.workspace }}/vcpkg
|
||||
vcpkgArguments: ${{ env.VCPKG_ARGUMENTS }}
|
||||
vcpkgGitCommitId: ${{ env.VCPKG_VERSION }}
|
||||
vcpkgTriplet: ${{ matrix.config.triplet }}
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -B ${{ github.workspace }}/build -DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake ${{ env.CMAKE_ARGS }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{ github.workspace }}/build --config ${{ env.BUILD_TYPE }} --parallel ${{ matrix.config.parallel }}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ github.workspace }}/build
|
||||
run: ctest -C ${{ env.BUILD_TYPE }} -T test --parallel ${{ matrix.config.parallel }} --output-on-failure --timeout 200
|
1
externals/cpp-jwt/.gitignore
vendored
Executable file
1
externals/cpp-jwt/.gitignore
vendored
Executable file
@@ -0,0 +1 @@
|
||||
/build/
|
115
externals/cpp-jwt/CMakeLists.txt
vendored
Executable file
115
externals/cpp-jwt/CMakeLists.txt
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
cmake_minimum_required(VERSION 3.14.0)
|
||||
project(cpp-jwt VERSION 1.5.0)
|
||||
|
||||
option(CPP_JWT_BUILD_EXAMPLES "build examples" ON)
|
||||
option(CPP_JWT_BUILD_TESTS "build tests" ON)
|
||||
option(CPP_JWT_USE_VENDORED_NLOHMANN_JSON "use vendored json header" ON)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# only set compiler flags if we are the main project, otherwise let the main
|
||||
# project decide on the flags
|
||||
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}"
|
||||
MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if(NOT CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
# LIBRARY
|
||||
# ##############################################################################
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
INTERFACE $<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE OpenSSL::SSL)
|
||||
if(NOT CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE nlohmann_json::nlohmann_json)
|
||||
else()
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
endif()
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_14)
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
|
||||
# ##############################################################################
|
||||
# TESTS
|
||||
# ##############################################################################
|
||||
|
||||
if(CPP_JWT_BUILD_TESTS)
|
||||
find_package(GTest REQUIRED)
|
||||
include_directories(${GTEST_INCLUDE_DIRS})
|
||||
enable_testing()
|
||||
# Recurse into the "Hello" and "Demo" subdirectories. This does not actually
|
||||
# cause another cmake executable to run. The same process will walk through
|
||||
# the project's entire directory structure.
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
# EXAMPLES
|
||||
# ##############################################################################
|
||||
|
||||
if(CPP_JWT_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# ##############################################################################
|
||||
# INSTALL
|
||||
# ##############################################################################
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
set(CPP_JWT_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
COMPONENT dev)
|
||||
configure_package_config_file(cmake/Config.cmake.in ${PROJECT_NAME}Config.cmake
|
||||
INSTALL_DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR}
|
||||
NO_SET_AND_CHECK_MACRO)
|
||||
write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
|
||||
COMPATIBILITY SameMajorVersion
|
||||
ARCH_INDEPENDENT)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR}
|
||||
COMPONENT dev)
|
||||
|
||||
if(NOT CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
set(CPP_JWT_VENDORED_NLOHMANN_JSON_INSTALL_PATTERN PATTERN "json" EXCLUDE)
|
||||
endif()
|
||||
install(
|
||||
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/jwt/
|
||||
DESTINATION include/jwt
|
||||
COMPONENT dev
|
||||
FILES_MATCHING
|
||||
PATTERN "*.hpp"
|
||||
PATTERN "*.ipp"
|
||||
PATTERN "test" EXCLUDE
|
||||
${CPP_JWT_VENDORED_NLOHMANN_JSON_INSTALL_PATTERN})
|
21
externals/cpp-jwt/LICENSE
vendored
Executable file
21
externals/cpp-jwt/LICENSE
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
751
externals/cpp-jwt/README.md
vendored
Executable file
751
externals/cpp-jwt/README.md
vendored
Executable file
@@ -0,0 +1,751 @@
|
||||
<h1 align="center">CPP-JWT</h1>
|
||||
|
||||
<div align="center">
|
||||
<strong>A C++14 library for JSON Web Tokens(JWT)</strong>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
<img src="http://jwt.io/img/logo-asset.svg" />
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
<sub>
|
||||
A little library built with lots of ❤︎ for working with JWT easier.
|
||||
By Arun Muralidharan.
|
||||
</sub>
|
||||
</div>
|
||||
|
||||
## Table of Contents
|
||||
- [What is it](#what-is-it)
|
||||
- [Example](#example)
|
||||
- [API Philosophy](#api-philosophy)
|
||||
- [Support](#support)
|
||||
- [External Dependencies](#external-dependencies)
|
||||
- [Thanks to...](#thanks-to...)
|
||||
- [Compiler Support](#compiler-support)
|
||||
- [Installation](#installation)
|
||||
- [Parameters](#parameters)
|
||||
- [Claim Data Types](#claim-data-types)
|
||||
- [Advanced Examples](#advanced-examples)
|
||||
- [Error Codes & Exceptions](#error-codes-&-exceptions)
|
||||
- [Additional Header Data](#additional-header-data)
|
||||
- [Things for improvement](#things-for-improvement)
|
||||
- [LICENSE](#license)
|
||||
|
||||
|
||||
## What is it ?
|
||||
For the uninitiated, JSON Web Token(JWT) is a JSON based standard (<a href="https://tools.ietf.org/html/rfc7519">RFC-7519</a>) for creating assertions or access tokens that consists of some claims (encoded within the assertion).
|
||||
This assertion can be used in some kind of bearer authentication mechanism that the server will provide to clients, and the clients can make use of the provided assertion for accessing resources.
|
||||
|
||||
Few good resources on this material which I found useful are:
|
||||
<a href="https://scotch.io/tutorials/the-anatomy-of-a-json-web-token">Anatomy of JWT</a>
|
||||
<a href="https://auth0.com/learn/json-web-tokens/">Learn JWT</a>
|
||||
<a href="https://tools.ietf.org/html/rfc7519">RFC 7519</a>
|
||||
|
||||
|
||||
## Example
|
||||
Lets dive into see a simple example of encoding and decoding in Python. Taking the example of <strong>pyjwt</strong> module from its docs.
|
||||
|
||||
```python
|
||||
>>import jwt
|
||||
>>key = 'secret'
|
||||
>>
|
||||
>>encoded = jwt.encode({'some': 'payload'}, key, algorithm='HS256')
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg'
|
||||
>>
|
||||
>>decoded = jwt.decode(encoded, key, algorithms='HS256')
|
||||
{'some': 'payload'}
|
||||
```
|
||||
|
||||
Now, lets look at our C++ code doing the same thing.
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
auto key = "secret"; //Secret to use for the algorithm
|
||||
//Create JWT object
|
||||
jwt::jwt_object obj{algorithm("HS256"), payload({{"some", "payload"}}), secret(key)};
|
||||
|
||||
//Get the encoded string/assertion
|
||||
auto enc_str = obj.signature();
|
||||
std::cout << enc_str << std::endl;
|
||||
|
||||
//Decode
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret(key));
|
||||
std::cout << dec_obj.header() << std::endl;
|
||||
std::cout << dec_obj.payload() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
It outputs:
|
||||
```
|
||||
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
|
||||
{"alg":"HS256","typ":"JWT"}
|
||||
{"some":"payload"}
|
||||
```
|
||||
|
||||
Almost the same API, except for some ugliness here and there. But close enough!
|
||||
|
||||
Lets take another example in which we will see to add payload claim having type other than string.
|
||||
The <code>payload</code> function used in the above example to create <code>jwt_object</code> object can only take strings. For anything else, it will throw a compilation error.
|
||||
|
||||
For adding claims having values other than string, <code>jwt_object</code> class provides <code>add_claim</code> API. We will also see few other APIs in the next example. Make sure to read the comments :).
|
||||
|
||||
```cpp
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"user", "admin"}})};
|
||||
|
||||
//Use add_claim API to add claim values which are
|
||||
// _not_ strings.
|
||||
// For eg: `iat` and `exp` claims below.
|
||||
// Other claims could have been added in the payload
|
||||
// function above as they are just stringy things.
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "test")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
.add_claim("exp", std::chrono::system_clock::now() + std::chrono::seconds{10})
|
||||
;
|
||||
|
||||
//Use `has_claim` to check if the claim exists or not
|
||||
assert (obj.has_claim("iss"));
|
||||
assert (obj.has_claim("exp"));
|
||||
|
||||
//Use `has_claim_with_value` to check if the claim exists
|
||||
//with a specific value or not.
|
||||
assert (obj.payload().has_claim_with_value("id", "a-b-c-d-e-f-1-2-3"));
|
||||
assert (obj.payload().has_claim_with_value("iat", 1513862371));
|
||||
|
||||
//Remove a claim using `remove_claim` API.
|
||||
//Most APIs have an overload which takes enum class type as well
|
||||
//It can be used interchangeably with strings.
|
||||
obj.remove_claim(jwt::registered_claims::expiration);
|
||||
assert (!obj.has_claim("exp"));
|
||||
|
||||
//Using `add_claim` with extra features.
|
||||
//Check return status and overwrite
|
||||
bool ret = obj.payload().add_claim("sub", "new test", false/*overwrite*/);
|
||||
assert (!ret);
|
||||
|
||||
// Overwrite an existing claim
|
||||
ret = obj.payload().add_claim("sub", "new test", true/*overwrite*/);
|
||||
assert (ret);
|
||||
|
||||
assert (obj.payload().has_claim_with_value("sub", "new test"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The <code>jwt_object</code> class is basically a composition of the JWT component classes, which are <code>jwt_header</code> & <code>jwt_payload</code>. For convenience <code>jwt_object</code> exposes only few important APIs to the user, the remaining APIs under <code>jwt_header</code> and <code>jwt_payload</code> can be accessed by calling <code>jwt_object::header()</code> and <code>jwt_object::payload()</code> APIs.
|
||||
|
||||
|
||||
## API Philosophy
|
||||
I wanted to make the code easy to read and at the same time make most of the standard library and the modern features.
|
||||
It also uses some metaprogramming tricks to enforce type checks and give better error messages.
|
||||
|
||||
The design of `parameters` alleviates the pain of remembering positional arguments. Also makes the APIs more extensible for future enhancements.
|
||||
|
||||
The library has 2 sets of APIs for encoding and decoding:
|
||||
- API which takes an instance of <code>std::error_code</code>
|
||||
These APIs will report the errors by setting the `error_code`. This does not mean that these API would not throw. Memory allocation errors would still be thrown instead of setting the error_code.
|
||||
- API which throws exceptions
|
||||
All the errors would be thrown as exception.
|
||||
|
||||
## Support
|
||||
<strong>Algorithms and features supported</strong>
|
||||
- [x] HS256
|
||||
- [x] HS384
|
||||
- [x] HS512
|
||||
- [x] RS256
|
||||
- [x] RS384
|
||||
- [x] RS512
|
||||
- [x] ES256
|
||||
- [x] ES384
|
||||
- [x] ES512
|
||||
- [x] Sign
|
||||
- [x] Verify
|
||||
- [x] iss (issuer) check
|
||||
- [x] sub (subject) check
|
||||
- [x] aud (audience) check
|
||||
- [x] exp (expiration time) check
|
||||
- [x] nbf (not before time) check
|
||||
- [x] iat (issued at) check
|
||||
- [x] jti (JWT id) check
|
||||
- [x] JWS header addition support. For eg "kid" support.
|
||||
|
||||
## External Dependencies
|
||||
- <strong>OpenSSL </strong>(Version >= 1.0.2j)
|
||||
Might work with older version as well, but I did not check that.
|
||||
- <strong>Google Test Framework</strong>
|
||||
For running the tests
|
||||
- <strong>nlohmann JSON library</strong>
|
||||
The awesome JSON library :)
|
||||
|
||||
## Thanks to...
|
||||
- <a href="https://github.com/benmcollins/libjwt">ben-collins JWT library</a>
|
||||
- Howard Hinnant for the stack allocator
|
||||
- libstd++ code (I took the hashing code for string_view)
|
||||
|
||||
## Compiler Support
|
||||
|
||||
Tested with <strong>clang-5.0</strong> and <strong>g++-6.4</strong>.
|
||||
With issue#12, <strong>VS2017</strong> is also supported.
|
||||
|
||||
## Building the library
|
||||
|
||||
### using conan
|
||||
|
||||
```shell
|
||||
mkdir build
|
||||
cd build
|
||||
conan install .. --build missing
|
||||
cmake ..
|
||||
cmake --build . -j
|
||||
```
|
||||
|
||||
### using debian
|
||||
|
||||
```shell
|
||||
sudo apt install nlohmann-json3-dev
|
||||
sudo apt install libgtest-dev
|
||||
sudo apt install libssl-dev
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . -j
|
||||
```
|
||||
|
||||
## Consuming the library
|
||||
|
||||
This library is uses cmake as a build system.
|
||||
```cmake
|
||||
# you can use cmake's `find_package` after installation or `add_subdirectory` when vendoring this repository
|
||||
|
||||
find_package(cpp-jwt REQUIRED)
|
||||
# or
|
||||
add_subdirectory(third_party/cpp-jwt)
|
||||
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main cpp-jwt::cpp-jwt)
|
||||
```
|
||||
|
||||
You can also use this library as a conan package, its available in the [conan center](https://conan.io/center/cpp-jwt):
|
||||
just add `cpp-jwt[>=1.2]` to your conanfile.txt.
|
||||
|
||||
It can also be installed using [vcpkg](https://github.com/microsoft/vcpkg) by adding `"cpp-jwt"` to the dependencies in your `vcpkg.json` file.
|
||||
|
||||
## Parameters
|
||||
There are two sets of parameters which can be used for creating `jwt_object` and for decoding.
|
||||
All the parameters are basically a function which returns an instance of a type which are modelled after <code>ParameterConcept</code> (see <code>jwt::detail::meta::is_parameter_concept</code>).
|
||||
|
||||
|
||||
- <strong><code>jwt_object</code> creation parameters</strong>
|
||||
- <strong>payload</strong>
|
||||
|
||||
Used to populate the claims while creating the `jwt_object` instance.
|
||||
|
||||
There are two overloads of this function:
|
||||
- Takes Initializer list of <code>pair<string_view, string_view></code>
|
||||
|
||||
Easy to pass claims with string values which are all known at the time of object creation.
|
||||
Can be used like:
|
||||
```cpp
|
||||
jwt_object obj {
|
||||
payload({
|
||||
{"iss", "some-guy"},
|
||||
{"sub", "something"},
|
||||
{"X-pld", "data1"}
|
||||
}),
|
||||
... // Add other parameters
|
||||
};
|
||||
```
|
||||
Claim values which are not strings/string_views cannot be used.
|
||||
|
||||
- Takes any type which models <code>MappingConcept</code> (see <code>detail::meta::is_mapping_concept</code>)
|
||||
|
||||
This overload can accept <code>std::map</code> or <code>std::unordered_map</code> like containers.
|
||||
Can be used like:
|
||||
```cpp
|
||||
map<string, string> m;
|
||||
m["iss"] = "some-guy";
|
||||
m["sub"] = "something";
|
||||
m["X-pld"] = "data1";
|
||||
|
||||
jwt_object obj{
|
||||
payload(std::move(m)),
|
||||
... // Add other parameters
|
||||
};
|
||||
//OR
|
||||
jwt_object obj{
|
||||
payload(m),
|
||||
... // Add other parameters
|
||||
};
|
||||
```
|
||||
|
||||
- <strong>secret</strong>
|
||||
|
||||
Used to pass the key which could be some random string or the bytes of the PEM encoded public key
|
||||
file in PEM format (wrapped in -----BEGIN PUBLIC KEY----- block) as string.
|
||||
The passed string type must be convertible to <code>jwt::string_view</code>
|
||||
|
||||
- <strong>algorithm</strong>
|
||||
|
||||
Used to pass the type of algorithm to use for encoding.
|
||||
There are two overloads of this function:
|
||||
- Takes <code>jwt::string_view</code>
|
||||
|
||||
Can pass the algorithm value in any case. It is case agnostic.
|
||||
|
||||
- Takes value of type <code>enum class jwt::algorithm</code>
|
||||
|
||||
- <strong>headers</strong>
|
||||
|
||||
Used to populate fields in JWT header. It is very similar to `payload` function parameter.
|
||||
There are two overloads for this function which are similar to how <code>payload</code> function is.
|
||||
This parameter can be used to add headers other that <strong>alg</strong> and <strong>typ</strong>.
|
||||
|
||||
Same as the case with payload, only string values can be used with this. For adding values of other
|
||||
data types, use <code>add_header</code> API of <code>jwt_header</code> class.
|
||||
|
||||
For example adding `kid` header with other additional data fields.
|
||||
```cpp
|
||||
jwt_object obj{
|
||||
algorithm("HS256"),
|
||||
headers({
|
||||
{"kid", "12-34-56"},
|
||||
{"xtra", "header"}
|
||||
})
|
||||
... // Add other parameters
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
- <strong>Decoding parameters</strong>
|
||||
|
||||
- <strong>algorithms</strong>
|
||||
|
||||
This is a mandatory parameter which takes a sequence of algorithms (as string) which the user would like to permit when validating the JWT. The value in the header for "alg" would be matched against the provided sequence of values. If nothing matches <code>InvalidAlgorithmError</code> exception or <code>InvalidAlgorithm</code> error would be set based upon the API being used.
|
||||
|
||||
There are two overloads for this function:
|
||||
- Takes initializer-list of string values
|
||||
- Takes in any type which satifies the <strong>SequenceConcept</strong> (see <code>idetail::meta::is_sequence_concept</code>)
|
||||
|
||||
```cpp
|
||||
jwt::decode(algorithms({"none", "HS256", "RS256"}), ...);
|
||||
|
||||
OR
|
||||
|
||||
std::vector<std::string> algs{"none", "HS256", "RS256"};
|
||||
jwt::decode(algorithms(algs), ...);
|
||||
```
|
||||
|
||||
- <strong>secret</strong>
|
||||
|
||||
Optional parameter. To be supplied only when the algorithm used is not "none". Else would throw/set <code>KeyNotPresentError</code> / <code>KeyNotPresent</code> exception/error.
|
||||
|
||||
- <strong>leeway</strong>
|
||||
|
||||
Optional parameter. Used with validation of "Expiration" and "Not Before" claims.
|
||||
The value passed should be `seconds` to account for clock skew.
|
||||
Default value is `0` seconds.
|
||||
|
||||
- <strong>verify</strong>
|
||||
|
||||
Optional parameter. Suggests if verification of claims should be done or not.
|
||||
Takes a boolean value.
|
||||
By default verification is turned on.
|
||||
|
||||
- <strong>issuer</strong>
|
||||
|
||||
Optional parameter.
|
||||
Takes a string value.
|
||||
Validates the passed issuer value against the one present in the decoded JWT object. If the values do not match <code>InvalidIssuerError</code> or <code>InvalidIssuer</code> exception or error_code is thrown/set.
|
||||
|
||||
- <strong>aud</strong>
|
||||
|
||||
Optional parameter.
|
||||
Takes a string value.
|
||||
Validates the passed audience value against the one present in the decoded JWT object. If the values do not match <code>InvalidAudienceError</code> or <code>InvalidAudience</code> exception or error_code is thrown/set.
|
||||
|
||||
- <strong>sub</strong>
|
||||
|
||||
Optional parameter.
|
||||
Takes a string value.
|
||||
Validates the passed subject value against the one present in the decoded JWT object. If the values do not match <code>InvalidSubjectError</code> or <code>InvalidSubject</code> exception or error_code is thrown/set.
|
||||
|
||||
- <strong>validate_iat</strong>
|
||||
|
||||
Optional parameter.
|
||||
Takes a boolean value.
|
||||
Validates the IAT claim. Only checks whether the field is present and is of correct type. If not throws/sets <code>InvalidIATError</code> or <code>InvalidIAT</code>.
|
||||
|
||||
Default value is false.
|
||||
|
||||
- <strong>validate_jti</strong>
|
||||
|
||||
Optional parameter.
|
||||
Takes a boolean value.
|
||||
Validates the JTI claim. Only checks for the presence of the claim. If not throws or sets <code>InvalidJTIError</code> or <code>InvalidJTI</code>.
|
||||
|
||||
Default is false.
|
||||
|
||||
|
||||
## Claim Data Types
|
||||
For the registered claim types the library assumes specific data types for the claim values. Using anything else is not supported and would result in runtime JSON parse error.
|
||||
|
||||
Claim | Data Type
|
||||
-----------------------------------
|
||||
Expiration(exp) | uint64_t (Epoch time in seconds)
|
||||
-----------------------------------
|
||||
Not Before(nbf) | uint64_t (Epoch time in seconds)
|
||||
-----------------------------------
|
||||
Issuer(iss) | string
|
||||
-----------------------------------
|
||||
Audience(aud) | string
|
||||
-----------------------------------
|
||||
Issued At(iat) | uint64_t (Epoch time in seconds)
|
||||
-----------------------------------
|
||||
Subject(sub) | string
|
||||
-----------------------------------
|
||||
JTI(jti) | <Value type not checked by library. Upto application.>
|
||||
-----------------------------------
|
||||
|
||||
|
||||
## Advanced Examples
|
||||
We will see few complete examples which makes use of error code checks and exception handling.
|
||||
The examples are taken from the "tests" section. Users are requested to checkout the tests to find out more ways to use this library.
|
||||
|
||||
Expiration verification example (uses error_code):
|
||||
```cpp
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
assert (!ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), verify(true));
|
||||
assert (ec);
|
||||
assert (ec.value() == static_cast<int>(jwt::VerificationErrc::TokenExpired));
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Expiration verification example (uses exception):
|
||||
```cpp
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
try {
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), verify(true));
|
||||
} catch (const jwt::TokenExpiredError& e) {
|
||||
//Handle Token expired exception here
|
||||
//...
|
||||
} catch (const jwt::SignatureFormatError& e) {
|
||||
//Handle invalid signature format error
|
||||
//...
|
||||
} catch (const jwt::DecodeError& e) {
|
||||
//Handle all kinds of other decode errors
|
||||
//...
|
||||
} catch (const jwt::VerificationError& e) {
|
||||
// Handle the base verification error.
|
||||
//NOTE: There are other derived types of verification errors
|
||||
// which will be discussed in next topic.
|
||||
} catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Invalid issuer test(uses error_code):
|
||||
```cpp
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
assert (!ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), issuer("arun.muralidharan"));
|
||||
assert (ec);
|
||||
|
||||
assert (ec.value() == static_cast<int>(jwt::VerificationErrc::InvalidIssuer));
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Error Codes & Exceptions
|
||||
The library as we saw earlier supports error reporting via both exceptions and error_code.
|
||||
|
||||
<strong>Error codes:</strong>
|
||||
|
||||
The error codes are divided into different categories:
|
||||
- Algorithm Errors
|
||||
|
||||
Used for reporting errors at the time of encoding / signature creation.
|
||||
```cpp
|
||||
enum class AlgorithmErrc
|
||||
{
|
||||
SigningErr = 1,
|
||||
VerificationErr,
|
||||
KeyNotFoundErr,
|
||||
NoneAlgorithmUsed, // Not an actual error!
|
||||
};
|
||||
```
|
||||
|
||||
<strong>NOTE:</strong> <code>NoneAlgorithmUsed</code> will be set in the error_code, but it usually should not be treated as a hard error when NONE algorithm is used intentionally.
|
||||
|
||||
- Decode Errors
|
||||
|
||||
Used for reporting errors at the time of decoding. Different categories of decode errors are:
|
||||
```cpp
|
||||
enum class DecodeErrc
|
||||
{
|
||||
// No algorithms provided in decode API
|
||||
EmptyAlgoList = 1,
|
||||
// The JWT signature has incorrect format
|
||||
SignatureFormatError,
|
||||
// The JSON library failed to parse
|
||||
JsonParseError,
|
||||
// Algorithm field in header is missing
|
||||
AlgHeaderMiss,
|
||||
// Type field in header is missing
|
||||
TypHeaderMiss,
|
||||
// Unexpected type field value
|
||||
TypMismatch,
|
||||
// Found duplicate claims
|
||||
DuplClaims,
|
||||
// Key/Secret not passed as decode argument
|
||||
KeyNotPresent,
|
||||
// Key/secret passed as argument for NONE algorithm.
|
||||
// Not a hard error.
|
||||
KeyNotRequiredForNoneAlg,
|
||||
};
|
||||
```
|
||||
|
||||
- Verification errors
|
||||
|
||||
Used for reporting verification errors when the verification falg is set to true in decode API.
|
||||
Different categories of decode errors are:
|
||||
```cpp
|
||||
enum class VerificationErrc
|
||||
{
|
||||
//Algorithms provided does not match with header
|
||||
InvalidAlgorithm = 1,
|
||||
//Token is expired at the time of decoding
|
||||
TokenExpired,
|
||||
//The issuer specified does not match with payload
|
||||
InvalidIssuer,
|
||||
//The subject specified does not match with payload
|
||||
InvalidSubject,
|
||||
//The field IAT is not present or is of invalid type
|
||||
InvalidIAT,
|
||||
//Checks for the existence of JTI
|
||||
//if validate_jti is passed in decode
|
||||
InvalidJTI,
|
||||
//The audience specified dowes not match with payload
|
||||
InvalidAudience,
|
||||
//Decoded before nbf time
|
||||
ImmatureSignature,
|
||||
//Signature match error
|
||||
InvalidSignature,
|
||||
// Invalid value type used for known claims
|
||||
TypeConversionError,
|
||||
};
|
||||
```
|
||||
|
||||
<strong>Exceptions:</strong>
|
||||
There are exception types created for almost all the error codes above.
|
||||
|
||||
- MemoryAllocationException
|
||||
|
||||
Derived from <code>std::bad_alloc</code>. Thrown for memory allocation errors in OpenSSL C API.
|
||||
|
||||
- SigningError
|
||||
|
||||
Derived from <code>std::runtime_error</code>. Thrown for failures in OpenSSL APIs while signing.
|
||||
|
||||
- DecodeError
|
||||
|
||||
Derived from <code>std::runtime_error</code>. Base class for all decoding related exceptions.
|
||||
|
||||
- SignatureFormatError
|
||||
|
||||
Thrown if the format of the signature is not as expected.
|
||||
|
||||
- KeyNotPresentError
|
||||
|
||||
Thrown if key/secret is not passed in with the decode API if the algorithm used is something other than "none".
|
||||
|
||||
- VerificationError
|
||||
|
||||
Derived from <code>std::runtime_error</code>. Base class exception for all kinds of verification errors. Verification errors are thrown only when the verify decode parameter is set to true.
|
||||
|
||||
- InvalidAlgorithmError
|
||||
- TokenExpiredError
|
||||
- InvalidIssuerError
|
||||
- InvalidAudienceError
|
||||
- InvalidSubjectError
|
||||
- InvalidIATError
|
||||
- InvalidJTIError
|
||||
- ImmatureSignatureError
|
||||
- InvalidSignatureError
|
||||
- TypeConversionError
|
||||
|
||||
NOTE: See the error code section for explanation on above verification errors or checkout <code>exceptions.hpp</code> header for more details.
|
||||
|
||||
|
||||
## Additional Header Data
|
||||
Generally the header consists only of `type` and `algorithm` fields. But there could be a need to add additional header fields. For example, to provide some kind of hint about what algorithm was used to sign the JWT. Checkout JOSE header section in <a href="https://tools.ietf.org/html/rfc7515">RFC-7515</a>.
|
||||
|
||||
The library provides APIs to do that as well.
|
||||
|
||||
```cpp
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{
|
||||
headers({
|
||||
{"alg", "none"},
|
||||
{"typ", "jwt"},
|
||||
}),
|
||||
payload({
|
||||
{"iss", "arun.muralidharan"},
|
||||
{"sub", "nsfw"},
|
||||
{"x-pld", "not my ex"}
|
||||
})
|
||||
};
|
||||
|
||||
bool ret = obj.header().add_header("kid", 1234567);
|
||||
assert (ret);
|
||||
|
||||
ret = obj.header().add_header("crit", std::array<std::string, 1>{"exp"});
|
||||
assert (ret);
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"none"}), ec, verify(false));
|
||||
|
||||
// Should not be a hard error in general
|
||||
assert (ec.value() == static_cast<int>(jwt::AlgorithmErrc::NoneAlgorithmUsed));
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Things for improvement
|
||||
Many things!
|
||||
Encoding and decoding JWT is fairly a simple task and could be done in a single source file. I have tried my best to get the APIs and design correct in how much ever time I could give for this project. Still, there are quite a few places (or all the places :( ? ) where things are not correct or may not be the best approach.
|
||||
|
||||
With C++, it is pretty easy to go overboard and create something very difficult or something very straightforward (not worth to be a library). My intention was to make a sane library easier for end users to use while also making the life of someone reading the source have fairly good time debugging some issue.
|
||||
|
||||
Things one may have questions about
|
||||
- There is a string_view implementation. Why not use <code>boost::string_ref</code> ?
|
||||
|
||||
Sorry, I love boost! But, do not want it to be part of dependency.
|
||||
If you use C++17 or greater `std::string_view` gets used instead and `jwt::string_view` implementation does not get included.
|
||||
|
||||
- You are not using the stack allocator or the shart string anywhere. Why to include it then ?
|
||||
|
||||
I will be using it in few places where I am sure I need not use `std::string` especially in the signing code.
|
||||
|
||||
- Why the complete `nlohmann JSON` is part of your library ?
|
||||
|
||||
Honestly did not know any better way. I know there are ways to use third party github repositories, but I do not know how to do that. Once I figure that out, I may move it out.
|
||||
|
||||
- Am I bound to use `nlohmann JSON` ? Can I use some other JSON library ?
|
||||
|
||||
As of now, ys. You cannot use any other JSON library unless you change the code. I would have liked to provide some adaptors for JSON interface. Perhaps in future, if required.
|
||||
|
||||
- Error codes and exceptions....heh?
|
||||
|
||||
Yeah, I often wonder if that was the right approach. I could have just stuck with error codes and be happy. But that was a good learning time for me.
|
||||
|
||||
- Where to find more about the usage ?
|
||||
|
||||
Checkout the tests. It has examples for all the algorithms which are supported.
|
||||
|
||||
- Support for C++11 seems trivial based on the changes required. Why not support C+11 then ?
|
||||
|
||||
Its 2018 now! If I ever start getting requests to have support for C++11, then I will surely consider it.
|
||||
|
||||
- The Metaprogramming concept checks for Sequence and Mapping looks sad.
|
||||
|
||||
Yeah I know. Just hacked something very basic.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
10
externals/cpp-jwt/cmake/Config.cmake.in
vendored
Executable file
10
externals/cpp-jwt/cmake/Config.cmake.in
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if(NOT @CPP_JWT_USE_VENDORED_NLOHMANN_JSON@)
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
1
externals/cpp-jwt/cmake_command
vendored
Executable file
1
externals/cpp-jwt/cmake_command
vendored
Executable file
@@ -0,0 +1 @@
|
||||
cmake -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2j -DGTEST_ROOT=$HOME/googletest
|
10
externals/cpp-jwt/conanfile.txt
vendored
Executable file
10
externals/cpp-jwt/conanfile.txt
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
[requires]
|
||||
gtest/1.10.0
|
||||
nlohmann_json/3.7.0
|
||||
openssl/1.1.1d
|
||||
|
||||
[generators]
|
||||
cmake_find_package
|
||||
cmake_paths
|
||||
|
||||
[options]
|
22
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/DependInfo.cmake
vendored
Executable file
22
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/DependInfo.cmake
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
# The set of languages for which implicit dependencies are needed:
|
||||
set(CMAKE_DEPENDS_LANGUAGES
|
||||
"CXX"
|
||||
)
|
||||
# The set of files for implicit dependencies of each language:
|
||||
set(CMAKE_DEPENDS_CHECK_CXX
|
||||
"/Users/amuralid/dev_test/cpp-jwt/examples/simple_ex1.cc" "/Users/amuralid/dev_test/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/simple_ex1.cc.o"
|
||||
)
|
||||
set(CMAKE_CXX_COMPILER_ID "Clang")
|
||||
|
||||
# The include file search paths:
|
||||
set(CMAKE_CXX_TARGET_INCLUDE_PATH
|
||||
"include"
|
||||
"/usr/local/Cellar/openssl/1.0.2j/include"
|
||||
)
|
||||
|
||||
# Targets to which this target links.
|
||||
set(CMAKE_TARGET_LINKED_INFO_FILES
|
||||
)
|
||||
|
||||
# Fortran module output directory.
|
||||
set(CMAKE_Fortran_TARGET_MODULE_DIR "")
|
10
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/cmake_clean.cmake
vendored
Executable file
10
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/cmake_clean.cmake
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
file(REMOVE_RECURSE
|
||||
"CMakeFiles/simple_ex1.dir/simple_ex1.cc.o"
|
||||
"simple_ex1.pdb"
|
||||
"simple_ex1"
|
||||
)
|
||||
|
||||
# Per-language clean rules from dependency scanning.
|
||||
foreach(lang CXX)
|
||||
include(CMakeFiles/simple_ex1.dir/cmake_clean_${lang}.cmake OPTIONAL)
|
||||
endforeach()
|
3
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/progress.make
vendored
Executable file
3
externals/cpp-jwt/examples/CMakeFiles/simple_ex1.dir/progress.make
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
CMAKE_PROGRESS_1 = 1
|
||||
CMAKE_PROGRESS_2 = 2
|
||||
|
24
externals/cpp-jwt/examples/CMakeLists.txt
vendored
Executable file
24
externals/cpp-jwt/examples/CMakeLists.txt
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
set(CERT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/rsa_256")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -DCERT_ROOT_DIR=\"\\\"${CERT_ROOT_DIR}\\\"\"")
|
||||
|
||||
add_executable(simple_ex1 simple_ex1.cc)
|
||||
target_link_libraries(simple_ex1 ${PROJECT_NAME})
|
||||
add_test(
|
||||
NAME simple_ex1
|
||||
COMMAND ./simple_ex1
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(simple_ex2 simple_ex2.cc)
|
||||
target_link_libraries(simple_ex2 ${PROJECT_NAME})
|
||||
add_test(
|
||||
NAME simple_ex2
|
||||
COMMAND ./simple_ex2
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(simple_ex3_rsa simple_ex3_rsa.cc)
|
||||
target_link_libraries(simple_ex3_rsa ${PROJECT_NAME})
|
||||
add_test(
|
||||
NAME simple_ex3_rsa
|
||||
COMMAND ./simple_ex3_rsa
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
15
externals/cpp-jwt/examples/rsa_256/jwtRS256.key
vendored
Executable file
15
externals/cpp-jwt/examples/rsa_256/jwtRS256.key
vendored
Executable file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQC4fkg/JYyN3Skr6RYLiAd/Yhl02TE3/HzHSNPnCaRdUakGp9og
|
||||
7oXBMcoadFDjnoSq1sz+gUHnpoO7s2fwkD5Q4OnCBGD3oKP2A4PlOOWD2B2cVmMq
|
||||
X/vf1nAA/343496jsbfgkh1Q7LTzR0IXfdii0o1UCbvrVCuaBoyiv4TxWQIDAQAB
|
||||
AoGAWA5uDTWu0Ecuz3aAvyA9896up8bCZyZrp/JqsWs4uBGxyytyQSWXUY6iF95M
|
||||
fVe7mo7LaO3ottgTKBOJGJjAJKnfwXRn8/NV/Q5oHx48sPGDoUUtyMrRbZpeLM1L
|
||||
gpFX715XWrtALInWPlVG1OfkQQLv4K7mwveM0cez0bWPUsECQQDuPK9IL7WuO2WR
|
||||
s6pGEHBc3/MMk6I+vqJ+rJMgJjCC/Wjeyo6U3xTNipJRJL5L/Y8iMqpWCrYOjpo8
|
||||
+1p4FXqDAkEAxj/FcVhXl3NMco6D9u0LxTAmqavMzmXDmODVW2m1K3+rQWQDqXqr
|
||||
FQ9WQq0LSsqiwRul6hrd0EmCkNJqpCMN8wJBAIz06uDTGbPVAOuMWhrKbzEEcFHo
|
||||
p/5n3M0GXqaO8fUO6pWnU2VR+IUEkD3id5WOmLmrMI1oGP/T7/5U2dpjGvECQEBq
|
||||
0k4tJXEJvupuUoT2q19scPOq5kaenHrde5ZTd9HljxEVXXdBa7vRGvdZYRTxWQck
|
||||
Y7n49uBKMom6RXqGBW8CQQCrnub4stg6dwdpnmZmEtAE4VqNSZeV5UWz7+l7+R+B
|
||||
ENtNlIgyQfE6NpOc3Fr/uy3IQjaHcOOwIKI0GMJww9sC
|
||||
-----END RSA PRIVATE KEY-----
|
6
externals/cpp-jwt/examples/rsa_256/jwtRS256.key.pub
vendored
Executable file
6
externals/cpp-jwt/examples/rsa_256/jwtRS256.key.pub
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4fkg/JYyN3Skr6RYLiAd/Yhl0
|
||||
2TE3/HzHSNPnCaRdUakGp9og7oXBMcoadFDjnoSq1sz+gUHnpoO7s2fwkD5Q4OnC
|
||||
BGD3oKP2A4PlOOWD2B2cVmMqX/vf1nAA/343496jsbfgkh1Q7LTzR0IXfdii0o1U
|
||||
CbvrVCuaBoyiv4TxWQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
21
externals/cpp-jwt/examples/simple_ex1.cc
vendored
Executable file
21
externals/cpp-jwt/examples/simple_ex1.cc
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
auto key = "secret"; //Secret to use for the algorithm
|
||||
//Create JWT object
|
||||
jwt::jwt_object obj{algorithm("HS256"), payload({{"some", "payload"}}), secret(key)};
|
||||
|
||||
//Get the encoded string/assertion
|
||||
auto enc_str = obj.signature();
|
||||
std::cout << enc_str << std::endl;
|
||||
|
||||
//Decode
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret(key));
|
||||
std::cout << dec_obj.header() << std::endl;
|
||||
std::cout << dec_obj.payload() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
48
externals/cpp-jwt/examples/simple_ex2.cc
vendored
Executable file
48
externals/cpp-jwt/examples/simple_ex2.cc
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"user", "admin"}})};
|
||||
|
||||
//Use add_claim API to add claim values which are
|
||||
// _not_ strings.
|
||||
// For eg: `iat` and `exp` claims below.
|
||||
// Other claims could have been added in the payload
|
||||
// function above as they are just stringy things.
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "test")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
.add_claim("exp", std::chrono::system_clock::now() + std::chrono::seconds{10})
|
||||
;
|
||||
|
||||
//Use `has_claim` to check if the claim exists or not
|
||||
assert (obj.has_claim("iss"));
|
||||
assert (obj.has_claim("exp"));
|
||||
|
||||
//Use `has_claim_with_value` to check if the claim exists
|
||||
//with a specific value or not.
|
||||
assert (obj.payload().has_claim_with_value("id", "a-b-c-d-e-f-1-2-3"));
|
||||
assert (obj.payload().has_claim_with_value("iat", 1513862371));
|
||||
|
||||
//Remove a claim using `remove_claim` API.
|
||||
//Most APIs have an overload which takes enum class type as well
|
||||
//It can be used interchangeably with strings.
|
||||
obj.remove_claim(jwt::registered_claims::expiration);
|
||||
assert (!obj.has_claim("exp"));
|
||||
|
||||
//Using `add_claim` with extra features.
|
||||
//Check return status and overwrite
|
||||
assert (!obj.payload().add_claim("sub", "new test", false/*overwrite*/));
|
||||
|
||||
// Overwrite an existing claim
|
||||
assert (obj.payload().add_claim("sub", "new test", true/*overwrite*/));
|
||||
|
||||
assert (obj.payload().has_claim_with_value("sub", "new test"));
|
||||
|
||||
return 0;
|
||||
}
|
82
externals/cpp-jwt/examples/simple_ex3_rsa.cc
vendored
Executable file
82
externals/cpp-jwt/examples/simple_ex3_rsa.cc
vendored
Executable file
@@ -0,0 +1,82 @@
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
/***
|
||||
* STEPS TO GENERATE RSA PRIVATE PUBLIC KEYPAIR.
|
||||
*
|
||||
* 1. openssl genrsa -out jwtRS256.key 1024
|
||||
* 2. openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
|
||||
*/
|
||||
|
||||
std::string read_from_file(const std::string& path)
|
||||
{
|
||||
std::string contents;
|
||||
std::ifstream is{path, std::ifstream::binary};
|
||||
|
||||
if (is) {
|
||||
// get length of file:
|
||||
is.seekg (0, is.end);
|
||||
auto length = is.tellg();
|
||||
is.seekg (0, is.beg);
|
||||
contents.resize(length);
|
||||
|
||||
is.read(&contents[0], length);
|
||||
if (!is) {
|
||||
is.close();
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
std::cerr << "FILE not FOUND!!" << std::endl;
|
||||
}
|
||||
|
||||
is.close();
|
||||
return contents;
|
||||
}
|
||||
|
||||
int main() {
|
||||
using namespace jwt::params;
|
||||
const std::string priv_key_path = std::string{CERT_ROOT_DIR} + "/jwtRS256.key";
|
||||
const std::string pub_key_path = std::string{CERT_ROOT_DIR} + "/jwtRS256.key.pub";
|
||||
|
||||
auto priv_key = read_from_file(priv_key_path);
|
||||
|
||||
jwt::jwt_object obj{algorithm("RS256"), secret(priv_key), payload({{"user", "admin"}})};
|
||||
|
||||
//Use add_claim API to add claim values which are
|
||||
// _not_ strings.
|
||||
// For eg: `iat` and `exp` claims below.
|
||||
// Other claims could have been added in the payload
|
||||
// function above as they are just stringy things.
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "test")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
.add_claim("exp", std::chrono::system_clock::now() + std::chrono::seconds{10})
|
||||
;
|
||||
|
||||
//Use `has_claim` to check if the claim exists or not
|
||||
assert (obj.has_claim("iss"));
|
||||
assert (obj.has_claim("exp"));
|
||||
|
||||
//Use `has_claim_with_value` to check if the claim exists
|
||||
//with a specific value or not.
|
||||
assert (obj.payload().has_claim_with_value("id", "a-b-c-d-e-f-1-2-3"));
|
||||
assert (obj.payload().has_claim_with_value("iat", 1513862371));
|
||||
|
||||
auto pub_key = read_from_file(pub_key_path);
|
||||
|
||||
std::error_code ec{};
|
||||
auto sign = obj.signature(ec);
|
||||
if (ec) {
|
||||
std::cerr << ec.message() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto dec_obj = jwt::decode(sign, algorithms({"RS256"}), verify(false), secret(pub_key));
|
||||
|
||||
return 0;
|
||||
}
|
557
externals/cpp-jwt/include/jwt/algorithm.hpp
vendored
Executable file
557
externals/cpp-jwt/include/jwt/algorithm.hpp
vendored
Executable file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ALGORITHM_HPP
|
||||
#define CPP_JWT_ALGORITHM_HPP
|
||||
|
||||
/*!
|
||||
* Most of the signing and verification code has been taken
|
||||
* and modified for C++ specific use from the C implementation
|
||||
* JWT library, libjwt.
|
||||
* https://github.com/benmcollins/libjwt/tree/master/libjwt
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <system_error>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#include "jwt/assertions.hpp"
|
||||
#include "jwt/exceptions.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
#include "jwt/error_codes.hpp"
|
||||
#include "jwt/base64.hpp"
|
||||
#include "jwt/config.hpp"
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/// The result type of the signing function
|
||||
using sign_result_t = std::pair<std::string, std::error_code>;
|
||||
/// The result type of verification function
|
||||
using verify_result_t = std::pair<bool, std::error_code>;
|
||||
/// The function pointer type for the signing function
|
||||
using sign_func_t = sign_result_t (*) (const jwt::string_view key,
|
||||
const jwt::string_view data);
|
||||
/// The function pointer type for the verifying function
|
||||
using verify_func_t = verify_result_t (*) (const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign);
|
||||
|
||||
namespace algo {
|
||||
|
||||
//Me: TODO: All these can be done using code generaion.
|
||||
//Me: NO. NEVER. I hate Macros.
|
||||
//Me: You can use templates too.
|
||||
//Me: No. I would rather prefer explicit.
|
||||
//Me: Ok. You win.
|
||||
//Me: Same to you.
|
||||
|
||||
/**
|
||||
* HS256 algorithm.
|
||||
*/
|
||||
struct HS256
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HS384 algorithm.
|
||||
*/
|
||||
struct HS384
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* HS512 algorithm.
|
||||
*/
|
||||
struct HS512
|
||||
{
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* NONE algorithm.
|
||||
*/
|
||||
struct NONE
|
||||
{
|
||||
void operator()() noexcept
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS256 algorithm.
|
||||
*/
|
||||
struct RS256
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS384 algorithm.
|
||||
*/
|
||||
struct RS384
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RS512 algorithm.
|
||||
*/
|
||||
struct RS512
|
||||
{
|
||||
static const int type = EVP_PKEY_RSA;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES256 algorithm.
|
||||
*/
|
||||
struct ES256
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha256();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES384 algorithm.
|
||||
*/
|
||||
struct ES384
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha384();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ES512 algorithm.
|
||||
*/
|
||||
struct ES512
|
||||
{
|
||||
static const int type = EVP_PKEY_EC;
|
||||
|
||||
const EVP_MD* operator()() noexcept
|
||||
{
|
||||
return EVP_sha512();
|
||||
}
|
||||
};
|
||||
|
||||
} //END Namespace algo
|
||||
|
||||
|
||||
/**
|
||||
* JWT signing algorithm types.
|
||||
*/
|
||||
enum class algorithm
|
||||
{
|
||||
NONE = 0,
|
||||
HS256,
|
||||
HS384,
|
||||
HS512,
|
||||
RS256,
|
||||
RS384,
|
||||
RS512,
|
||||
ES256,
|
||||
ES384,
|
||||
ES512,
|
||||
UNKN,
|
||||
TERM,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Convert the algorithm enum class type to
|
||||
* its stringified form.
|
||||
*/
|
||||
inline jwt::string_view alg_to_str(SCOPED_ENUM algorithm alg) noexcept
|
||||
{
|
||||
switch (alg) {
|
||||
case algorithm::HS256: return "HS256";
|
||||
case algorithm::HS384: return "HS384";
|
||||
case algorithm::HS512: return "HS512";
|
||||
case algorithm::RS256: return "RS256";
|
||||
case algorithm::RS384: return "RS384";
|
||||
case algorithm::RS512: return "RS512";
|
||||
case algorithm::ES256: return "ES256";
|
||||
case algorithm::ES384: return "ES384";
|
||||
case algorithm::ES512: return "ES512";
|
||||
case algorithm::TERM: return "TERM";
|
||||
case algorithm::NONE: return "NONE";
|
||||
case algorithm::UNKN: return "UNKN";
|
||||
default: assert (0 && "Unknown Algorithm");
|
||||
};
|
||||
return "UNKN";
|
||||
JWT_NOT_REACHED("Code not reached");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert stringified algorithm to enum class.
|
||||
* The string comparison is case insesitive.
|
||||
*/
|
||||
inline SCOPED_ENUM algorithm str_to_alg(const jwt::string_view alg) noexcept
|
||||
{
|
||||
if (!alg.length()) return algorithm::UNKN;
|
||||
|
||||
if (!strcasecmp(alg.data(), "NONE")) return algorithm::NONE;
|
||||
if (!strcasecmp(alg.data(), "HS256")) return algorithm::HS256;
|
||||
if (!strcasecmp(alg.data(), "HS384")) return algorithm::HS384;
|
||||
if (!strcasecmp(alg.data(), "HS512")) return algorithm::HS512;
|
||||
if (!strcasecmp(alg.data(), "RS256")) return algorithm::RS256;
|
||||
if (!strcasecmp(alg.data(), "RS384")) return algorithm::RS384;
|
||||
if (!strcasecmp(alg.data(), "RS512")) return algorithm::RS512;
|
||||
if (!strcasecmp(alg.data(), "ES256")) return algorithm::ES256;
|
||||
if (!strcasecmp(alg.data(), "ES384")) return algorithm::ES384;
|
||||
if (!strcasecmp(alg.data(), "ES512")) return algorithm::ES512;
|
||||
|
||||
return algorithm::UNKN;
|
||||
|
||||
JWT_NOT_REACHED("Code not reached");
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void bio_deletor(BIO* ptr)
|
||||
{
|
||||
if (ptr) BIO_free_all(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void evp_md_ctx_deletor(EVP_MD_CTX* ptr)
|
||||
{
|
||||
if (ptr) EVP_MD_CTX_destroy(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ec_key_deletor(EC_KEY* ptr)
|
||||
{
|
||||
if (ptr) EC_KEY_free(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ec_sig_deletor(ECDSA_SIG* ptr)
|
||||
{
|
||||
if (ptr) ECDSA_SIG_free(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline void ev_pkey_deletor(EVP_PKEY* ptr)
|
||||
{
|
||||
if (ptr) EVP_PKEY_free(ptr);
|
||||
}
|
||||
|
||||
/// Useful typedefs
|
||||
using bio_deletor_t = decltype(&bio_deletor);
|
||||
using BIO_uptr = std::unique_ptr<BIO, bio_deletor_t>;
|
||||
|
||||
using evp_mdctx_deletor_t = decltype(&evp_md_ctx_deletor);
|
||||
using EVP_MDCTX_uptr = std::unique_ptr<EVP_MD_CTX, evp_mdctx_deletor_t>;
|
||||
|
||||
using eckey_deletor_t = decltype(&ec_key_deletor);
|
||||
using EC_KEY_uptr = std::unique_ptr<EC_KEY, eckey_deletor_t>;
|
||||
|
||||
using ecsig_deletor_t = decltype(&ec_sig_deletor);
|
||||
using EC_SIG_uptr = std::unique_ptr<ECDSA_SIG, ecsig_deletor_t>;
|
||||
|
||||
using evpkey_deletor_t = decltype(&ev_pkey_deletor);
|
||||
using EC_PKEY_uptr = std::unique_ptr<EVP_PKEY, evpkey_deletor_t>;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OpenSSL HMAC based signature and verfication.
|
||||
*
|
||||
* The template type `Hasher` takes the type representing
|
||||
* the HMAC algorithm type from the `jwt::algo` namespace.
|
||||
*
|
||||
* The struct is specialized for NONE algorithm. See the
|
||||
* details of that class as well.
|
||||
*/
|
||||
template <typename Hasher>
|
||||
struct HMACSign
|
||||
{
|
||||
/// The type of Hashing algorithm
|
||||
using hasher_type = Hasher;
|
||||
|
||||
/**
|
||||
* Signs the input using the HMAC algorithm using the
|
||||
* provided key.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The secret/key to use for the signing.
|
||||
* Cannot be empty string.
|
||||
* @data : The data to be signed.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure will result in jwt::MemoryAllocationException
|
||||
* being thrown.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
std::string sign;
|
||||
sign.resize(EVP_MAX_MD_SIZE);
|
||||
std::error_code ec{};
|
||||
|
||||
uint32_t len = 0;
|
||||
|
||||
unsigned char* res = HMAC(Hasher{}(),
|
||||
key.data(),
|
||||
static_cast<int>(key.length()),
|
||||
reinterpret_cast<const unsigned char*>(data.data()),
|
||||
data.length(),
|
||||
reinterpret_cast<unsigned char*>(&sign[0]),
|
||||
&len);
|
||||
if (!res) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
}
|
||||
|
||||
sign.resize(len);
|
||||
return { std::move(sign), ec };
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the JWT string against the signature using
|
||||
* the provided key.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The secret/key to use for the signing.
|
||||
* Cannot be empty string.
|
||||
* @head : The part of JWT encoded string representing header
|
||||
* and the payload claims.
|
||||
* @sign : The signature part of the JWT encoded string.
|
||||
*
|
||||
* Returns:
|
||||
* verify_result_t
|
||||
* verify_result_t::first set to true if verification succeeds.
|
||||
* false otherwise.
|
||||
* verify_result_t::second set to relevant error if verification fails.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure will result in jwt::MemoryAllocationException
|
||||
* being thrown.
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of `HMACSign` class
|
||||
* for NONE algorithm.
|
||||
*
|
||||
* This specialization is selected for even
|
||||
* PEM based algorithms.
|
||||
*
|
||||
* The signing and verification APIs are
|
||||
* basically no-op except that they would
|
||||
* set the relevant error code.
|
||||
*
|
||||
* NOTE: error_code would be set in the case
|
||||
* of usage of NONE algorithm.
|
||||
* Users of this API are expected to check for
|
||||
* the case explicitly.
|
||||
*/
|
||||
template <>
|
||||
struct HMACSign<algo::NONE>
|
||||
{
|
||||
using hasher_type = algo::NONE;
|
||||
|
||||
/**
|
||||
* Basically a no-op. Sets the error code to NoneAlgorithmUsed.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
(void)key;
|
||||
(void)data;
|
||||
std::error_code ec{};
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
|
||||
return { std::string{}, ec };
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically a no-op. Sets the error code to NoneAlgorithmUsed.
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign)
|
||||
{
|
||||
(void)key;
|
||||
(void)head;
|
||||
(void)sign;
|
||||
std::error_code ec{};
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
|
||||
return { true, ec };
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OpenSSL PEM based signature and verfication.
|
||||
*
|
||||
* The template type `Hasher` takes the type representing
|
||||
* the PEM algorithm type from the `jwt::algo` namespace.
|
||||
*
|
||||
* For NONE algorithm, HMACSign<> specialization is used.
|
||||
* See that for more details.
|
||||
*/
|
||||
template <typename Hasher>
|
||||
struct PEMSign
|
||||
{
|
||||
public:
|
||||
/// The type of Hashing algorithm
|
||||
using hasher_type = Hasher;
|
||||
|
||||
/**
|
||||
* Signs the input data using PEM encryption algorithm.
|
||||
*
|
||||
* Arguments:
|
||||
* @key : The key/secret to be used for signing.
|
||||
* Cannot be an empty string.
|
||||
* @data: The data to be signed.
|
||||
*
|
||||
* Exceptions:
|
||||
* Any allocation failure would be thrown out as
|
||||
* jwt::MemoryAllocationException.
|
||||
*/
|
||||
static sign_result_t sign(const jwt::string_view key, const jwt::string_view data)
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
std::string ii{data.data(), data.length()};
|
||||
|
||||
EC_PKEY_uptr pkey{load_key(key, ec), ev_pkey_deletor};
|
||||
if (ec) return { std::string{}, ec };
|
||||
|
||||
//TODO: Use stack string here ?
|
||||
std::string sign = evp_digest(pkey.get(), data, ec);
|
||||
|
||||
if (ec) return { std::string{}, ec };
|
||||
|
||||
if (Hasher::type == EVP_PKEY_EC) {
|
||||
sign = public_key_ser(pkey.get(), sign, ec);
|
||||
}
|
||||
|
||||
return { std::move(sign), ec };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
static verify_result_t
|
||||
verify(const jwt::string_view key, const jwt::string_view head, const jwt::string_view sign);
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
*/
|
||||
static EVP_PKEY* load_key(const jwt::string_view key, std::error_code& ec);
|
||||
|
||||
/*!
|
||||
*/
|
||||
static std::string evp_digest(EVP_PKEY* pkey, const jwt::string_view data, std::error_code& ec);
|
||||
|
||||
/*!
|
||||
*/
|
||||
static std::string public_key_ser(EVP_PKEY* pkey, jwt::string_view sign, std::error_code& ec);
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L
|
||||
|
||||
|
||||
//ATTN: Below 2 functions
|
||||
//are Taken from https://github.com/nginnever/zogminer/issues/39
|
||||
|
||||
/**
|
||||
*/
|
||||
static void ECDSA_SIG_get0(const ECDSA_SIG* sig, const BIGNUM** pr, const BIGNUM** ps)
|
||||
{
|
||||
if (pr != nullptr) *pr = sig->r;
|
||||
if (ps != nullptr) *ps = sig->s;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
static int ECDSA_SIG_set0(ECDSA_SIG* sig, BIGNUM* r, BIGNUM* s)
|
||||
{
|
||||
if (r == nullptr || s == nullptr) return 0;
|
||||
|
||||
BN_clear_free(sig->r);
|
||||
BN_clear_free(sig->s);
|
||||
|
||||
sig->r = r;
|
||||
sig->s = s;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/algorithm.ipp"
|
||||
|
||||
|
||||
#endif
|
51
externals/cpp-jwt/include/jwt/assertions.hpp
vendored
Executable file
51
externals/cpp-jwt/include/jwt/assertions.hpp
vendored
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ASSERTIONS_HPP
|
||||
#define CPP_JWT_ASSERTIONS_HPP
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
#if defined(__clang__)
|
||||
# define JWT_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
#elif defined(__GNUC__)
|
||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
# define JWT_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define JWT_NOT_REACHED_MARKER() __assume(0)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
# define JWT_NOT_REACHED(reason) do { \
|
||||
assert (0 && reason); \
|
||||
JWT_NOT_REACHED_MARKER(); \
|
||||
} while (0)
|
||||
#else
|
||||
# define JWT_NOT_REACHED(reason) JWT_NOT_REACHED_MARKER()
|
||||
#endif
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
335
externals/cpp-jwt/include/jwt/base64.hpp
vendored
Executable file
335
externals/cpp-jwt/include/jwt/base64.hpp
vendored
Executable file
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_BASE64_HPP
|
||||
#define CPP_JWT_BASE64_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include "jwt/config.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
namespace jwt {
|
||||
|
||||
// Returns the maximum number of bytes required to
|
||||
// encode an input byte string of length `n` to base64.
|
||||
inline constexpr
|
||||
size_t encoding_size(size_t n)
|
||||
{
|
||||
return 4 * ((n + 2) / 3);
|
||||
}
|
||||
|
||||
|
||||
// Returns the maximum number of bytes required
|
||||
// to store a decoded base64 byte string.
|
||||
inline constexpr
|
||||
size_t decoding_size(size_t n)
|
||||
{
|
||||
return n / 4 * 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding map.
|
||||
* A constexpr helper class for performing base64
|
||||
* encoding on the input byte string.
|
||||
*/
|
||||
class EMap
|
||||
{
|
||||
public:
|
||||
constexpr EMap() = default;
|
||||
|
||||
public:
|
||||
constexpr char at(size_t pos) const noexcept
|
||||
{
|
||||
return X_ASSERT(pos < chars_.size()), chars_.at(pos);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<char, 64> chars_ = {{
|
||||
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
|
||||
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'+','/',
|
||||
}};
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes a sequence of octet into base64 string.
|
||||
* Returns std::string resized to contain only the
|
||||
* encoded data (as usual without null terminator).
|
||||
*
|
||||
* The encoded string is atleast `encoding_size(input len)`
|
||||
* in size.
|
||||
*
|
||||
* Arguments:
|
||||
* @in : Input byte string to be encoded.
|
||||
* @len : Length of the input byte string.
|
||||
*/
|
||||
inline std::string base64_encode(const char* in, size_t len)
|
||||
{
|
||||
std::string result;
|
||||
const auto encoded_siz = encoding_size(len);
|
||||
result.resize(encoded_siz);
|
||||
|
||||
constexpr static const EMap emap{};
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
for (; i < static_cast<int>(len) - 2; i += 3) {
|
||||
const auto first = in[i];
|
||||
const auto second = in[i+1];
|
||||
const auto third = in[i+2];
|
||||
|
||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||
result[j++] = emap.at(((second & 0x0F) << 2) | ((third & 0xC0) >> 6));
|
||||
result[j++] = emap.at( (third & 0x3F) );
|
||||
}
|
||||
|
||||
switch (len % 3) {
|
||||
case 2:
|
||||
{
|
||||
const auto first = in[i];
|
||||
const auto second = in[i+1];
|
||||
|
||||
result[j++] = emap.at( (first >> 2) & 0x3F );
|
||||
result[j++] = emap.at(((first & 0x03) << 4) | ((second & 0xF0) >> 4));
|
||||
result[j++] = emap.at( (second & 0x0F) << 2 );
|
||||
result[j++] = '=';
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
const auto first = in[i];
|
||||
|
||||
result[j++] = emap.at((first >> 2) & 0x3F);
|
||||
result[j++] = emap.at((first & 0x03) << 4);
|
||||
result[j++] = '=';
|
||||
result[j++] = '=';
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
break;
|
||||
};
|
||||
|
||||
result.resize(j);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//======================= Decoder ==========================
|
||||
|
||||
/**
|
||||
* Decoding map.
|
||||
* A helper constexpr class for providing interface
|
||||
* to the decoding map for base64.
|
||||
*/
|
||||
class DMap
|
||||
{
|
||||
public:
|
||||
constexpr DMap() = default;
|
||||
|
||||
public:
|
||||
constexpr signed char at(size_t pos) const noexcept
|
||||
{
|
||||
return X_ASSERT(pos < map_.size()), map_[pos];
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<signed char, 256> map_ = {{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 32-47
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 48-63
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 80-95
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 112-127
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // 240-255
|
||||
}};
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes octet of base64 encoded byte string.
|
||||
*
|
||||
* Returns a std::string with the decoded byte string.
|
||||
*
|
||||
* Arguments:
|
||||
* @in : Encoded base64 byte string.
|
||||
* @len : Length of the encoded input byte string.
|
||||
*/
|
||||
inline std::string base64_decode(const char* in, size_t len)
|
||||
{
|
||||
std::string result;
|
||||
const auto decoded_siz = decoding_size(len);
|
||||
result.resize(decoded_siz);
|
||||
|
||||
int i = 0;
|
||||
size_t bytes_rem = len;
|
||||
size_t bytes_wr = 0;
|
||||
|
||||
constexpr static const DMap dmap{};
|
||||
|
||||
while (bytes_rem > 0 && dmap.at(in[bytes_rem - 1]) == -1) { bytes_rem--; }
|
||||
|
||||
while (bytes_rem > 4)
|
||||
{
|
||||
// Error case in input
|
||||
if (dmap.at(*in) == -1) return result;
|
||||
|
||||
const auto first = dmap.at(in[0]);
|
||||
const auto second = dmap.at(in[1]);
|
||||
const auto third = dmap.at(in[2]);
|
||||
const auto fourth = dmap.at(in[3]);
|
||||
|
||||
result[i] = (first << 2) | (second >> 4);
|
||||
result[i + 1] = (second << 4) | (third >> 2);
|
||||
result[i + 2] = (third << 6) | fourth;
|
||||
|
||||
bytes_rem -= 4;
|
||||
i += 3;
|
||||
in += 4;
|
||||
}
|
||||
bytes_wr = i;
|
||||
|
||||
switch(bytes_rem) {
|
||||
case 4:
|
||||
{
|
||||
const auto third = dmap.at(in[2]);
|
||||
const auto fourth = dmap.at(in[3]);
|
||||
result[i + 2] = (third << 6) | fourth;
|
||||
bytes_wr++;
|
||||
}
|
||||
//FALLTHROUGH
|
||||
case 3:
|
||||
{
|
||||
const auto second = dmap.at(in[1]);
|
||||
const auto third = dmap.at(in[2]);
|
||||
result[i + 1] = (second << 4) | (third >> 2);
|
||||
bytes_wr++;
|
||||
}
|
||||
//FALLTHROUGH
|
||||
case 2:
|
||||
{
|
||||
const auto first = dmap.at(in[0]);
|
||||
const auto second = dmap.at(in[1]);
|
||||
result[i] = (first << 2) | (second >> 4);
|
||||
bytes_wr++;
|
||||
}
|
||||
};
|
||||
|
||||
result.resize(bytes_wr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the base64 encoded byte string URL safe.
|
||||
* Overwrites/skips few URL unsafe characters
|
||||
* from the input sequence.
|
||||
*
|
||||
* Arguments:
|
||||
* @data : Base64 encoded byte string.
|
||||
* @len : Length of the base64 byte string.
|
||||
*
|
||||
* Returns:
|
||||
* Length of the URL safe base64 encoded byte string.
|
||||
*/
|
||||
inline size_t base64_uri_encode(char* data, size_t len) noexcept
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
for (; i < len; ++i) {
|
||||
switch (data[i]) {
|
||||
case '+':
|
||||
data[j++] = '-';
|
||||
break;
|
||||
case '/':
|
||||
data[j++] = '_';
|
||||
break;
|
||||
case '=':
|
||||
break;
|
||||
default:
|
||||
data[j++] = data[i];
|
||||
};
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an input URL safe base64 encoded byte string.
|
||||
*
|
||||
* NOTE: To be used only for decoding URL safe base64 encoded
|
||||
* byte string.
|
||||
*
|
||||
* Arguments:
|
||||
* @data : URL safe base64 encoded byte string.
|
||||
* @len : Length of the input byte string.
|
||||
*/
|
||||
inline std::string base64_uri_decode(const char* data, size_t len)
|
||||
{
|
||||
std::string uri_dec;
|
||||
uri_dec.resize(len + 4);
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i < len; ++i)
|
||||
{
|
||||
switch (data[i]) {
|
||||
case '-':
|
||||
uri_dec[i] = '+';
|
||||
break;
|
||||
case '_':
|
||||
uri_dec[i] = '/';
|
||||
break;
|
||||
default:
|
||||
uri_dec[i] = data[i];
|
||||
};
|
||||
}
|
||||
|
||||
size_t trailer = 4 - (i % 4);
|
||||
if (trailer && trailer < 4) {
|
||||
while (trailer--) {
|
||||
uri_dec[i++] = '=';
|
||||
}
|
||||
}
|
||||
|
||||
return base64_decode(uri_dec.c_str(), uri_dec.length());
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
#endif
|
51
externals/cpp-jwt/include/jwt/config.hpp
vendored
Executable file
51
externals/cpp-jwt/include/jwt/config.hpp
vendored
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2018 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef CPP_JWT_CONFIG_HPP
|
||||
#define CPP_JWT_CONFIG_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
// To hack around Visual Studio error:
|
||||
// error C3431: 'algorithm': a scoped enumeration cannot be redeclared as an unscoped enumeration
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define SCOPED_ENUM enum class
|
||||
#else
|
||||
#define SCOPED_ENUM enum
|
||||
#endif
|
||||
|
||||
// To hack around Visual Studio error
|
||||
// error C3249: illegal statement or sub-expression for 'constexpr' function
|
||||
// Doesn't allow assert to be part of constexpr functions.
|
||||
// Copied the solution as described in:
|
||||
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
|
||||
#if defined NDEBUG
|
||||
# define X_ASSERT(CHECK) void(0)
|
||||
#else
|
||||
# define X_ASSERT(CHECK) \
|
||||
( (CHECK) ? void(0) : []{assert(!#CHECK);}() )
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
236
externals/cpp-jwt/include/jwt/detail/meta.hpp
vendored
Executable file
236
externals/cpp-jwt/include/jwt/detail/meta.hpp
vendored
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef CPP_JWT_META_HPP
|
||||
#define CPP_JWT_META_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
namespace jwt {
|
||||
namespace detail {
|
||||
namespace meta {
|
||||
|
||||
/**
|
||||
* The famous void_t trick.
|
||||
*/
|
||||
template <typename... T>
|
||||
struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
using void_t = typename make_void<T...>::type;
|
||||
|
||||
/**
|
||||
* A type tag representing an empty tag.
|
||||
* To be used to represent a `result-not-found`
|
||||
* situation.
|
||||
*/
|
||||
struct empty_type {};
|
||||
|
||||
/**
|
||||
* A type list.
|
||||
*/
|
||||
template <typename... T> struct list{};
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct has_create_json_obj_member: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_create_json_obj_member<T,
|
||||
void_t<
|
||||
decltype(
|
||||
std::declval<T&&>().create_json_obj(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the type `T` models MappingConcept.
|
||||
*
|
||||
* Requirements on type `T` for matching the requirements:
|
||||
* a. Must be able to construct jwt::string_view from the
|
||||
* `key_type` of the map.
|
||||
* b. Must be able to construct jwt::string_view from the
|
||||
* `mapped_type` of the map.
|
||||
* c. The type `T` must have an access operator i.e. operator[].
|
||||
* d. The type `T` must have `begin` and `end` member functions
|
||||
* for iteration.
|
||||
*
|
||||
* NOTE: Requirements `a` and `b` means that the concept
|
||||
* type can only hold values that are string or constructible
|
||||
* to form a string_view (basically C strings and std::string)
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_mapping_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_mapping_concept<T,
|
||||
void_t<
|
||||
typename std::enable_if<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::key_type>::value,
|
||||
void
|
||||
>::type,
|
||||
|
||||
typename std::enable_if<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::mapped_type>::value,
|
||||
void
|
||||
>::type,
|
||||
|
||||
decltype(
|
||||
std::declval<T&>().operator[](std::declval<typename std::remove_reference_t<T>::key_type>()),
|
||||
std::declval<T&>().begin(),
|
||||
std::declval<T&>().end(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the type `T` models the ParameterConcept.
|
||||
*
|
||||
* Requirements on type `T` for matching the requirements:
|
||||
* a. The type must have a `get` method.
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_parameter_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_parameter_concept<T,
|
||||
void_t<
|
||||
decltype(
|
||||
std::declval<T&>().get(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Models SequenceConcept
|
||||
*/
|
||||
template <typename T, typename=void>
|
||||
struct is_sequence_concept: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
/// For array types
|
||||
template <typename T>
|
||||
struct is_sequence_concept<T,
|
||||
void_t<
|
||||
std::enable_if_t<std::is_array<std::decay_t<T>>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view,
|
||||
std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>>::value
|
||||
>
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_sequence_concept<T,
|
||||
void_t<
|
||||
std::enable_if_t<
|
||||
std::is_base_of<
|
||||
std::forward_iterator_tag,
|
||||
typename std::remove_reference_t<T>::iterator::iterator_category
|
||||
>::value>,
|
||||
|
||||
std::enable_if_t<
|
||||
std::is_constructible<jwt::string_view, typename std::remove_reference_t<T>::value_type>::value
|
||||
>,
|
||||
|
||||
decltype(
|
||||
std::declval<T&>().begin(),
|
||||
std::declval<T&>().end(),
|
||||
(void)0
|
||||
)
|
||||
>
|
||||
>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Find if a type is present in the typelist.
|
||||
* Eg: has_type<int, list<int, char, float>>{} == true
|
||||
* has_type<long, list<int, char, float>>{} == false
|
||||
*/
|
||||
template <typename F, typename T> struct has_type;
|
||||
|
||||
template <typename F>
|
||||
struct has_type<F, list<>>: std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename F, typename... T>
|
||||
struct has_type<F, list<F, T...>>: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename F, typename H, typename... T>
|
||||
struct has_type<F, list<H,T...>>: has_type<F, list<T...>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* A pack of bools for the bool trick.
|
||||
*/
|
||||
template <bool... V>
|
||||
struct bool_pack {};
|
||||
|
||||
/**
|
||||
*/
|
||||
template <bool... B>
|
||||
using all_true = std::is_same<bool_pack<true, B...>, bool_pack<B..., true>>;
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename... T>
|
||||
using are_all_params = all_true<is_parameter_concept<T>::value...>;
|
||||
|
||||
|
||||
} // END namespace meta
|
||||
} // END namespace detail
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
136
externals/cpp-jwt/include/jwt/error_codes.hpp
vendored
Executable file
136
externals/cpp-jwt/include/jwt/error_codes.hpp
vendored
Executable file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ERROR_CODES_HPP
|
||||
#define CPP_JWT_ERROR_CODES_HPP
|
||||
|
||||
#include <system_error>
|
||||
|
||||
namespace jwt {
|
||||
/**
|
||||
* All the algorithm errors
|
||||
*/
|
||||
enum class AlgorithmErrc
|
||||
{
|
||||
SigningErr = 1,
|
||||
VerificationErr,
|
||||
KeyNotFoundErr,
|
||||
InvalidKeyErr,
|
||||
NoneAlgorithmUsed, // Not an actual error!
|
||||
};
|
||||
|
||||
/**
|
||||
* Algorithm error conditions
|
||||
* TODO: Remove it or use it!
|
||||
*/
|
||||
enum class AlgorithmFailureSource
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode error conditions
|
||||
*/
|
||||
enum class DecodeErrc
|
||||
{
|
||||
// No algorithms provided in decode API
|
||||
EmptyAlgoList = 1,
|
||||
// The JWT signature has incorrect format
|
||||
SignatureFormatError,
|
||||
// The JSON library failed to parse
|
||||
JsonParseError,
|
||||
// Algorithm field in header is missing
|
||||
AlgHeaderMiss,
|
||||
// Type field in header is missing
|
||||
TypHeaderMiss,
|
||||
// Unexpected type field value
|
||||
TypMismatch,
|
||||
// Found duplicate claims
|
||||
DuplClaims,
|
||||
// Key/Secret not passed as decode argument
|
||||
KeyNotPresent,
|
||||
// Key/secret passed as argument for NONE algorithm.
|
||||
// Not a hard error.
|
||||
KeyNotRequiredForNoneAlg,
|
||||
};
|
||||
|
||||
/**
|
||||
* Errors handled during verification process.
|
||||
*/
|
||||
enum class VerificationErrc
|
||||
{
|
||||
//Algorithms provided does not match with header
|
||||
InvalidAlgorithm = 1,
|
||||
//Token is expired at the time of decoding
|
||||
TokenExpired,
|
||||
//The issuer specified does not match with payload
|
||||
InvalidIssuer,
|
||||
//The subject specified does not match with payload
|
||||
InvalidSubject,
|
||||
//The field IAT is not present or is of invalid type
|
||||
InvalidIAT,
|
||||
//Checks for the existence of JTI
|
||||
//if validate_jti is passed in decode
|
||||
InvalidJTI,
|
||||
//The audience specified does not match with payload
|
||||
InvalidAudience,
|
||||
//Decoded before nbf time
|
||||
ImmatureSignature,
|
||||
//Signature match error
|
||||
InvalidSignature,
|
||||
// Invalid value type used for known claims
|
||||
TypeConversionError,
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(AlgorithmErrc err);
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(DecodeErrc err);
|
||||
|
||||
/**
|
||||
*/
|
||||
std::error_code make_error_code(VerificationErrc err);
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
/**
|
||||
* Make the custom enum classes as error code
|
||||
* adaptable.
|
||||
*/
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::AlgorithmErrc> : true_type {};
|
||||
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::DecodeErrc>: true_type {};
|
||||
|
||||
template <>
|
||||
struct is_error_code_enum<jwt::VerificationErrc>: true_type {};
|
||||
}
|
||||
|
||||
#include "jwt/impl/error_codes.ipp"
|
||||
|
||||
#endif
|
305
externals/cpp-jwt/include/jwt/exceptions.hpp
vendored
Executable file
305
externals/cpp-jwt/include/jwt/exceptions.hpp
vendored
Executable file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_EXCEPTIONS_HPP
|
||||
#define CPP_JWT_EXCEPTIONS_HPP
|
||||
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/**
|
||||
* Exception for allocation related failures in the
|
||||
* OpenSSL C APIs.
|
||||
*/
|
||||
class MemoryAllocationException final: public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct MemoryAllocationException from a
|
||||
* string literal.
|
||||
*/
|
||||
template <size_t N>
|
||||
MemoryAllocationException(const char(&msg)[N])
|
||||
: msg_(&msg[0])
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return msg_;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* msg_ = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown for failures in OpenSSL
|
||||
* APIs while signing.
|
||||
*/
|
||||
class SigningError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
SigningError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown for decode related errors.
|
||||
*/
|
||||
class DecodeError: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
DecodeError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A derived decode error for signature format
|
||||
* error.
|
||||
*/
|
||||
class SignatureFormatError final : public DecodeError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
SignatureFormatError(std::string msg)
|
||||
: DecodeError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A derived decode error for Key argument not present
|
||||
* error. Only thrown if the algorithm set is not NONE.
|
||||
*/
|
||||
class KeyNotPresentError final : public DecodeError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
KeyNotPresentError(std::string msg)
|
||||
: DecodeError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base class exception for all kinds of verification errors.
|
||||
* Verification errors are thrown only when the verify
|
||||
* decode parameter is set to true.
|
||||
*/
|
||||
class VerificationError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
VerificationError(std::string msg)
|
||||
: std::runtime_error(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the algorithm decoded in the header
|
||||
* is incorrect.
|
||||
*/
|
||||
class InvalidAlgorithmError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidAlgorithmError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the token is expired at the
|
||||
* time of decoding.
|
||||
*/
|
||||
class TokenExpiredError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
TokenExpiredError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the issuer claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidIssuerError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidIssuerError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the audience claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidAudienceError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidAudienceError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the subject claim does not match
|
||||
* with the one provided as part of decode argument.
|
||||
*/
|
||||
class InvalidSubjectError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidSubjectError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when verify_iat parameter is passed to
|
||||
* decode and IAT is not present.
|
||||
*/
|
||||
class InvalidIATError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidIATError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when validate_jti is asked for
|
||||
* in decode and jti claim is not present.
|
||||
*/
|
||||
class InvalidJTIError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidJTIError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the token is decoded at a time before
|
||||
* as specified in the `nbf` claim.
|
||||
*/
|
||||
class ImmatureSignatureError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
ImmatureSignatureError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when the signature does not match in the verification process.
|
||||
*/
|
||||
class InvalidSignatureError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidSignatureError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class InvalidKeyError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
InvalidKeyError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Derived from VerificationError.
|
||||
* Thrown when there type expectation mismatch
|
||||
* while verifying the values of registered claim names.
|
||||
*/
|
||||
class TypeConversionError final: public VerificationError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*/
|
||||
TypeConversionError(std::string msg)
|
||||
: VerificationError(std::move(msg))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
312
externals/cpp-jwt/include/jwt/impl/algorithm.ipp
vendored
Executable file
312
externals/cpp-jwt/include/jwt/impl/algorithm.ipp
vendored
Executable file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ALGORITHM_IPP
|
||||
#define CPP_JWT_ALGORITHM_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <typename Hasher>
|
||||
verify_result_t HMACSign<Hasher>::verify(
|
||||
const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
unsigned char enc_buf[EVP_MAX_MD_SIZE];
|
||||
uint32_t enc_buf_len = 0;
|
||||
|
||||
unsigned char* res = HMAC(Hasher{}(),
|
||||
key.data(),
|
||||
static_cast<int>(key.length()),
|
||||
reinterpret_cast<const unsigned char*>(head.data()),
|
||||
head.length(),
|
||||
enc_buf,
|
||||
&enc_buf_len);
|
||||
if (!res) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
if (enc_buf_len == 0) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
|
||||
std::string b64_enc_str = jwt::base64_encode((const char*)&enc_buf[0], enc_buf_len);
|
||||
|
||||
if (!b64_enc_str.length()) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return {false, ec};
|
||||
}
|
||||
|
||||
// Make the base64 string url safe
|
||||
auto new_len = jwt::base64_uri_encode(&b64_enc_str[0], b64_enc_str.length());
|
||||
b64_enc_str.resize(new_len);
|
||||
|
||||
bool ret = (jwt::string_view{b64_enc_str} == jwt_sign);
|
||||
|
||||
return { ret, ec };
|
||||
}
|
||||
|
||||
|
||||
template <typename Hasher>
|
||||
verify_result_t PEMSign<Hasher>::verify(
|
||||
const jwt::string_view key,
|
||||
const jwt::string_view head,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
std::error_code ec{};
|
||||
std::string dec_sig = base64_uri_decode(jwt_sign.data(), jwt_sign.length());
|
||||
|
||||
BIO_uptr bufkey{
|
||||
BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
|
||||
bio_deletor};
|
||||
|
||||
if (!bufkey) {
|
||||
throw MemoryAllocationException("BIO_new_mem_buf failed");
|
||||
}
|
||||
|
||||
EC_PKEY_uptr pkey{
|
||||
PEM_read_bio_PUBKEY(bufkey.get(), nullptr, nullptr, nullptr),
|
||||
ev_pkey_deletor};
|
||||
|
||||
if (!pkey) {
|
||||
ec = AlgorithmErrc::InvalidKeyErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
int pkey_type = EVP_PKEY_id(pkey.get());
|
||||
|
||||
if (pkey_type != Hasher::type) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
//Convert EC signature back to ASN1
|
||||
if (Hasher::type == EVP_PKEY_EC) {
|
||||
EC_SIG_uptr ec_sig{ECDSA_SIG_new(), ec_sig_deletor};
|
||||
if (!ec_sig) {
|
||||
throw MemoryAllocationException("ECDSA_SIG_new failed");
|
||||
}
|
||||
|
||||
//Get the actual ec_key
|
||||
EC_KEY_uptr ec_key{EVP_PKEY_get1_EC_KEY(pkey.get()), ec_key_deletor};
|
||||
if (!ec_key) {
|
||||
throw MemoryAllocationException("EVP_PKEY_get1_EC_KEY failed");
|
||||
}
|
||||
|
||||
unsigned int degree = EC_GROUP_get_degree(
|
||||
EC_KEY_get0_group(ec_key.get()));
|
||||
|
||||
unsigned int bn_len = (degree + 7) / 8;
|
||||
|
||||
if ((bn_len * 2) != dec_sig.length()) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
BIGNUM* ec_sig_r = BN_bin2bn((unsigned char*)dec_sig.data(), bn_len, nullptr);
|
||||
BIGNUM* ec_sig_s = BN_bin2bn((unsigned char*)dec_sig.data() + bn_len, bn_len, nullptr);
|
||||
|
||||
if (!ec_sig_r || !ec_sig_s) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
ECDSA_SIG_set0(ec_sig.get(), ec_sig_r, ec_sig_s);
|
||||
|
||||
size_t nlen = i2d_ECDSA_SIG(ec_sig.get(), nullptr);
|
||||
dec_sig.resize(nlen);
|
||||
|
||||
auto data = reinterpret_cast<unsigned char*>(&dec_sig[0]);
|
||||
nlen = i2d_ECDSA_SIG(ec_sig.get(), &data);
|
||||
|
||||
if (nlen == 0) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MDCTX_uptr mdctx_ptr{EVP_MD_CTX_create(), evp_md_ctx_deletor};
|
||||
if (!mdctx_ptr) {
|
||||
throw MemoryAllocationException("EVP_MD_CTX_create failed");
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyInit(
|
||||
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey.get()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyUpdate(mdctx_ptr.get(), head.data(), head.length()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyFinal(
|
||||
mdctx_ptr.get(), (unsigned char*)&dec_sig[0], dec_sig.length()) != 1) {
|
||||
ec = AlgorithmErrc::VerificationErr;
|
||||
return { false, ec };
|
||||
}
|
||||
|
||||
return { true, ec };
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
EVP_PKEY* PEMSign<Hasher>::load_key(
|
||||
const jwt::string_view key,
|
||||
std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
BIO_uptr bio_ptr{
|
||||
BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
|
||||
bio_deletor};
|
||||
|
||||
if (!bio_ptr) {
|
||||
throw MemoryAllocationException("BIO_new_mem_buf failed");
|
||||
}
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(
|
||||
bio_ptr.get(), nullptr, nullptr, nullptr);
|
||||
|
||||
if (!pkey) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pkey_type = EVP_PKEY_id(pkey);
|
||||
if (pkey_type != Hasher::type) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pkey;
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
std::string PEMSign<Hasher>::evp_digest(
|
||||
EVP_PKEY* pkey,
|
||||
const jwt::string_view data,
|
||||
std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
EVP_MDCTX_uptr mdctx_ptr{EVP_MD_CTX_create(), evp_md_ctx_deletor};
|
||||
|
||||
if (!mdctx_ptr) {
|
||||
throw MemoryAllocationException("EVP_MD_CTX_create failed");
|
||||
}
|
||||
|
||||
//Initialiaze the digest algorithm
|
||||
if (EVP_DigestSignInit(
|
||||
mdctx_ptr.get(), nullptr, Hasher{}(), nullptr, pkey) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
//Update the digest with the input data
|
||||
if (EVP_DigestSignUpdate(mdctx_ptr.get(), data.data(), data.length()) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
|
||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), nullptr, &len) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string sign;
|
||||
sign.resize(len);
|
||||
|
||||
//Get the signature
|
||||
if (EVP_DigestSignFinal(mdctx_ptr.get(), (unsigned char*)&sign[0], &len) != 1) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
return sign;
|
||||
}
|
||||
|
||||
template <typename Hasher>
|
||||
std::string PEMSign<Hasher>::public_key_ser(
|
||||
EVP_PKEY* pkey,
|
||||
jwt::string_view sign,
|
||||
std::error_code& ec)
|
||||
{
|
||||
// Get the EC_KEY representing a public key and
|
||||
// (optionaly) an associated private key
|
||||
std::string new_sign;
|
||||
ec.clear();
|
||||
|
||||
EC_KEY_uptr ec_key{EVP_PKEY_get1_EC_KEY(pkey), ec_key_deletor};
|
||||
|
||||
if (!ec_key) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint32_t degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key.get()));
|
||||
|
||||
ec_key.reset(nullptr);
|
||||
|
||||
auto char_ptr = &sign[0];
|
||||
|
||||
EC_SIG_uptr ec_sig{d2i_ECDSA_SIG(nullptr,
|
||||
(const unsigned char**)&char_ptr,
|
||||
static_cast<long>(sign.length())),
|
||||
ec_sig_deletor};
|
||||
|
||||
if (!ec_sig) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const BIGNUM* ec_sig_r = nullptr;
|
||||
const BIGNUM* ec_sig_s = nullptr;
|
||||
|
||||
ECDSA_SIG_get0(ec_sig.get(), &ec_sig_r, &ec_sig_s);
|
||||
|
||||
int r_len = BN_num_bytes(ec_sig_r);
|
||||
int s_len = BN_num_bytes(ec_sig_s);
|
||||
int bn_len = static_cast<int>((degree + 7) / 8);
|
||||
|
||||
if ((r_len > bn_len) || (s_len > bn_len)) {
|
||||
ec = AlgorithmErrc::SigningErr;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buf_len = 2 * bn_len;
|
||||
new_sign.resize(buf_len);
|
||||
|
||||
BN_bn2bin(ec_sig_r, (unsigned char*)&new_sign[0] + bn_len - r_len);
|
||||
BN_bn2bin(ec_sig_s, (unsigned char*)&new_sign[0] + buf_len - s_len);
|
||||
|
||||
return new_sign;
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
160
externals/cpp-jwt/include/jwt/impl/error_codes.ipp
vendored
Executable file
160
externals/cpp-jwt/include/jwt/impl/error_codes.ipp
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_ERROR_CODES_IPP
|
||||
#define CPP_JWT_ERROR_CODES_IPP
|
||||
|
||||
namespace jwt {
|
||||
// Anonymous namespace
|
||||
namespace {
|
||||
|
||||
/**
|
||||
*/
|
||||
struct AlgorithmErrCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "algorithms";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<AlgorithmErrc>(ev))
|
||||
{
|
||||
case AlgorithmErrc::SigningErr:
|
||||
return "signing failed";
|
||||
case AlgorithmErrc::VerificationErr:
|
||||
return "verification failed";
|
||||
case AlgorithmErrc::KeyNotFoundErr:
|
||||
return "key not provided";
|
||||
case AlgorithmErrc::NoneAlgorithmUsed:
|
||||
return "none algorithm used";
|
||||
case AlgorithmErrc::InvalidKeyErr:
|
||||
return "invalid key";
|
||||
};
|
||||
return "unknown algorithm error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct DecodeErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "decode";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<DecodeErrc>(ev))
|
||||
{
|
||||
case DecodeErrc::EmptyAlgoList:
|
||||
return "empty algorithm list";
|
||||
case DecodeErrc::SignatureFormatError:
|
||||
return "signature format is incorrect";
|
||||
case DecodeErrc::AlgHeaderMiss:
|
||||
return "missing algorithm header";
|
||||
case DecodeErrc::TypHeaderMiss:
|
||||
return "missing type header";
|
||||
case DecodeErrc::TypMismatch:
|
||||
return "type mismatch";
|
||||
case DecodeErrc::JsonParseError:
|
||||
return "json parse failed";
|
||||
case DecodeErrc::DuplClaims:
|
||||
return "duplicate claims";
|
||||
case DecodeErrc::KeyNotPresent:
|
||||
return "key not present";
|
||||
case DecodeErrc::KeyNotRequiredForNoneAlg:
|
||||
return "key not required for NONE algorithm";
|
||||
};
|
||||
return "unknown decode error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct VerificationErrorCategory: std::error_category
|
||||
{
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "verification";
|
||||
}
|
||||
|
||||
std::string message(int ev) const override
|
||||
{
|
||||
switch (static_cast<VerificationErrc>(ev))
|
||||
{
|
||||
case VerificationErrc::InvalidAlgorithm:
|
||||
return "invalid algorithm";
|
||||
case VerificationErrc::TokenExpired:
|
||||
return "token expired";
|
||||
case VerificationErrc::InvalidIssuer:
|
||||
return "invalid issuer";
|
||||
case VerificationErrc::InvalidSubject:
|
||||
return "invalid subject";
|
||||
case VerificationErrc::InvalidAudience:
|
||||
return "invalid audience";
|
||||
case VerificationErrc::InvalidIAT:
|
||||
return "invalid iat";
|
||||
case VerificationErrc::InvalidJTI:
|
||||
return "invalid jti";
|
||||
case VerificationErrc::ImmatureSignature:
|
||||
return "immature signature";
|
||||
case VerificationErrc::InvalidSignature:
|
||||
return "invalid signature";
|
||||
case VerificationErrc::TypeConversionError:
|
||||
return "type conversion error";
|
||||
};
|
||||
return "unknown verification error";
|
||||
}
|
||||
};
|
||||
|
||||
// Create global object for the error categories
|
||||
const AlgorithmErrCategory theAlgorithmErrCategory {};
|
||||
|
||||
const DecodeErrorCategory theDecodeErrorCategory {};
|
||||
|
||||
const VerificationErrorCategory theVerificationErrorCategory {};
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Create the AlgorithmErrc error code
|
||||
inline std::error_code make_error_code(AlgorithmErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theAlgorithmErrCategory };
|
||||
}
|
||||
|
||||
inline std::error_code make_error_code(DecodeErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theDecodeErrorCategory };
|
||||
}
|
||||
|
||||
inline std::error_code make_error_code(VerificationErrc err)
|
||||
{
|
||||
return { static_cast<int>(err), theVerificationErrorCategory };
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
882
externals/cpp-jwt/include/jwt/impl/jwt.ipp
vendored
Executable file
882
externals/cpp-jwt/include/jwt/impl/jwt.ipp
vendored
Executable file
@@ -0,0 +1,882 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_IPP
|
||||
#define JWT_IPP
|
||||
|
||||
#include "jwt/config.hpp"
|
||||
#include "jwt/detail/meta.hpp"
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/**
|
||||
*/
|
||||
static inline void jwt_throw_exception(const std::error_code& ec);
|
||||
|
||||
template <typename T, typename Cond>
|
||||
std::string to_json_str(const T& obj, bool pretty)
|
||||
{
|
||||
return pretty ? obj.create_json_obj().dump(2)
|
||||
: obj.create_json_obj().dump()
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::ostream& write(std::ostream& os, const T& obj, bool pretty)
|
||||
{
|
||||
pretty ? (os << std::setw(2) << obj.create_json_obj())
|
||||
: (os << obj.create_json_obj())
|
||||
;
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename Cond>
|
||||
std::ostream& operator<< (std::ostream& os, const T& obj)
|
||||
{
|
||||
os << obj.create_json_obj();
|
||||
return os;
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
|
||||
inline void jwt_header::decode(const jwt::string_view enc_str, std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
std::string json_str = base64_decode(enc_str);
|
||||
|
||||
try {
|
||||
payload_ = json_t::parse(std::move(json_str));
|
||||
} catch(const std::exception&) {
|
||||
ec = DecodeErrc::JsonParseError;
|
||||
return;
|
||||
}
|
||||
|
||||
//Look for the algorithm field
|
||||
auto alg_itr = payload_.find("alg");
|
||||
if (alg_itr == payload_.end()) {
|
||||
ec = DecodeErrc::AlgHeaderMiss;
|
||||
return;
|
||||
}
|
||||
|
||||
alg_ = str_to_alg(alg_itr.value().get<std::string>());
|
||||
|
||||
if (alg_ != algorithm::NONE)
|
||||
{
|
||||
auto itr = payload_.find("typ");
|
||||
|
||||
if (itr != payload_.end()) {
|
||||
const auto& typ = itr.value().get<std::string>();
|
||||
if (strcasecmp(typ.c_str(), "JWT")) {
|
||||
ec = DecodeErrc::TypMismatch;
|
||||
return;
|
||||
}
|
||||
|
||||
typ_ = str_to_type(typ);
|
||||
}
|
||||
} else {
|
||||
//TODO:
|
||||
}
|
||||
|
||||
// Populate header
|
||||
for (auto it = payload_.begin(); it != payload_.end(); ++it) {
|
||||
auto ret = headers_.insert(it.key());
|
||||
if (!ret.second) {
|
||||
ec = DecodeErrc::DuplClaims;
|
||||
//ATTN: Dont stop the decode here
|
||||
//Not a hard error.
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_header::decode(const jwt::string_view enc_str)
|
||||
{
|
||||
std::error_code ec;
|
||||
decode(enc_str, ec);
|
||||
if (ec) {
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_payload::decode(const jwt::string_view enc_str, std::error_code& ec)
|
||||
{
|
||||
ec.clear();
|
||||
std::string json_str = base64_decode(enc_str);
|
||||
try {
|
||||
payload_ = json_t::parse(std::move(json_str));
|
||||
} catch(const std::exception&) {
|
||||
ec = DecodeErrc::JsonParseError;
|
||||
return;
|
||||
}
|
||||
//populate the claims set
|
||||
for (auto it = payload_.begin(); it != payload_.end(); ++it) {
|
||||
auto ret = claim_names_.insert(it.key());
|
||||
if (!ret.second) {
|
||||
ec = DecodeErrc::DuplClaims;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
inline void jwt_payload::decode(const jwt::string_view enc_str)
|
||||
{
|
||||
std::error_code ec;
|
||||
decode(enc_str, ec);
|
||||
if (ec) {
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
inline std::string jwt_signature::encode(const jwt_header& header,
|
||||
const jwt_payload& payload,
|
||||
std::error_code& ec)
|
||||
{
|
||||
std::string jwt_msg;
|
||||
ec.clear();
|
||||
//TODO: Optimize allocations
|
||||
|
||||
sign_func_t sign_fn = get_sign_algorithm_impl(header);
|
||||
|
||||
std::string hdr_sign = header.base64_encode();
|
||||
std::string pld_sign = payload.base64_encode();
|
||||
std::string data = hdr_sign + '.' + pld_sign;
|
||||
|
||||
auto res = sign_fn(key_, data);
|
||||
|
||||
if (res.second && res.second != AlgorithmErrc::NoneAlgorithmUsed) {
|
||||
ec = res.second;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string b64hash;
|
||||
|
||||
if (!res.second) {
|
||||
b64hash = base64_encode(res.first.c_str(), res.first.length());
|
||||
}
|
||||
|
||||
auto new_len = base64_uri_encode(&b64hash[0], b64hash.length());
|
||||
b64hash.resize(new_len);
|
||||
|
||||
jwt_msg = data + '.' + b64hash;
|
||||
|
||||
return jwt_msg;
|
||||
}
|
||||
|
||||
inline verify_result_t jwt_signature::verify(const jwt_header& header,
|
||||
const jwt::string_view hdr_pld_sign,
|
||||
const jwt::string_view jwt_sign)
|
||||
{
|
||||
verify_func_t verify_fn = get_verify_algorithm_impl(header);
|
||||
return verify_fn(key_, hdr_pld_sign, jwt_sign);
|
||||
}
|
||||
|
||||
|
||||
inline sign_func_t
|
||||
jwt_signature::get_sign_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||
{
|
||||
sign_func_t ret = nullptr;
|
||||
|
||||
switch (hdr.algo()) {
|
||||
case algorithm::HS256:
|
||||
ret = HMACSign<algo::HS256>::sign;
|
||||
break;
|
||||
case algorithm::HS384:
|
||||
ret = HMACSign<algo::HS384>::sign;
|
||||
break;
|
||||
case algorithm::HS512:
|
||||
ret = HMACSign<algo::HS512>::sign;
|
||||
break;
|
||||
case algorithm::NONE:
|
||||
ret = HMACSign<algo::NONE>::sign;
|
||||
break;
|
||||
case algorithm::RS256:
|
||||
ret = PEMSign<algo::RS256>::sign;
|
||||
break;
|
||||
case algorithm::RS384:
|
||||
ret = PEMSign<algo::RS384>::sign;
|
||||
break;
|
||||
case algorithm::RS512:
|
||||
ret = PEMSign<algo::RS512>::sign;
|
||||
break;
|
||||
case algorithm::ES256:
|
||||
ret = PEMSign<algo::ES256>::sign;
|
||||
break;
|
||||
case algorithm::ES384:
|
||||
ret = PEMSign<algo::ES384>::sign;
|
||||
break;
|
||||
case algorithm::ES512:
|
||||
ret = PEMSign<algo::ES512>::sign;
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Code not reached");
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline verify_func_t
|
||||
jwt_signature::get_verify_algorithm_impl(const jwt_header& hdr) const noexcept
|
||||
{
|
||||
verify_func_t ret = nullptr;
|
||||
|
||||
switch (hdr.algo()) {
|
||||
case algorithm::HS256:
|
||||
ret = HMACSign<algo::HS256>::verify;
|
||||
break;
|
||||
case algorithm::HS384:
|
||||
ret = HMACSign<algo::HS384>::verify;
|
||||
break;
|
||||
case algorithm::HS512:
|
||||
ret = HMACSign<algo::HS512>::verify;
|
||||
break;
|
||||
case algorithm::NONE:
|
||||
ret = HMACSign<algo::NONE>::verify;
|
||||
break;
|
||||
case algorithm::RS256:
|
||||
ret = PEMSign<algo::RS256>::verify;
|
||||
break;
|
||||
case algorithm::RS384:
|
||||
ret = PEMSign<algo::RS384>::verify;
|
||||
break;
|
||||
case algorithm::RS512:
|
||||
ret = PEMSign<algo::RS512>::verify;
|
||||
break;
|
||||
case algorithm::ES256:
|
||||
ret = PEMSign<algo::ES256>::verify;
|
||||
break;
|
||||
case algorithm::ES384:
|
||||
ret = PEMSign<algo::ES384>::verify;
|
||||
break;
|
||||
case algorithm::ES512:
|
||||
ret = PEMSign<algo::ES512>::verify;
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Code not reached");
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
template <typename First, typename... Rest,
|
||||
typename SFINAE_COND>
|
||||
jwt_object::jwt_object(
|
||||
First&& first, Rest&&... rest)
|
||||
{
|
||||
static_assert (detail::meta::is_parameter_concept<First>::value &&
|
||||
detail::meta::are_all_params<Rest...>::value,
|
||||
"All constructor argument types must model ParameterConcept");
|
||||
|
||||
set_parameters(std::forward<First>(first), std::forward<Rest>(rest)...);
|
||||
}
|
||||
|
||||
template <typename Map, typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::payload_param<Map>&& payload, Rest&&... rargs)
|
||||
{
|
||||
for (const auto& elem : payload.get()) {
|
||||
payload_.add_claim(std::move(elem.first), std::move(elem.second));
|
||||
}
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::secret_param secret, Rest&&... rargs)
|
||||
{
|
||||
secret_.assign(secret.get().data(), secret.get().length());
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::algorithm_param alg, Rest&&... rargs)
|
||||
{
|
||||
header_.algo(alg.get());
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
template <typename Map, typename... Rest>
|
||||
void jwt_object::set_parameters(
|
||||
params::detail::headers_param<Map>&& header, Rest&&... rargs)
|
||||
{
|
||||
for (const auto& elem : header.get()) {
|
||||
header_.add_header(std::move(elem.first), std::move(elem.second));
|
||||
}
|
||||
|
||||
set_parameters(std::forward<Rest>(rargs)...);
|
||||
}
|
||||
|
||||
inline void jwt_object::set_parameters()
|
||||
{
|
||||
//sentinel call
|
||||
return;
|
||||
}
|
||||
|
||||
inline jwt_object& jwt_object::add_claim(const jwt::string_view name, system_time_t tp)
|
||||
{
|
||||
return add_claim(
|
||||
name,
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count()
|
||||
);
|
||||
}
|
||||
|
||||
inline jwt_object& jwt_object::remove_claim(const jwt::string_view name)
|
||||
{
|
||||
payload_.remove_claim(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline std::string jwt_object::signature(std::error_code& ec) const
|
||||
{
|
||||
ec.clear();
|
||||
|
||||
//key/secret should be set for any algorithm except NONE
|
||||
if (header().algo() != jwt::algorithm::NONE) {
|
||||
if (secret_.length() == 0) {
|
||||
ec = AlgorithmErrc::KeyNotFoundErr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
jwt_signature jws{secret_};
|
||||
return jws.encode(header_, payload_, ec);
|
||||
}
|
||||
|
||||
inline std::string jwt_object::signature() const
|
||||
{
|
||||
std::error_code ec;
|
||||
std::string res = signature(ec);
|
||||
if (ec) {
|
||||
throw SigningError(ec.message());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename Params, typename SequenceT>
|
||||
std::error_code jwt_object::verify(
|
||||
const Params& dparams,
|
||||
const params::detail::algorithms_param<SequenceT>& algos) const
|
||||
{
|
||||
std::error_code ec{};
|
||||
|
||||
//Verify if the algorithm set in the header
|
||||
//is any of the one expected by the client.
|
||||
auto fitr = std::find_if(algos.get().begin(),
|
||||
algos.get().end(),
|
||||
[this](const auto& elem)
|
||||
{
|
||||
return jwt::str_to_alg(elem) == this->header().algo();
|
||||
});
|
||||
|
||||
if (fitr == algos.get().end()) {
|
||||
ec = VerificationErrc::InvalidAlgorithm;
|
||||
return ec;
|
||||
}
|
||||
|
||||
//Check for the expiry timings
|
||||
if (has_claim(registered_claims::expiration)) {
|
||||
auto curr_time =
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
auto p_exp = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::expiration);
|
||||
|
||||
if (static_cast<uint64_t>(curr_time) > static_cast<uint64_t>(p_exp + dparams.leeway)) {
|
||||
ec = VerificationErrc::TokenExpired;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for issuer
|
||||
if (dparams.has_issuer)
|
||||
{
|
||||
if (has_claim(registered_claims::issuer))
|
||||
{
|
||||
const std::string& p_issuer = payload()
|
||||
.get_claim_value<std::string>(registered_claims::issuer);
|
||||
|
||||
if (p_issuer != dparams.issuer) {
|
||||
ec = VerificationErrc::InvalidIssuer;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidIssuer;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for audience
|
||||
if (dparams.has_aud)
|
||||
{
|
||||
if (has_claim(registered_claims::audience))
|
||||
{
|
||||
const std::string& p_aud = payload()
|
||||
.get_claim_value<std::string>(registered_claims::audience);
|
||||
|
||||
if (p_aud != dparams.aud) {
|
||||
ec = VerificationErrc::InvalidAudience;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidAudience;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check the subject
|
||||
if (dparams.has_sub)
|
||||
{
|
||||
if (has_claim(registered_claims::subject))
|
||||
{
|
||||
const std::string& p_sub = payload()
|
||||
.get_claim_value<std::string>(registered_claims::subject);
|
||||
if (p_sub != dparams.sub) {
|
||||
ec = VerificationErrc::InvalidSubject;
|
||||
return ec;
|
||||
}
|
||||
} else {
|
||||
ec = VerificationErrc::InvalidSubject;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check for NBF
|
||||
if (has_claim(registered_claims::not_before))
|
||||
{
|
||||
auto curr_time =
|
||||
std::chrono::duration_cast<
|
||||
std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
auto p_exp = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::not_before);
|
||||
|
||||
if (static_cast<uint64_t>(p_exp - dparams.leeway) > static_cast<uint64_t>(curr_time)) {
|
||||
ec = VerificationErrc::ImmatureSignature;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
//Check IAT validation
|
||||
if (dparams.validate_iat) {
|
||||
if (!has_claim(registered_claims::issued_at)) {
|
||||
ec = VerificationErrc::InvalidIAT;
|
||||
return ec;
|
||||
} else {
|
||||
// Will throw type conversion error
|
||||
auto val = payload()
|
||||
.get_claim_value<uint64_t>(registered_claims::issued_at);
|
||||
(void)val;
|
||||
}
|
||||
}
|
||||
|
||||
//Check JTI validation
|
||||
if (dparams.validate_jti) {
|
||||
if (!has_claim("jti")) {
|
||||
ec = VerificationErrc::InvalidJTI;
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
||||
inline std::array<jwt::string_view, 3>
|
||||
jwt_object::three_parts(const jwt::string_view enc_str)
|
||||
{
|
||||
std::array<jwt::string_view, 3> result;
|
||||
|
||||
size_t fpos = enc_str.find_first_of('.');
|
||||
assert (fpos != jwt::string_view::npos);
|
||||
|
||||
result[0] = jwt::string_view{&enc_str[0], fpos};
|
||||
|
||||
size_t spos = enc_str.find_first_of('.', fpos + 1);
|
||||
|
||||
result[1] = jwt::string_view{&enc_str[fpos + 1], spos - fpos - 1};
|
||||
|
||||
if (spos + 1 != enc_str.length()) {
|
||||
result[2] = jwt::string_view{&enc_str[spos + 1], enc_str.length() - spos - 1};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::secret_param s, Rest&&... args)
|
||||
{
|
||||
dparams.secret.assign(s.get().data(), s.get().length());
|
||||
dparams.has_secret = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename T, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::secret_function_param<T>&& s, Rest&&... args)
|
||||
{
|
||||
dparams.secret = s.get(*dparams.payload_ptr);
|
||||
dparams.has_secret = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::leeway_param l, Rest&&... args)
|
||||
{
|
||||
dparams.leeway = l.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::verify_param v, Rest&&... args)
|
||||
{
|
||||
dparams.verify = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::issuer_param i, Rest&&... args)
|
||||
{
|
||||
dparams.issuer = std::move(i).get();
|
||||
dparams.has_issuer = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::audience_param a, Rest&&... args)
|
||||
{
|
||||
dparams.aud = std::move(a).get();
|
||||
dparams.has_aud = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::subject_param s, Rest&&... args)
|
||||
{
|
||||
dparams.sub = std::move(s).get();
|
||||
dparams.has_sub = true;
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::validate_iat_param v, Rest&&... args)
|
||||
{
|
||||
dparams.validate_iat = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams, typename... Rest>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams, params::detail::validate_jti_param v, Rest&&... args)
|
||||
{
|
||||
dparams.validate_jti = v.get();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Rest>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodeParams>
|
||||
void jwt_object::set_decode_params(DecodeParams& dparams)
|
||||
{
|
||||
(void) dparams; // prevent -Wunused-parameter with gcc
|
||||
return;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
|
||||
template <typename SequenceT, typename... Args>
|
||||
jwt_object decode(const jwt::string_view enc_str,
|
||||
const params::detail::algorithms_param<SequenceT>& algos,
|
||||
std::error_code& ec,
|
||||
Args&&... args)
|
||||
{
|
||||
ec.clear();
|
||||
jwt_object obj;
|
||||
|
||||
if (algos.get().size() == 0) {
|
||||
ec = DecodeErrc::EmptyAlgoList;
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct decode_params
|
||||
{
|
||||
/// key to decode the JWS
|
||||
bool has_secret = false;
|
||||
std::string secret;
|
||||
|
||||
/// Verify parameter. Defaulted to true.
|
||||
bool verify = true;
|
||||
|
||||
/// Leeway parameter. Defaulted to zero seconds.
|
||||
uint32_t leeway = 0;
|
||||
|
||||
///The issuer
|
||||
//TODO: optional type
|
||||
bool has_issuer = false;
|
||||
std::string issuer;
|
||||
|
||||
///The audience
|
||||
//TODO: optional type
|
||||
bool has_aud = false;
|
||||
std::string aud;
|
||||
|
||||
//The subject
|
||||
//TODO: optional type
|
||||
bool has_sub = false;
|
||||
std::string sub;
|
||||
|
||||
//Validate IAT
|
||||
bool validate_iat = false;
|
||||
|
||||
//Validate JTI
|
||||
bool validate_jti = false;
|
||||
const jwt_payload* payload_ptr = 0;
|
||||
};
|
||||
|
||||
decode_params dparams{};
|
||||
|
||||
|
||||
//Signature must have atleast 2 dots
|
||||
auto dot_cnt = std::count_if(std::begin(enc_str), std::end(enc_str),
|
||||
[](char ch) { return ch == '.'; });
|
||||
if (dot_cnt < 2) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
|
||||
auto parts = jwt_object::three_parts(enc_str);
|
||||
|
||||
//throws decode error
|
||||
jwt_header hdr{};
|
||||
hdr.decode(parts[0], ec);
|
||||
if (ec) {
|
||||
return obj;
|
||||
}
|
||||
//obj.header(jwt_header{parts[0]});
|
||||
obj.header(std::move(hdr));
|
||||
|
||||
//If the algorithm is not NONE, it must not
|
||||
//have more than two dots ('.') and the split
|
||||
//must result in three strings with some length.
|
||||
if (obj.header().algo() != jwt::algorithm::NONE) {
|
||||
if (dot_cnt > 2) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
if (parts[2].length() == 0) {
|
||||
ec = DecodeErrc::SignatureFormatError;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
//throws decode error
|
||||
jwt_payload payload{};
|
||||
payload.decode(parts[1], ec);
|
||||
if (ec) {
|
||||
return obj;
|
||||
}
|
||||
obj.payload(std::move(payload));
|
||||
dparams.payload_ptr = & obj.payload();
|
||||
jwt_object::set_decode_params(dparams, std::forward<Args>(args)...);
|
||||
if (dparams.verify) {
|
||||
try {
|
||||
ec = obj.verify(dparams, algos);
|
||||
} catch (const json_ns::detail::type_error&) {
|
||||
ec = VerificationErrc::TypeConversionError;
|
||||
}
|
||||
|
||||
if (ec) return obj;
|
||||
|
||||
//Verify the signature only if some algorithm was used
|
||||
if (obj.header().algo() != algorithm::NONE)
|
||||
{
|
||||
if (!dparams.has_secret) {
|
||||
ec = DecodeErrc::KeyNotPresent;
|
||||
return obj;
|
||||
}
|
||||
jwt_signature jsign{dparams.secret};
|
||||
|
||||
// Length of the encoded header and payload only.
|
||||
// Addition of '1' to account for the '.' character.
|
||||
auto l = parts[0].length() + 1 + parts[1].length();
|
||||
|
||||
//MemoryAllocationError is not caught
|
||||
verify_result_t res = jsign.verify(obj.header(), enc_str.substr(0, l), parts[2]);
|
||||
if (res.second) {
|
||||
ec = res.second;
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (!res.first) {
|
||||
ec = VerificationErrc::InvalidSignature;
|
||||
return obj;
|
||||
}
|
||||
} else {
|
||||
ec = AlgorithmErrc::NoneAlgorithmUsed;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename SequenceT, typename... Args>
|
||||
jwt_object decode(const jwt::string_view enc_str,
|
||||
const params::detail::algorithms_param<SequenceT>& algos,
|
||||
Args&&... args)
|
||||
{
|
||||
std::error_code ec{};
|
||||
auto jwt_obj = decode(enc_str,
|
||||
algos,
|
||||
ec,
|
||||
std::forward<Args>(args)...);
|
||||
|
||||
if (ec) {
|
||||
jwt_throw_exception(ec);
|
||||
}
|
||||
|
||||
return jwt_obj;
|
||||
}
|
||||
|
||||
|
||||
void jwt_throw_exception(const std::error_code& ec)
|
||||
{
|
||||
const auto& cat = ec.category();
|
||||
|
||||
if (&cat == &theVerificationErrorCategory ||
|
||||
std::string(cat.name()) == std::string(theVerificationErrorCategory.name()))
|
||||
{
|
||||
switch (static_cast<VerificationErrc>(ec.value()))
|
||||
{
|
||||
case VerificationErrc::InvalidAlgorithm:
|
||||
{
|
||||
throw InvalidAlgorithmError(ec.message());
|
||||
}
|
||||
case VerificationErrc::TokenExpired:
|
||||
{
|
||||
throw TokenExpiredError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidIssuer:
|
||||
{
|
||||
throw InvalidIssuerError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidAudience:
|
||||
{
|
||||
throw InvalidAudienceError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidSubject:
|
||||
{
|
||||
throw InvalidSubjectError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidIAT:
|
||||
{
|
||||
throw InvalidIATError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidJTI:
|
||||
{
|
||||
throw InvalidJTIError(ec.message());
|
||||
}
|
||||
case VerificationErrc::ImmatureSignature:
|
||||
{
|
||||
throw ImmatureSignatureError(ec.message());
|
||||
}
|
||||
case VerificationErrc::InvalidSignature:
|
||||
{
|
||||
throw InvalidSignatureError(ec.message());
|
||||
}
|
||||
case VerificationErrc::TypeConversionError:
|
||||
{
|
||||
throw TypeConversionError(ec.message());
|
||||
}
|
||||
default:
|
||||
assert (0 && "Unknown error code");
|
||||
};
|
||||
}
|
||||
|
||||
if (&cat == &theDecodeErrorCategory ||
|
||||
std::string(cat.name()) == std::string(theDecodeErrorCategory.name()))
|
||||
{
|
||||
switch (static_cast<DecodeErrc>(ec.value()))
|
||||
{
|
||||
case DecodeErrc::SignatureFormatError:
|
||||
{
|
||||
throw SignatureFormatError(ec.message());
|
||||
}
|
||||
case DecodeErrc::KeyNotPresent:
|
||||
{
|
||||
throw KeyNotPresentError(ec.message());
|
||||
}
|
||||
case DecodeErrc::KeyNotRequiredForNoneAlg:
|
||||
{
|
||||
// Not an error. Just to be ignored.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw DecodeError(ec.message());
|
||||
}
|
||||
};
|
||||
|
||||
assert (0 && "Unknown error code");
|
||||
}
|
||||
|
||||
if (&cat == &theAlgorithmErrCategory ||
|
||||
std::string(cat.name()) == std::string(theAlgorithmErrCategory.name()))
|
||||
{
|
||||
switch (static_cast<AlgorithmErrc>(ec.value()))
|
||||
{
|
||||
case AlgorithmErrc::InvalidKeyErr:
|
||||
{
|
||||
throw InvalidKeyError(ec.message());
|
||||
}
|
||||
case AlgorithmErrc::VerificationErr:
|
||||
{
|
||||
throw InvalidSignatureError(ec.message());
|
||||
}
|
||||
case AlgorithmErrc::NoneAlgorithmUsed:
|
||||
{
|
||||
//Not an error actually.
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert (0 && "Unknown error code or not to be treated as an error");
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
|
||||
#endif
|
87
externals/cpp-jwt/include/jwt/impl/stack_alloc.ipp
vendored
Executable file
87
externals/cpp-jwt/include/jwt/impl/stack_alloc.ipp
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_IPP
|
||||
#define STACK_ALLOC_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <size_t N, size_t alignment>
|
||||
template <size_t reqested_alignment>
|
||||
char* Arena<N, alignment>::allocate(size_t n) noexcept
|
||||
{
|
||||
static_assert (reqested_alignment <= alignment,
|
||||
"Requested alignment is too small for this arena");
|
||||
|
||||
assert (pointer_in_storage(ptr_) &&
|
||||
"No more space in the arena or it has outgrown its capacity");
|
||||
|
||||
n = align_up(n);
|
||||
|
||||
if ((ptr_ + n) <= (buf_ + N)) {
|
||||
char* ret = ptr_;
|
||||
ptr_ += n;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
assert (0 && "Code should not reach here");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <size_t N, size_t alignment>
|
||||
void Arena<N, alignment>::deallocate(char* p, size_t n) noexcept
|
||||
{
|
||||
assert (pointer_in_storage(p) &&
|
||||
"The address to de deleted does not lie inside the storage");
|
||||
|
||||
n = align_up(n);
|
||||
|
||||
if ((p + n) == ptr_) {
|
||||
ptr_ = p;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename T, size_t N, size_t alignment>
|
||||
T* stack_alloc<T, N, alignment>::allocate(size_t n) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
arena_.template allocate<alignof(T)>(n * sizeof(T))
|
||||
);
|
||||
}
|
||||
|
||||
template <typename T, size_t N, size_t alignment>
|
||||
void stack_alloc<T, N, alignment>::deallocate(T* p, size_t n) noexcept
|
||||
{
|
||||
arena_.deallocate(reinterpret_cast<char*>(p), n);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
339
externals/cpp-jwt/include/jwt/impl/string_view.ipp
vendored
Executable file
339
externals/cpp-jwt/include/jwt/impl/string_view.ipp
vendored
Executable file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_STRING_VIEW_IPP
|
||||
#define JWT_STRING_VIEW_IPP
|
||||
|
||||
namespace jwt {
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (n < (len_ - pos) && "Comparison size out of bounds");
|
||||
|
||||
if (n == 0) {
|
||||
return pos <= len_ ? pos : npos;
|
||||
}
|
||||
if (n <= len_) {
|
||||
for (; pos <= (len_ - n); ++pos) {
|
||||
if (traits_type::eq(data_[pos], str[0]) &&
|
||||
traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::rfind(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position out of bounds");
|
||||
|
||||
if (n <= len_) {
|
||||
pos = std::min(len_ - n, pos);
|
||||
do {
|
||||
if (traits_type::eq(data_[pos], str[0]) &&
|
||||
traits_type::compare(data_ + pos + 1, str + 1, n - 1) == 0) {
|
||||
return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find(
|
||||
const CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
if (pos < len_) {
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
if (traits_type::eq(data_[i], ch)) return i;
|
||||
}
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::rfind(
|
||||
const CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
if (pos < len_) {
|
||||
do {
|
||||
if (traits_type::eq(data_[pos], ch)) {
|
||||
return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type count) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
auto p = traits_type::find(str, count, data_[i]);
|
||||
if (p) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type count) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
size_type siz = len_;
|
||||
|
||||
if (siz && count) {
|
||||
siz = std::min(pos, siz);
|
||||
|
||||
do {
|
||||
auto p = traits_type::find(str, count, data_[siz]);
|
||||
if (p) {
|
||||
return siz;
|
||||
}
|
||||
} while (siz-- != 0);
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_not_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_&& "Position must be within the bounds of the view");
|
||||
|
||||
for (size_type i = pos; i < len_; ++i)
|
||||
{
|
||||
auto p = traits_type::find(str, n, data_[i]);
|
||||
if (!p) return i;
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_not_of(
|
||||
const CharT* str,
|
||||
size_type pos,
|
||||
size_type n) const noexcept -> size_type
|
||||
{
|
||||
assert (str);
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
|
||||
do {
|
||||
for (size_type i = 0; i < n; ++i) {
|
||||
if (!traits_type::eq(data_[pos], str[i])) return pos;
|
||||
}
|
||||
} while (pos-- != 0);
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_first_not_of(
|
||||
CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
assert (pos < len_&& "Position must be within the bounds of the view");
|
||||
|
||||
for (size_type i = pos; i < len_; ++i) {
|
||||
if (!traits_type::eq(data_[i], ch)) return i;
|
||||
}
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
auto basic_string_view<CharT, Traits>::find_last_not_of(
|
||||
CharT ch,
|
||||
size_type pos) const noexcept -> size_type
|
||||
{
|
||||
assert (pos < len_ && "Position must be within the bounds of the view");
|
||||
|
||||
do {
|
||||
if (!traits_type::eq(data_[pos], ch)) return pos;
|
||||
} while (pos-- != 0);
|
||||
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Comparison Operators
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator== (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
if (a.length() != b.length()) return false;
|
||||
using traits_type = typename basic_string_view<CharT, Traits>::traits_type;
|
||||
using size_type = typename basic_string_view<CharT, Traits>::size_type;
|
||||
|
||||
for (size_type i = 0; i < a.length(); ++i) {
|
||||
if (!traits_type::eq(a[i], b[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator!= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return !( a == b );
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator< (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) < 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator> (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) > 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator<= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) <= 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
bool operator>= (basic_string_view<CharT, Traits> a,
|
||||
basic_string_view<CharT, Traits> b) noexcept
|
||||
{
|
||||
return a.compare(b) >= 0;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::ostream& operator<< (std::ostream& os, basic_string_view<CharT, Traits> sv)
|
||||
{
|
||||
os.write(sv.data(), sv.length());
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* Copy of gcc implementation of murmurhash
|
||||
* hash_bytes.cc
|
||||
*/
|
||||
|
||||
inline size_t
|
||||
unaligned_load(const char* p) noexcept
|
||||
{
|
||||
std::size_t result;
|
||||
std::memcpy(&result, p, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline size_t
|
||||
hash_bytes(const void* ptr, size_t len, size_t seed) noexcept
|
||||
{
|
||||
const size_t m = 0x5bd1e995;
|
||||
size_t hash = seed ^ len;
|
||||
const char* buf = static_cast<const char*>(ptr);
|
||||
|
||||
// Mix 4 bytes at a time into the hash.
|
||||
while(len >= 4)
|
||||
{
|
||||
size_t k = unaligned_load(buf);
|
||||
k *= m;
|
||||
k ^= k >> 24;
|
||||
k *= m;
|
||||
hash *= m;
|
||||
hash ^= k;
|
||||
buf += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array.
|
||||
switch(len)
|
||||
{
|
||||
case 3:
|
||||
hash ^= static_cast<unsigned char>(buf[2]) << 16;
|
||||
//FALLTHROUGH
|
||||
case 2:
|
||||
hash ^= static_cast<unsigned char>(buf[1]) << 8;
|
||||
//FALLTHROUGH
|
||||
case 1:
|
||||
hash ^= static_cast<unsigned char>(buf[0]);
|
||||
hash *= m;
|
||||
};
|
||||
|
||||
// Do a few final mixes of the hash.
|
||||
hash ^= hash >> 13;
|
||||
hash *= m;
|
||||
hash ^= hash >> 15;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
/// Provide a hash specialization
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<jwt::string_view>
|
||||
{
|
||||
size_t operator()(const jwt::string_view& sv) const noexcept
|
||||
{
|
||||
return jwt::hash_bytes((void*)sv.data(), sv.length(), static_cast<size_t>(0xc70f6907UL));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
25447
externals/cpp-jwt/include/jwt/json/json.hpp
vendored
Executable file
25447
externals/cpp-jwt/include/jwt/json/json.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
24
externals/cpp-jwt/include/jwt/json/test_json.cc
vendored
Executable file
24
externals/cpp-jwt/include/jwt/json/test_json.cc
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#if defined( CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
#include "./json.hpp"
|
||||
#else
|
||||
#include "nlohmann/json.hpp"
|
||||
#endif
|
||||
using json = nlohmann::json;
|
||||
|
||||
void basic_json_test()
|
||||
{
|
||||
json obj = json::object();
|
||||
obj["test"] = "value-test";
|
||||
obj["test-int"] = 42;
|
||||
|
||||
std::string jstr = obj.dump(0);
|
||||
std::cout << jstr << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_json_test();
|
||||
|
||||
return 0;
|
||||
}
|
1203
externals/cpp-jwt/include/jwt/jwt.hpp
vendored
Executable file
1203
externals/cpp-jwt/include/jwt/jwt.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
451
externals/cpp-jwt/include/jwt/parameters.hpp
vendored
Executable file
451
externals/cpp-jwt/include/jwt/parameters.hpp
vendored
Executable file
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_PARAMETERS_HPP
|
||||
#define CPP_JWT_PARAMETERS_HPP
|
||||
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "jwt/algorithm.hpp"
|
||||
#include "jwt/detail/meta.hpp"
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
namespace jwt {
|
||||
|
||||
using system_time_t = std::chrono::time_point<std::chrono::system_clock>;
|
||||
|
||||
namespace params {
|
||||
|
||||
|
||||
namespace detail {
|
||||
/**
|
||||
* Parameter for providing the payload.
|
||||
* Takes a Mapping concept representing
|
||||
* key-value pairs.
|
||||
*
|
||||
* NOTE: MappingConcept allows only strings
|
||||
* for both keys and values. Use `add_header`
|
||||
* API of `jwt_object` otherwise.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
struct payload_param
|
||||
{
|
||||
payload_param(MappingConcept&& mc)
|
||||
: payload_(std::forward<MappingConcept>(mc))
|
||||
{}
|
||||
|
||||
MappingConcept get() && { return std::move(payload_); }
|
||||
const MappingConcept& get() const& { return payload_; }
|
||||
|
||||
MappingConcept payload_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing the secret key.
|
||||
* Stores only the view of the provided string
|
||||
* as string_view. Later the implementation may or
|
||||
* may-not copy it.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
struct secret_param
|
||||
{
|
||||
secret_param(string_view sv)
|
||||
: secret_(sv)
|
||||
{}
|
||||
|
||||
string_view get() { return secret_; }
|
||||
string_view secret_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct secret_function_param
|
||||
{
|
||||
T get() const { return fun_; }
|
||||
template <typename U>
|
||||
std::string get(U&& u) const { return fun_(u);}
|
||||
T fun_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing the algorithm to use.
|
||||
* The parameter can accept either the string representation
|
||||
* or the enum class.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
struct algorithm_param
|
||||
{
|
||||
algorithm_param(const string_view alg)
|
||||
: alg_(str_to_alg(alg))
|
||||
{}
|
||||
|
||||
algorithm_param(jwt::algorithm alg)
|
||||
: alg_(alg)
|
||||
{}
|
||||
|
||||
jwt::algorithm get() const noexcept
|
||||
{
|
||||
return alg_;
|
||||
}
|
||||
|
||||
typename jwt::algorithm alg_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameter for providing additional headers.
|
||||
* Takes a mapping concept representing
|
||||
* key-value pairs.
|
||||
*
|
||||
* Modeled as ParameterConcept.
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
struct headers_param
|
||||
{
|
||||
headers_param(MappingConcept&& mc)
|
||||
: headers_(std::forward<MappingConcept>(mc))
|
||||
{}
|
||||
|
||||
MappingConcept get() && { return std::move(headers_); }
|
||||
const MappingConcept& get() const& { return headers_; }
|
||||
|
||||
MappingConcept headers_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct verify_param
|
||||
{
|
||||
verify_param(bool v)
|
||||
: verify_(v)
|
||||
{}
|
||||
|
||||
bool get() const { return verify_; }
|
||||
|
||||
bool verify_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename Sequence>
|
||||
struct algorithms_param
|
||||
{
|
||||
algorithms_param(Sequence&& seq)
|
||||
: seq_(std::forward<Sequence>(seq))
|
||||
{}
|
||||
|
||||
Sequence get() && { return std::move(seq_); }
|
||||
const Sequence& get() const& { return seq_; }
|
||||
|
||||
Sequence seq_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct leeway_param
|
||||
{
|
||||
leeway_param(uint32_t v)
|
||||
: leeway_(v)
|
||||
{}
|
||||
|
||||
uint32_t get() const noexcept { return leeway_; }
|
||||
|
||||
uint32_t leeway_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct audience_param
|
||||
{
|
||||
audience_param(std::string aud)
|
||||
: aud_(std::move(aud))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return aud_; }
|
||||
std::string get() && noexcept { return aud_; }
|
||||
|
||||
std::string aud_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct issuer_param
|
||||
{
|
||||
issuer_param(std::string iss)
|
||||
: iss_(std::move(iss))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return iss_; }
|
||||
std::string get() && noexcept { return iss_; }
|
||||
|
||||
std::string iss_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct subject_param
|
||||
{
|
||||
subject_param(std::string sub)
|
||||
: sub_(std::move(sub))
|
||||
{}
|
||||
|
||||
const std::string& get() const& noexcept { return sub_; }
|
||||
std::string get() && noexcept { return sub_; }
|
||||
|
||||
std::string sub_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct validate_iat_param
|
||||
{
|
||||
validate_iat_param(bool v)
|
||||
: iat_(v)
|
||||
{}
|
||||
|
||||
bool get() const noexcept { return iat_; }
|
||||
|
||||
bool iat_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct validate_jti_param
|
||||
{
|
||||
validate_jti_param(bool v)
|
||||
: jti_(v)
|
||||
{}
|
||||
|
||||
bool get() const noexcept { return jti_; }
|
||||
|
||||
bool jti_;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
struct nbf_param
|
||||
{
|
||||
nbf_param(const jwt::system_time_t tp)
|
||||
: duration_(std::chrono::duration_cast<
|
||||
std::chrono::seconds>(tp.time_since_epoch()).count())
|
||||
{}
|
||||
|
||||
nbf_param(const uint64_t epoch)
|
||||
: duration_(epoch)
|
||||
{}
|
||||
|
||||
uint64_t get() const noexcept { return duration_; }
|
||||
|
||||
uint64_t duration_;
|
||||
};
|
||||
|
||||
} // END namespace detail
|
||||
|
||||
// Useful typedef
|
||||
using param_init_list_t = std::initializer_list<std::pair<jwt::string_view, jwt::string_view>>;
|
||||
using param_seq_list_t = std::initializer_list<jwt::string_view>;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::payload_param<std::unordered_map<std::string, std::string>>
|
||||
payload(const param_init_list_t& kvs)
|
||||
{
|
||||
std::unordered_map<std::string, std::string> m;
|
||||
|
||||
for (const auto& elem : kvs) {
|
||||
m.emplace(elem.first.data(), elem.second.data());
|
||||
}
|
||||
|
||||
return { std::move(m) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
detail::payload_param<MappingConcept>
|
||||
payload(MappingConcept&& mc)
|
||||
{
|
||||
static_assert (jwt::detail::meta::is_mapping_concept<MappingConcept>::value,
|
||||
"Template parameter does not meet the requirements for MappingConcept.");
|
||||
|
||||
return { std::forward<MappingConcept>(mc) };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::secret_param secret(const string_view sv)
|
||||
{
|
||||
return { sv };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::enable_if_t<!std::is_convertible<T, string_view>::value, detail::secret_function_param<T>>
|
||||
secret(T&& fun)
|
||||
{
|
||||
return detail::secret_function_param<T>{ fun };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithm_param algorithm(const string_view sv)
|
||||
{
|
||||
return { sv };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithm_param algorithm(jwt::algorithm alg)
|
||||
{
|
||||
return { alg };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::headers_param<std::map<std::string, std::string>>
|
||||
headers(const param_init_list_t& kvs)
|
||||
{
|
||||
std::map<std::string, std::string> m;
|
||||
|
||||
for (const auto& elem : kvs) {
|
||||
m.emplace(elem.first.data(), elem.second.data());
|
||||
}
|
||||
|
||||
return { std::move(m) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
template <typename MappingConcept>
|
||||
detail::headers_param<MappingConcept>
|
||||
headers(MappingConcept&& mc)
|
||||
{
|
||||
static_assert (jwt::detail::meta::is_mapping_concept<MappingConcept>::value,
|
||||
"Template parameter does not meet the requirements for MappingConcept.");
|
||||
|
||||
return { std::forward<MappingConcept>(mc) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::verify_param
|
||||
verify(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::leeway_param
|
||||
leeway(uint32_t l)
|
||||
{
|
||||
return { l };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::algorithms_param<std::vector<std::string>>
|
||||
algorithms(const param_seq_list_t& seq)
|
||||
{
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(seq.size());
|
||||
|
||||
for (const auto& e: seq) { vec.emplace_back(e.data(), e.length()); }
|
||||
|
||||
return { std::move(vec) };
|
||||
}
|
||||
|
||||
template <typename SequenceConcept>
|
||||
detail::algorithms_param<SequenceConcept>
|
||||
algorithms(SequenceConcept&& sc)
|
||||
{
|
||||
return { std::forward<SequenceConcept>(sc) };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::audience_param
|
||||
aud(const jwt::string_view aud)
|
||||
{
|
||||
return { aud.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::issuer_param
|
||||
issuer(const jwt::string_view iss)
|
||||
{
|
||||
return { iss.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::subject_param
|
||||
sub(const jwt::string_view subj)
|
||||
{
|
||||
return { subj.data() };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::validate_iat_param
|
||||
validate_iat(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::validate_jti_param
|
||||
validate_jti(bool v)
|
||||
{
|
||||
return { v };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::nbf_param
|
||||
nbf(const system_time_t tp)
|
||||
{
|
||||
return { tp };
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
inline detail::nbf_param
|
||||
nbf(const uint64_t epoch)
|
||||
{
|
||||
return { epoch };
|
||||
}
|
||||
|
||||
} // END namespace params
|
||||
} // END namespace jwt
|
||||
|
||||
#endif
|
38
externals/cpp-jwt/include/jwt/short_string.hpp
vendored
Executable file
38
externals/cpp-jwt/include/jwt/short_string.hpp
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CPP_JWT_SHORT_STRING_HPP
|
||||
#define CPP_JWT_SHORT_STRING_HPP
|
||||
|
||||
#include <string>
|
||||
#include "jwt/stack_alloc.hpp"
|
||||
|
||||
namespace jwt {
|
||||
/*
|
||||
* A basic_string implementation using stack allocation.
|
||||
*/
|
||||
template <size_t N>
|
||||
using short_string = std::basic_string<char, std::char_traits<char>, stack_alloc<char, N>>;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
200
externals/cpp-jwt/include/jwt/stack_alloc.hpp
vendored
Executable file
200
externals/cpp-jwt/include/jwt/stack_alloc.hpp
vendored
Executable file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2015 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef STACK_ALLOC_HPP
|
||||
#define STACK_ALLOC_HPP
|
||||
|
||||
/*
|
||||
* Based on Howard Hinnants awesome allocator boilerplate code
|
||||
* https://howardhinnant.github.io/short_alloc.h
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/*
|
||||
*/
|
||||
template <
|
||||
/// Size of the stack allocated byte buffer.
|
||||
size_t N,
|
||||
/// The alignment required for the buffer.
|
||||
size_t alignment = alignof(std::max_align_t)
|
||||
>
|
||||
class Arena
|
||||
{
|
||||
public: // 'tors
|
||||
Arena() noexcept
|
||||
: ptr_(buf_)
|
||||
{
|
||||
static_assert (alignment <= alignof(std::max_align_t),
|
||||
"Alignment chosen is more than the maximum supported alignment");
|
||||
}
|
||||
|
||||
/// Non copyable and assignable
|
||||
Arena(const Arena&) = delete;
|
||||
Arena& operator=(const Arena&) = delete;
|
||||
|
||||
~Arena()
|
||||
{
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public: // Public APIs
|
||||
|
||||
/*
|
||||
* Reserves space within the buffer of size atleast 'n'
|
||||
* bytes.
|
||||
* More bytes maybe reserved based on the alignment requirements.
|
||||
*
|
||||
* Returns:
|
||||
* 1. The pointer within the storage buffer where the object can be constructed.
|
||||
* 2. nullptr if space cannot be reserved for requested number of bytes
|
||||
* (+ alignment padding if applicable)
|
||||
*/
|
||||
template <
|
||||
/// The requested alignment for this allocation.
|
||||
/// Must be less than or equal to the 'alignment'.
|
||||
size_t requested_alignment
|
||||
>
|
||||
char* allocate(size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* Free back the space pointed by p within the storage buffer.
|
||||
*/
|
||||
void deallocate(char* p, size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* The size of the internal storage buffer.
|
||||
*/
|
||||
constexpr static size_t size() noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns number of remaining bytes within the storage buffer
|
||||
* that can be used for further allocation requests.
|
||||
*/
|
||||
size_t used() const noexcept
|
||||
{
|
||||
return static_cast<size_t>(ptr_ - buf_);
|
||||
}
|
||||
|
||||
private: // Private member functions
|
||||
|
||||
/*
|
||||
* A check to determine if the pointer 'p'
|
||||
* points to a region within storage.
|
||||
*/
|
||||
bool pointer_in_storage(char* p) const noexcept
|
||||
{
|
||||
return (buf_ <= p) && (p <= (buf_ + N));
|
||||
}
|
||||
|
||||
/*
|
||||
* Rounds up the number to the next closest number
|
||||
* as per the alignment.
|
||||
*/
|
||||
constexpr static size_t align_up(size_t n) noexcept
|
||||
{
|
||||
return (n + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
private: // data members
|
||||
/// Storage
|
||||
alignas(alignment) char buf_[N];
|
||||
|
||||
/// Current allocation pointer within storage
|
||||
char* ptr_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
template <
|
||||
/// The allocator for type T
|
||||
typename T,
|
||||
/// Number of bytes for the arena
|
||||
size_t N,
|
||||
/// Alignment of the arena
|
||||
size_t align = alignof(std::max_align_t)
|
||||
>
|
||||
class stack_alloc
|
||||
{
|
||||
public: // typedefs
|
||||
using value_type = T;
|
||||
using arena_type = Arena<N, align>;
|
||||
|
||||
static auto constexpr alignment = align;
|
||||
static auto constexpr size = N;
|
||||
|
||||
public: // 'tors
|
||||
stack_alloc(arena_type& a)
|
||||
: arena_(a)
|
||||
{
|
||||
}
|
||||
|
||||
stack_alloc(const stack_alloc&) = default;
|
||||
stack_alloc& operator=(const stack_alloc&) = delete;
|
||||
|
||||
template <typename U>
|
||||
stack_alloc(const stack_alloc<U, N, alignment>& other)
|
||||
: arena_(other.arena_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
struct rebind {
|
||||
using other = stack_alloc<U, N, alignment>;
|
||||
};
|
||||
|
||||
public: // Exposed APIs
|
||||
|
||||
/*
|
||||
* Allocate memory of 'n' bytes for object
|
||||
* of type 'T'
|
||||
*/
|
||||
T* allocate(size_t n) noexcept;
|
||||
|
||||
/*
|
||||
* Deallocate the storage reserved for the object
|
||||
* of type T pointed by pointer 'p'
|
||||
*/
|
||||
void deallocate(T* p, size_t n) noexcept;
|
||||
|
||||
private: // Private APIs
|
||||
|
||||
private: // Private data members
|
||||
/// The arena
|
||||
arena_type& arena_;
|
||||
};
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/stack_alloc.ipp"
|
||||
|
||||
#endif
|
381
externals/cpp-jwt/include/jwt/string_view.hpp
vendored
Executable file
381
externals/cpp-jwt/include/jwt/string_view.hpp
vendored
Executable file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
Copyright (c) 2017 Arun Muralidharan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef JWT_STRING_VIEW_HPP
|
||||
#define JWT_STRING_VIEW_HPP
|
||||
|
||||
#if defined(__cpp_lib_string_view)
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace jwt {
|
||||
using string_view = std::string_view;
|
||||
}
|
||||
|
||||
#else // defined(__cpp_lib_string_view)
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace jwt {
|
||||
|
||||
/*
|
||||
* Implements c++17 string_view.
|
||||
* Could have used boost::string_ref, but wanted to
|
||||
* keep boost dependency off from this library.
|
||||
*/
|
||||
|
||||
template <
|
||||
typename CharT,
|
||||
typename Traits = std::char_traits<CharT>
|
||||
>
|
||||
class basic_string_view
|
||||
{
|
||||
public: // Member Types
|
||||
using traits_type = std::char_traits<CharT>;
|
||||
using value_type = CharT;
|
||||
using pointer = const CharT*;
|
||||
using const_pointer = const CharT*;
|
||||
using reference = const CharT&;
|
||||
using const_reference = const CharT&;
|
||||
using iterator = const CharT*;
|
||||
using const_iterator = const CharT*;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using size_type = size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
static constexpr size_type npos = size_type(-1);
|
||||
|
||||
public: // 'tors
|
||||
/// The default constructor;
|
||||
basic_string_view() = default;
|
||||
|
||||
/// Construct from string literal
|
||||
basic_string_view(const CharT* str) noexcept
|
||||
: data_(str)
|
||||
, len_(str ? traits_type::length(str) : 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from CharT pointer and provided length
|
||||
basic_string_view(const CharT* p, size_type len) noexcept
|
||||
: data_(p)
|
||||
, len_(len)
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct from std::string
|
||||
template <typename Allocator>
|
||||
basic_string_view(
|
||||
const std::basic_string<CharT, Traits, Allocator>& str) noexcept
|
||||
: data_(str.data())
|
||||
, len_(str.length())
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
basic_string_view(const basic_string_view&) = default;
|
||||
|
||||
/// Assignment operator
|
||||
basic_string_view& operator=(const basic_string_view&) = default;
|
||||
|
||||
/// Destructor
|
||||
~basic_string_view()
|
||||
{
|
||||
data_ = nullptr;
|
||||
len_ = 0;
|
||||
}
|
||||
|
||||
public: // Exposed APIs
|
||||
/// Iterator Member Functions
|
||||
|
||||
iterator begin() const noexcept { return data_; }
|
||||
iterator end() const noexcept { return data_ + len_; }
|
||||
|
||||
iterator rbegin() const noexcept { return reverse_iterator(end()); }
|
||||
iterator rend() const noexcept { return reverse_iterator(begin()); }
|
||||
|
||||
const_iterator cbegin() const noexcept { return begin(); }
|
||||
const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
const_iterator crbegin() const noexcept { return rbegin(); }
|
||||
const_iterator crend() const noexcept { return rend(); }
|
||||
|
||||
/// Capacity Member Functions
|
||||
|
||||
size_type length() const noexcept { return len_; }
|
||||
size_type size() const noexcept { return len_; }
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return (npos - sizeof(size_type) - sizeof(void*))
|
||||
/ sizeof(value_type) / 4;
|
||||
}
|
||||
|
||||
bool empty() const noexcept { return len_ == 0; }
|
||||
|
||||
/// Element Access Member Functions
|
||||
const_reference operator[](size_type idx) const noexcept
|
||||
{
|
||||
assert(idx < len_ && "string_view subscript out of range");
|
||||
return data_[idx];
|
||||
}
|
||||
|
||||
// NOTE: 'at' not supported
|
||||
//CharT at(size_type idx) const;
|
||||
|
||||
const_reference front() const noexcept
|
||||
{
|
||||
return data_[0];
|
||||
}
|
||||
|
||||
const_reference back() const noexcept
|
||||
{
|
||||
return data_[len_ - 1];
|
||||
}
|
||||
|
||||
const_pointer data() const noexcept
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
/// Modifier Member Functions
|
||||
void remove_prefix(size_type n) noexcept
|
||||
{
|
||||
assert (n < len_ && "Data would point out of bounds");
|
||||
data_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void remove_suffix(size_type n) noexcept
|
||||
{
|
||||
assert (n < len_ && "Suffix length more than data length");
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
void swap(basic_string_view& other)
|
||||
{
|
||||
std::swap(data_, other.data_);
|
||||
std::swap(len_, other.len_);
|
||||
}
|
||||
|
||||
/// String Operation Member Functions
|
||||
|
||||
template <typename Allocator>
|
||||
explicit operator std::basic_string<CharT, Traits, Allocator>() const
|
||||
{
|
||||
return {data_, len_};
|
||||
}
|
||||
|
||||
// NOTE: Does not throw
|
||||
size_type copy(CharT* dest, size_type n, size_type pos = 0) const noexcept
|
||||
{
|
||||
assert (pos < len_ && n < len_);
|
||||
size_type to_copy = std::min(n, len_ - pos);
|
||||
|
||||
for (size_type i = 0; i < to_copy; i++) {
|
||||
dest[i] = data_[i + pos];
|
||||
}
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
// NOTE: Does not throw
|
||||
basic_string_view substr(size_type pos, size_type n = npos) const noexcept
|
||||
{
|
||||
assert (pos < len_ && "Start position should be less than length of the view");
|
||||
assert (n == npos ? 1 : (n - pos) < len_ &&
|
||||
"Substring length asked for is more than the view length");
|
||||
|
||||
if (n == npos) n = len_;
|
||||
|
||||
return basic_string_view{data_ + pos, n};
|
||||
}
|
||||
|
||||
/// Comparison Member Functions
|
||||
int compare(const basic_string_view& other) const noexcept
|
||||
{
|
||||
int ret = traits_type::compare(data_, other.data_, std::min(len_, other.len_));
|
||||
if (ret == 0) {
|
||||
ret = compare_length(len_, other.len_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n, basic_string_view other) const noexcept
|
||||
{
|
||||
return substr(pos, n).compare(other);
|
||||
}
|
||||
|
||||
int compare(const CharT* str) const noexcept
|
||||
{
|
||||
return compare(basic_string_view{str});
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n, const CharT* str) const noexcept
|
||||
{
|
||||
return compare(pos, n, basic_string_view{str});
|
||||
}
|
||||
|
||||
int compare(size_type pos, size_type n1, const CharT* str, size_type n2) const noexcept
|
||||
{
|
||||
return compare(pos, n1, basic_string_view{str, n2});
|
||||
}
|
||||
|
||||
/// Find operations
|
||||
size_type find(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find(const CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find(basic_string_view sv, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(sv.data(), pos, sv.length());
|
||||
}
|
||||
|
||||
size_type find(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type rfind(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type rfind(const CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type rfind(basic_string_view sv, size_type pos = 0) const noexcept
|
||||
{
|
||||
return rfind(sv.data(), pos, sv.length());
|
||||
}
|
||||
|
||||
size_type rfind(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return rfind(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_first_of(const CharT* str, size_type pos, size_type count) const noexcept;
|
||||
|
||||
size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(str.data(), pos, str.length());
|
||||
}
|
||||
|
||||
size_type find_first_of(CharT ch, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find(ch, pos);
|
||||
}
|
||||
|
||||
size_type find_first_of(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_of(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_last_of(const CharT* str, size_type pos, size_type count) const noexcept;
|
||||
|
||||
size_type find_last_of(basic_string_view str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length());
|
||||
}
|
||||
|
||||
size_type find_last_of(CharT ch, size_type pos = npos) const noexcept
|
||||
{
|
||||
return rfind(ch, pos == npos ? len_ - 1 : pos);
|
||||
}
|
||||
|
||||
size_type find_last_of(const CharT* str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_first_not_of(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find_first_not_of(CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(str.data(), pos, str.length());
|
||||
}
|
||||
|
||||
size_type find_first_not_of(const CharT* str, size_type pos = 0) const noexcept
|
||||
{
|
||||
return find_first_not_of(str, pos, traits_type::length(str));
|
||||
}
|
||||
|
||||
size_type find_last_not_of(const CharT* str, size_type pos, size_type n) const noexcept;
|
||||
|
||||
size_type find_last_not_of(CharT ch, size_type pos) const noexcept;
|
||||
|
||||
size_type find_last_not_of(basic_string_view str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(str.data(), (pos == npos ? len_ - 1 : pos), str.length());
|
||||
}
|
||||
|
||||
size_type find_last_not_of(const CharT* str, size_type pos = npos) const noexcept
|
||||
{
|
||||
return find_last_not_of(str, (pos == npos ? len_ - 1 : pos), traits_type::length(str));
|
||||
}
|
||||
|
||||
/// Comparison operators Member Functions
|
||||
/*
|
||||
friend bool operator== (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator!= (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator< (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator> (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator<= (basic_string_view a, basic_string_view b) noexcept;
|
||||
|
||||
friend bool operator>= (basic_string_view a, basic_string_view b) noexcept;
|
||||
*/
|
||||
|
||||
private: // private implementations
|
||||
|
||||
static constexpr int compare_length(size_type n1, size_type n2) noexcept
|
||||
{
|
||||
return static_cast<difference_type>(n1 - n2) > std::numeric_limits<int>::max()
|
||||
? std::numeric_limits<int>::max()
|
||||
: static_cast<difference_type>(n1 - n2) < std::numeric_limits<int>::min()
|
||||
? std::numeric_limits<int>::min()
|
||||
: static_cast<int>(n1 - n2)
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
// This is what view is basically...
|
||||
const char* data_ = nullptr;
|
||||
size_type len_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/// Helper typedef
|
||||
using string_view = basic_string_view<char>;
|
||||
|
||||
|
||||
} // END namespace jwt
|
||||
|
||||
#include "jwt/impl/string_view.ipp"
|
||||
|
||||
#endif // defined(__cpp_lib_string_view)
|
||||
|
||||
#endif
|
1
externals/cpp-jwt/include/jwt/test/compile.txt
vendored
Executable file
1
externals/cpp-jwt/include/jwt/test/compile.txt
vendored
Executable file
@@ -0,0 +1 @@
|
||||
g++ -std=c++14 -I /usr/local/Cellar/openssl/1.0.2j/include/ -I /Users/amuralid/dev_test/cpp-jwt/include/ -o test_rsa test_rsa.cc -L /usr/local/Cellar//openssl/1.0.2j/lib/ -lssl -lcrypto
|
BIN
externals/cpp-jwt/include/jwt/test/test_base64
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_base64
vendored
Executable file
Binary file not shown.
48
externals/cpp-jwt/include/jwt/test/test_base64.cc
vendored
Executable file
48
externals/cpp-jwt/include/jwt/test/test_base64.cc
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include "jwt/base64.hpp"
|
||||
|
||||
void base64_test_encode()
|
||||
{
|
||||
std::string input = "ArunMu";
|
||||
std::string output = jwt::base64_encode(input.c_str(), input.length());
|
||||
assert (output == "QXJ1bk11");
|
||||
|
||||
input = "Something really strange!!";
|
||||
output = jwt::base64_encode(input.c_str(), input.length());
|
||||
assert (output == "U29tZXRoaW5nIHJlYWxseSBzdHJhbmdlISE=");
|
||||
|
||||
input = "Do you want to know something more stranger ????";
|
||||
output = jwt::base64_encode(input.c_str(), input.length());
|
||||
assert (output == "RG8geW91IHdhbnQgdG8ga25vdyBzb21ldGhpbmcgbW9yZSBzdHJhbmdlciA/Pz8/");
|
||||
|
||||
input = R"({"a" : "b", "c" : [1,2,3,4,5]})";
|
||||
output = jwt::base64_encode(input.c_str(), input.length());
|
||||
assert (output == "eyJhIiA6ICJiIiwgImMiIDogWzEsMiwzLDQsNV19");
|
||||
}
|
||||
|
||||
void base64_test_decode()
|
||||
{
|
||||
std::string input = "QXJ1bk11";
|
||||
std::string output = jwt::base64_decode(input.c_str(), input.length());
|
||||
assert (output == "ArunMu");
|
||||
|
||||
input = "U29tZXRoaW5nIHJlYWxseSBzdHJhbmdlISE=";
|
||||
output = jwt::base64_decode(input.c_str(), input.length());
|
||||
assert (output == "Something really strange!!");
|
||||
|
||||
input = "RG8geW91IHdhbnQgdG8ga25vdyBzb21ldGhpbmcgbW9yZSBzdHJhbmdlciA/Pz8/";
|
||||
output = jwt::base64_decode(input.c_str(), input.length());
|
||||
assert (output == "Do you want to know something more stranger ????");
|
||||
|
||||
input = "eyJhIiA6ICJiIiwgImMiIDogWzEsMiwzLDQsNV19";
|
||||
output = jwt::base64_decode(input.c_str(), input.length());
|
||||
assert (output == R"({"a" : "b", "c" : [1,2,3,4,5]})");
|
||||
}
|
||||
|
||||
int main() {
|
||||
base64_test_encode();
|
||||
base64_test_decode();
|
||||
return 0;
|
||||
}
|
45
externals/cpp-jwt/include/jwt/test/test_evp.c
vendored
Executable file
45
externals/cpp-jwt/include/jwt/test/test_evp.c
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
EVP_MD_CTX *mdctx;
|
||||
const EVP_MD *md;
|
||||
char mess1[] = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaXNzIjoiYXJ1bi5jb20iLCJ0aW1lX3N0ciI6Ijg6MThwbSAyNCBOb3YgMjAxNyIsIndoZXJlIjoiYWlycG9ydCJ9";
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
int md_len, i;
|
||||
|
||||
//OpenSSL_add_all_digests();
|
||||
|
||||
if(!argv[1]) {
|
||||
printf("Usage: mdtest digestname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
md = EVP_sha256();
|
||||
|
||||
if(!md) {
|
||||
printf("Unknown message digest %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mdctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit_ex(mdctx, md, NULL);
|
||||
EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
|
||||
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
|
||||
printf("Dig: %s\n", md_value);
|
||||
printf("Dig: %d\n", md_len);
|
||||
|
||||
printf("Digest is: ");
|
||||
for(i = 0; i < md_len; i++)
|
||||
printf("%02x", md_value[i]);
|
||||
printf("\n");
|
||||
|
||||
d2i_ECDSA_SIG(NULL, (const unsigned char **)&md_value[0], md_len);
|
||||
|
||||
/* Call this once before exit. */
|
||||
EVP_cleanup();
|
||||
exit(0);
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_hmac
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_hmac
vendored
Executable file
Binary file not shown.
16
externals/cpp-jwt/include/jwt/test/test_hmac.cc
vendored
Executable file
16
externals/cpp-jwt/include/jwt/test/test_hmac.cc
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include "jwt/algorithm.hpp"
|
||||
|
||||
void basic_hmac_test()
|
||||
{
|
||||
jwt::string_view sv = "secret" ;
|
||||
jwt::string_view d = "Some random data string";
|
||||
auto res = jwt::HMACSign<jwt::algo::HS256>::sign(sv, d);
|
||||
|
||||
std::cout << res.first << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_hmac_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_decode
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_decode
vendored
Executable file
Binary file not shown.
30
externals/cpp-jwt/include/jwt/test/test_jwt_decode.cc
vendored
Executable file
30
externals/cpp-jwt/include/jwt/test/test_jwt_decode.cc
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_decode_test()
|
||||
{
|
||||
// Create header
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
|
||||
// Create payload
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("sub", "1234567890");
|
||||
jp.add_claim("name", "John Doe");
|
||||
jp.add_claim("admin", true);
|
||||
|
||||
jwt::jwt_signature sgn{"secret"};
|
||||
std::error_code ec{};
|
||||
auto res = sgn.encode(hdr, jp, ec);
|
||||
std::cout << res << std::endl;
|
||||
|
||||
using namespace jwt::params;
|
||||
|
||||
std::cout << "DECODE: \n";
|
||||
jwt::decode(res, algorithms({"none", "HS256"}), ec, verify(false), secret("secret"));
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_decode_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_header
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_header
vendored
Executable file
Binary file not shown.
19
externals/cpp-jwt/include/jwt/test/test_jwt_header.cc
vendored
Executable file
19
externals/cpp-jwt/include/jwt/test/test_jwt_header.cc
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void test_basic_header()
|
||||
{
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
std::string jstr = to_json_str(hdr);
|
||||
std::cout << jstr << std::endl;
|
||||
|
||||
std::string enc_str = hdr.base64_encode();
|
||||
std::cout << "Base64: " << enc_str << std::endl;
|
||||
std::cout << "Decoded: " << hdr.base64_decode(enc_str) << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_basic_header();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_object
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_object
vendored
Executable file
Binary file not shown.
93
externals/cpp-jwt/include/jwt/test/test_jwt_object.cc
vendored
Executable file
93
externals/cpp-jwt/include/jwt/test/test_jwt_object.cc
vendored
Executable file
@@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <unordered_map>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_jwt_object_test()
|
||||
{
|
||||
using namespace jwt::params;
|
||||
jwt::jwt_object obj(payload({
|
||||
{"a", "b"},
|
||||
{"c", "d"}
|
||||
}));
|
||||
|
||||
//check with std::map
|
||||
std::map<std::string, std::string> m;
|
||||
m["a"] = "b";
|
||||
m["c"] = "d";
|
||||
|
||||
jwt::jwt_object obj1{payload(m)};
|
||||
|
||||
auto obj2 = std::move(obj1);
|
||||
|
||||
std::cout << obj2.payload() << std::endl;
|
||||
|
||||
//check with unordered map of string_view
|
||||
std::unordered_map<jwt::string_view, std::string> um = {
|
||||
{"a", "b"},
|
||||
{"c", "d"}
|
||||
};
|
||||
jwt::jwt_object obj3{payload(um)};
|
||||
|
||||
obj3.add_claim("f", true)
|
||||
.add_claim("time", 176353563)
|
||||
.add_claim("exp", std::chrono::system_clock::now())
|
||||
;
|
||||
|
||||
std::cout << jwt::to_json_str(obj3.payload(), true) << std::endl;
|
||||
|
||||
obj3.remove_claim(std::string{"a"});
|
||||
std::cout << obj3.payload() << std::endl;
|
||||
|
||||
obj3.secret("secret");
|
||||
obj3.header().algo("HS256");
|
||||
|
||||
auto dec_obj = jwt::decode(obj3.signature(), algorithms({"HS256"}), secret("secret"));
|
||||
}
|
||||
|
||||
void jwt_object_pem_test()
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string pub_key =
|
||||
R"(-----BEGIN PUBLIC KEY-----
|
||||
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEomxC9ycc8AkXSwWQpu1kN5Fmgy/sD/KJ
|
||||
qN3tlSZmUEZ3w3c6KYJfK97PMOSZQaUdeydBoq/IOglQQOj8zLqubq5IpaaUiDQ5
|
||||
0eJg79PvXuLiVUH98cBL/o8sDVB/sGzz
|
||||
-----END PUBLIC KEY-----)";
|
||||
|
||||
std::string priv_key =
|
||||
R"(-----BEGIN EC PRIVATE KEY-----
|
||||
MIGkAgEBBDBeLCgapjZmvTatMHaYX3A02+0Ys3Tr8kda+E9DFnmCSiCOEig519fT
|
||||
13edeU8YdDugBwYFK4EEACKhZANiAASibEL3JxzwCRdLBZCm7WQ3kWaDL+wP8omo
|
||||
3e2VJmZQRnfDdzopgl8r3s8w5JlBpR17J0Gir8g6CVBA6PzMuq5urkilppSINDnR
|
||||
4mDv0+9e4uJVQf3xwEv+jywNUH+wbPM=
|
||||
-----END EC PRIVATE KEY-----)";
|
||||
|
||||
jwt::jwt_object obj;
|
||||
obj.secret(priv_key);
|
||||
obj.header().algo(jwt::algorithm::ES256);
|
||||
|
||||
obj.add_claim("iss", "arun.com")
|
||||
.add_claim("where", "airport")
|
||||
.add_claim("time_str", "8:18pm 24 Nov 2017")
|
||||
.add_claim("id", 1)
|
||||
.add_claim("exp", std::chrono::system_clock::now())
|
||||
;
|
||||
|
||||
std::cout << "pem sign " << obj.signature() << std::endl;
|
||||
std::cout << "Get claim value for exp: " <<
|
||||
obj.payload().get_claim_value<uint64_t>("exp") << std::endl;
|
||||
|
||||
auto dec_obj = jwt::decode(obj.signature(), algorithms({"ES256"}), secret(pub_key));
|
||||
std::cout << dec_obj.payload() << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_jwt_object_test();
|
||||
//jwt_object_pem_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_payload
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_payload
vendored
Executable file
Binary file not shown.
34
externals/cpp-jwt/include/jwt/test/test_jwt_payload.cc
vendored
Executable file
34
externals/cpp-jwt/include/jwt/test/test_jwt_payload.cc
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_payload_test()
|
||||
{
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("iss", "myself");
|
||||
jp.add_claim("exp", 1234567);
|
||||
jp.add_claim("Exp", 1234567, true);
|
||||
|
||||
auto jstr = jwt::to_json_str(jp);
|
||||
std::cout << jstr << std::endl;
|
||||
|
||||
auto enc = jp.base64_encode();
|
||||
std::cout << "Base64 enc: " << enc << std::endl;
|
||||
|
||||
auto dec = jp.base64_decode(enc);
|
||||
std::cout << "Base64 dec: " << dec << std::endl;
|
||||
std::cout << "Base64 dec: " << jstr << std::endl;
|
||||
|
||||
assert (jstr == dec && "Encoded and decoded messages do not match");
|
||||
assert (jp.has_claim("exp") && "Claim exp must exist");
|
||||
assert (jp.has_claim("Exp") && "Claim Exp must exist");
|
||||
|
||||
assert (!jp.has_claim("aud") && "Claim aud does not exist");
|
||||
assert (jp.has_claim_with_value("exp", 1234567) && "Claim exp with value 1234567 does not exist");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_payload_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_signature
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_jwt_signature
vendored
Executable file
Binary file not shown.
25
externals/cpp-jwt/include/jwt/test/test_jwt_signature.cc
vendored
Executable file
25
externals/cpp-jwt/include/jwt/test/test_jwt_signature.cc
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
#include <iostream>
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
void basic_sign_test()
|
||||
{
|
||||
// Create header
|
||||
jwt::jwt_header hdr;
|
||||
hdr = jwt::jwt_header{jwt::algorithm::HS256};
|
||||
|
||||
// Create payload
|
||||
jwt::jwt_payload jp;
|
||||
jp.add_claim("sub", "1234567890");
|
||||
jp.add_claim("name", "John Doe");
|
||||
jp.add_claim("admin", true);
|
||||
|
||||
jwt::jwt_signature sgn{"secret"};
|
||||
std::error_code ec{};
|
||||
auto res = sgn.encode(hdr, jp, ec);
|
||||
std::cout << res << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_sign_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_rsa
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_rsa
vendored
Executable file
Binary file not shown.
47
externals/cpp-jwt/include/jwt/test/test_rsa.cc
vendored
Executable file
47
externals/cpp-jwt/include/jwt/test/test_rsa.cc
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
#include <iostream>
|
||||
#include "jwt/algorithm.hpp"
|
||||
|
||||
static const char* rsa_2048_pem =
|
||||
R"(-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDC2kwAziXUf33m
|
||||
iqWp0yG6o259+nj7hpQLC4UT0Hmz0wmvreDJ/yNbSgOvsxvVdvzL2IaRZ+Gi5mo0
|
||||
lswWvL6IGz7PZO0kXTq9sdBnNqMOx27HddV9e/2/p0MgibJTbgywY2Sk23QYhJpq
|
||||
Kq/nU0xlBfSaI5ddZ2RC9ZNkVeGawUKYksTruhAVJqviHN8BoK6VowP5vcxyyOWH
|
||||
TK9KruDqzCIhqwRTeo0spokBkTN/LCuhVivcHAzUiJVtB4qAiTI9L/zkzhjpKz9P
|
||||
45aLU54rj011gG8U/6E1USh5nMnPkr+d3oLfkhfS3Zs3kJVdyFQWZpQxiTaI92Fd
|
||||
2wLvbS0HAgMBAAECggEAD8dTnkETSSjlzhRuI9loAtAXM3Zj86JLPLW7GgaoxEoT
|
||||
n7lJ2bGicFMHB2ROnbOb9vnas82gtOtJsGaBslmoaCckp/C5T1eJWTEb+i+vdpPp
|
||||
wZcmKZovyyRFSE4+NYlU17fEv6DRvuaGBpDcW7QgHJIl45F8QWEM+msee2KE+V4G
|
||||
z/9vAQ+sOlvsb4mJP1tJIBx9Lb5loVREwCRy2Ha9tnWdDNar8EYkOn8si4snPT+E
|
||||
3ZCy8mlcZyUkZeiS/HdtydxZfoiwrSRYamd1diQpPhWCeRteQ802a7ds0Y2YzgfF
|
||||
UaYjNuRQm7zA//hwbXS7ELPyNMU15N00bajlG0tUOQKBgQDnLy01l20OneW6A2cI
|
||||
DIDyYhy5O7uulsaEtJReUlcjEDMkin8b767q2VZHb//3ZH+ipnRYByUUyYUhdOs2
|
||||
DYRGGeAebnH8wpTT4FCYxUsIUpDfB7RwfdBONgaKewTJz/FPswy1Ye0b5H2c6vVi
|
||||
m2FZ33HQcoZ3wvFFqyGVnMzpOwKBgQDXxL95yoxUGKa8vMzcE3Cn01szh0dFq0sq
|
||||
cFpM+HWLVr84CItuG9H6L0KaStEEIOiJsxOVpcXfFFhsJvOGhMA4DQTwH4WuXmXp
|
||||
1PoVMDlV65PYqvhzwL4+QhvZO2bsrEunITXOmU7CI6kilnAN3LuP4HbqZgoX9lqP
|
||||
I31VYzLupQKBgGEYck9w0s/xxxtR9ILv5XRnepLdoJzaHHR991aKFKjYU/KD7JDK
|
||||
INfoAhGs23+HCQhCCtkx3wQVA0Ii/erM0II0ueluD5fODX3TV2ZibnoHW2sgrEsW
|
||||
vFcs36BnvIIaQMptc+f2QgSV+Z/fGsKYadG6Q+39O7au/HB7SHayzWkjAoGBAMgt
|
||||
Fzslp9TpXd9iBWjzfCOnGUiP65Z+GWkQ/SXFqD+SRir0+m43zzGdoNvGJ23+Hd6K
|
||||
TdQbDJ0uoe4MoQeepzoZEgi4JeykVUZ/uVfo+nh06yArVf8FxTm7WVzLGGzgV/uA
|
||||
+wtl/cRtEyAsk1649yW/KHPEIP8kJdYAJeoO8xSlAoGAERMrkFR7KGYZG1eFNRdV
|
||||
mJMq+Ibxyw8ks/CbiI+n3yUyk1U8962ol2Q0T4qjBmb26L5rrhNQhneM4e8mo9FX
|
||||
LlQapYkPvkdrqW0Bp72A/UNAvcGTmN7z5OCJGMUutx2hmEAlrYmpLKS8pM/p9zpK
|
||||
tEOtzsP5GMDYVlEp1jYSjzQ=
|
||||
-----END PRIVATE KEY-----)";
|
||||
|
||||
void basic_rsa_test()
|
||||
{
|
||||
jwt::string_view sv = rsa_2048_pem;
|
||||
jwt::string_view d = "Some random data string";
|
||||
|
||||
auto res = jwt::PEMSign<jwt::algo::RS256>::sign(sv, d);
|
||||
|
||||
std::cout << res.first << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_rsa_test();
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_stack_alloc
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_stack_alloc
vendored
Executable file
Binary file not shown.
22
externals/cpp-jwt/include/jwt/test/test_stack_alloc.cc
vendored
Executable file
22
externals/cpp-jwt/include/jwt/test/test_stack_alloc.cc
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "jwt/stack_alloc.hpp"
|
||||
|
||||
template <typename T, size_t SZ = 2>
|
||||
using SmallVector = std::vector<T, jwt::stack_alloc<T, SZ, alignof(T)>>;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
SmallVector<int>::allocator_type::arena_type a;
|
||||
SmallVector<int> v{a};
|
||||
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
v.push_back(1);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
externals/cpp-jwt/include/jwt/test/test_sv
vendored
Executable file
BIN
externals/cpp-jwt/include/jwt/test/test_sv
vendored
Executable file
Binary file not shown.
169
externals/cpp-jwt/include/jwt/test/test_sv.cc
vendored
Executable file
169
externals/cpp-jwt/include/jwt/test/test_sv.cc
vendored
Executable file
@@ -0,0 +1,169 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include "jwt/string_view.hpp"
|
||||
|
||||
using string_view = jwt::basic_string_view<char>;
|
||||
|
||||
void basic_cons()
|
||||
{
|
||||
// Default construction
|
||||
string_view sv{};
|
||||
assert (sv.length() == 0 && "Size must be zero for default constructor");
|
||||
|
||||
// Construction from string literal
|
||||
string_view sv2{"Arun Muralidharan"};
|
||||
assert (sv2.length() == strlen("Arun Muralidharan") && "Lengths must match");
|
||||
|
||||
const char* haystack = "some really big data with infinite objects....";
|
||||
|
||||
// Construct using part of data
|
||||
string_view sv3{haystack, 4};
|
||||
assert (sv3.length() == 4 && "Partial construction is not ok");
|
||||
assert (sv3.to_string() == "some" && "Partial strings are not equal");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void iterator_test()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
for (auto c : sv) std::cout << c;
|
||||
std::cout << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void str_operations()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
string_view tmp = sv;
|
||||
sv.remove_prefix(5);
|
||||
assert (sv.to_string() == "Muralidharan" && "Remove prefix failed");
|
||||
|
||||
sv = tmp;
|
||||
sv.remove_suffix(strlen("Muralidharan"));
|
||||
assert (sv.to_string() == "Arun " && "Remove suffix failed");
|
||||
|
||||
sv=tmp;
|
||||
{
|
||||
std::unique_ptr<char[]> dst{new char[32]};
|
||||
sv.copy(dst.get(), 6, 0);
|
||||
dst[6] = '\0';
|
||||
assert (strlen(dst.get()) == 6 && "Copy Failed-1");
|
||||
assert (std::string{dst.get()} == "Arun M" && "Copy Failed-2");
|
||||
|
||||
sv.copy(dst.get(), 8, 4);
|
||||
dst[8] = '\0';
|
||||
assert (strlen(dst.get()) == 8 && "Middle copy failed-1");
|
||||
assert (std::string{dst.get()} == " Muralid" && "Middle copy failed-2");
|
||||
}
|
||||
|
||||
{
|
||||
auto ss1 = sv.substr(0, 4);
|
||||
assert (ss1.to_string() == "Arun" && "Substr failed - 1");
|
||||
|
||||
auto ss2 = sv.substr(1, 3);
|
||||
assert (ss2.to_string() == "run" && "Substr failed - 2");
|
||||
|
||||
auto ss3 = sv.substr(0);
|
||||
assert (ss3.length() == sv.length() && "Substr failed - 3");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void find_oper()
|
||||
{
|
||||
string_view sv{"Arun Muralidharan"};
|
||||
auto pos = sv.find("Arun", 0, 4);
|
||||
assert (pos == 0 && "Arun not found in sv");
|
||||
|
||||
pos = sv.find("arun", 0, 4);
|
||||
assert (pos == string_view::npos && "arun is not there in sv");
|
||||
|
||||
sv = "This has a, in it.";
|
||||
pos = sv.find_first_of(",", 0, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(",", 10, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(":", 10, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(",", 5, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(",", sv.length() - 1, 1);
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10 && "Comma not found at correct place");
|
||||
|
||||
pos = sv.find_first_of(".", 0, 1);
|
||||
assert (pos == sv.length() - 1 && "Dot not found at correct place");
|
||||
|
||||
pos = sv.find_last_of(".", sv.length() - 2, 1);
|
||||
assert (pos == string_view::npos);
|
||||
|
||||
pos = sv.find_last_of(".", sv.length() - 1, 1);
|
||||
assert (pos == sv.length() - 1);
|
||||
|
||||
sv = "Some string :<> with some ??? pattern --**";
|
||||
|
||||
pos = sv.rfind("???", sv.length() - 1, 3);
|
||||
assert (pos != string_view::npos && "??? not found");
|
||||
assert (pos == 26 && "??? not found at the correct place");
|
||||
|
||||
sv = "ATCGTTCACGRRRTCGGGGACGTC";
|
||||
|
||||
pos = sv.find_first_not_of("ATCG");
|
||||
assert (pos != string_view::npos);
|
||||
assert (pos == 10);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void conversions()
|
||||
{
|
||||
auto c2sv = [](int num) -> string_view {
|
||||
switch (num) {
|
||||
case 1: return "one";
|
||||
case 2: return "two";
|
||||
case 3: return "three";
|
||||
default: return "many";
|
||||
};
|
||||
};
|
||||
|
||||
auto res = c2sv(2);
|
||||
assert (res.to_string() == "two");
|
||||
|
||||
auto s2sv = [](std::string s) {
|
||||
return s;
|
||||
};
|
||||
|
||||
s2sv(static_cast<std::string>(res));
|
||||
}
|
||||
|
||||
void comparisons()
|
||||
{
|
||||
string_view s1{"Apple"};
|
||||
string_view s2{"Orange"};
|
||||
|
||||
assert (s1 != s2 && "Two string views are not equal");
|
||||
assert (s2 > s1 && "Orange is lexicographically bigger than Apple");
|
||||
|
||||
s2 = "Apples";
|
||||
assert (s2 > s1 && "Because Apples is plural");
|
||||
}
|
||||
|
||||
int main() {
|
||||
basic_cons();
|
||||
iterator_test();
|
||||
str_operations();
|
||||
find_oper();
|
||||
conversions();
|
||||
comparisons();
|
||||
return 0;
|
||||
};
|
69
externals/cpp-jwt/tests/CMakeLists.txt
vendored
Executable file
69
externals/cpp-jwt/tests/CMakeLists.txt
vendored
Executable file
@@ -0,0 +1,69 @@
|
||||
set(CERT_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/certs")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -DCERT_ROOT_DIR=\"\\\"${CERT_ROOT_DIR}\\\"\"")
|
||||
|
||||
add_executable(test_jwt_object test_jwt_object.cc)
|
||||
target_link_libraries(test_jwt_object GTest::GTest GTest::Main ${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_object PRIVATE ${GTEST_INCLUDE_DIRS}
|
||||
${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_object
|
||||
COMMAND ./test_jwt_object
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_encode test_jwt_encode.cc)
|
||||
target_link_libraries(test_jwt_encode GTest::GTest GTest::Main ${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_encode PRIVATE ${GTEST_INCLUDE_DIRS}
|
||||
${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_encode
|
||||
COMMAND ./test_jwt_encode
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_decode test_jwt_decode.cc)
|
||||
target_link_libraries(test_jwt_decode GTest::GTest GTest::Main ${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_decode PRIVATE ${GTEST_INCLUDE_DIRS}
|
||||
${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_decode
|
||||
COMMAND ./test_jwt_decode
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_decode_verifiy test_jwt_decode_verifiy.cc)
|
||||
target_link_libraries(test_jwt_decode_verifiy GTest::GTest GTest::Main
|
||||
${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_decode_verifiy
|
||||
PRIVATE ${GTEST_INCLUDE_DIRS} ${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_decode_verifiy
|
||||
COMMAND ./test_jwt_decode_verifiy
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_decode_verifiy_with_exception
|
||||
test_jwt_decode_verifiy_with_exception.cc)
|
||||
target_link_libraries(test_jwt_decode_verifiy_with_exception GTest::GTest GTest::Main
|
||||
${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_decode_verifiy_with_exception
|
||||
PRIVATE ${GTEST_INCLUDE_DIRS} ${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_decode_verifiy_with_exception
|
||||
COMMAND ./test_jwt_decode_verifiy_with_exception
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_rsa test_jwt_rsa.cc)
|
||||
target_link_libraries(test_jwt_rsa GTest::GTest GTest::Main ${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_rsa PRIVATE ${GTEST_INCLUDE_DIRS}
|
||||
${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_rsa
|
||||
COMMAND ./test_jwt_rsa
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_executable(test_jwt_es test_jwt_es.cc)
|
||||
target_link_libraries(test_jwt_es GTest::GTest GTest::Main ${PROJECT_NAME})
|
||||
target_include_directories(test_jwt_es PRIVATE ${GTEST_INCLUDE_DIRS}
|
||||
${GTest_INCLUDE_DIRS})
|
||||
add_test(
|
||||
NAME test_jwt_es
|
||||
COMMAND ./test_jwt_es
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
6
externals/cpp-jwt/tests/certs/ec_certs/ec384_priv.pem
vendored
Executable file
6
externals/cpp-jwt/tests/certs/ec_certs/ec384_priv.pem
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MIGkAgEBBDBeLCgapjZmvTatMHaYX3A02+0Ys3Tr8kda+E9DFnmCSiCOEig519fT
|
||||
13edeU8YdDugBwYFK4EEACKhZANiAASibEL3JxzwCRdLBZCm7WQ3kWaDL+wP8omo
|
||||
3e2VJmZQRnfDdzopgl8r3s8w5JlBpR17J0Gir8g6CVBA6PzMuq5urkilppSINDnR
|
||||
4mDv0+9e4uJVQf3xwEv+jywNUH+wbPM=
|
||||
-----END EC PRIVATE KEY-----
|
5
externals/cpp-jwt/tests/certs/ec_certs/ec384_pub.pem
vendored
Executable file
5
externals/cpp-jwt/tests/certs/ec_certs/ec384_pub.pem
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEomxC9ycc8AkXSwWQpu1kN5Fmgy/sD/KJ
|
||||
qN3tlSZmUEZ3w3c6KYJfK97PMOSZQaUdeydBoq/IOglQQOj8zLqubq5IpaaUiDQ5
|
||||
0eJg79PvXuLiVUH98cBL/o8sDVB/sGzz
|
||||
-----END PUBLIC KEY-----
|
28
externals/cpp-jwt/tests/certs/rsa_certs/rsa256_priv.pem
vendored
Executable file
28
externals/cpp-jwt/tests/certs/rsa_certs/rsa256_priv.pem
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDC2kwAziXUf33m
|
||||
iqWp0yG6o259+nj7hpQLC4UT0Hmz0wmvreDJ/yNbSgOvsxvVdvzL2IaRZ+Gi5mo0
|
||||
lswWvL6IGz7PZO0kXTq9sdBnNqMOx27HddV9e/2/p0MgibJTbgywY2Sk23QYhJpq
|
||||
Kq/nU0xlBfSaI5ddZ2RC9ZNkVeGawUKYksTruhAVJqviHN8BoK6VowP5vcxyyOWH
|
||||
TK9KruDqzCIhqwRTeo0spokBkTN/LCuhVivcHAzUiJVtB4qAiTI9L/zkzhjpKz9P
|
||||
45aLU54rj011gG8U/6E1USh5nMnPkr+d3oLfkhfS3Zs3kJVdyFQWZpQxiTaI92Fd
|
||||
2wLvbS0HAgMBAAECggEAD8dTnkETSSjlzhRuI9loAtAXM3Zj86JLPLW7GgaoxEoT
|
||||
n7lJ2bGicFMHB2ROnbOb9vnas82gtOtJsGaBslmoaCckp/C5T1eJWTEb+i+vdpPp
|
||||
wZcmKZovyyRFSE4+NYlU17fEv6DRvuaGBpDcW7QgHJIl45F8QWEM+msee2KE+V4G
|
||||
z/9vAQ+sOlvsb4mJP1tJIBx9Lb5loVREwCRy2Ha9tnWdDNar8EYkOn8si4snPT+E
|
||||
3ZCy8mlcZyUkZeiS/HdtydxZfoiwrSRYamd1diQpPhWCeRteQ802a7ds0Y2YzgfF
|
||||
UaYjNuRQm7zA//hwbXS7ELPyNMU15N00bajlG0tUOQKBgQDnLy01l20OneW6A2cI
|
||||
DIDyYhy5O7uulsaEtJReUlcjEDMkin8b767q2VZHb//3ZH+ipnRYByUUyYUhdOs2
|
||||
DYRGGeAebnH8wpTT4FCYxUsIUpDfB7RwfdBONgaKewTJz/FPswy1Ye0b5H2c6vVi
|
||||
m2FZ33HQcoZ3wvFFqyGVnMzpOwKBgQDXxL95yoxUGKa8vMzcE3Cn01szh0dFq0sq
|
||||
cFpM+HWLVr84CItuG9H6L0KaStEEIOiJsxOVpcXfFFhsJvOGhMA4DQTwH4WuXmXp
|
||||
1PoVMDlV65PYqvhzwL4+QhvZO2bsrEunITXOmU7CI6kilnAN3LuP4HbqZgoX9lqP
|
||||
I31VYzLupQKBgGEYck9w0s/xxxtR9ILv5XRnepLdoJzaHHR991aKFKjYU/KD7JDK
|
||||
INfoAhGs23+HCQhCCtkx3wQVA0Ii/erM0II0ueluD5fODX3TV2ZibnoHW2sgrEsW
|
||||
vFcs36BnvIIaQMptc+f2QgSV+Z/fGsKYadG6Q+39O7au/HB7SHayzWkjAoGBAMgt
|
||||
Fzslp9TpXd9iBWjzfCOnGUiP65Z+GWkQ/SXFqD+SRir0+m43zzGdoNvGJ23+Hd6K
|
||||
TdQbDJ0uoe4MoQeepzoZEgi4JeykVUZ/uVfo+nh06yArVf8FxTm7WVzLGGzgV/uA
|
||||
+wtl/cRtEyAsk1649yW/KHPEIP8kJdYAJeoO8xSlAoGAERMrkFR7KGYZG1eFNRdV
|
||||
mJMq+Ibxyw8ks/CbiI+n3yUyk1U8962ol2Q0T4qjBmb26L5rrhNQhneM4e8mo9FX
|
||||
LlQapYkPvkdrqW0Bp72A/UNAvcGTmN7z5OCJGMUutx2hmEAlrYmpLKS8pM/p9zpK
|
||||
tEOtzsP5GMDYVlEp1jYSjzQ=
|
||||
-----END PRIVATE KEY-----
|
9
externals/cpp-jwt/tests/certs/rsa_certs/rsa256_pub.pem
vendored
Executable file
9
externals/cpp-jwt/tests/certs/rsa_certs/rsa256_pub.pem
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwtpMAM4l1H995oqlqdMh
|
||||
uqNuffp4+4aUCwuFE9B5s9MJr63gyf8jW0oDr7Mb1Xb8y9iGkWfhouZqNJbMFry+
|
||||
iBs+z2TtJF06vbHQZzajDsdux3XVfXv9v6dDIImyU24MsGNkpNt0GISaaiqv51NM
|
||||
ZQX0miOXXWdkQvWTZFXhmsFCmJLE67oQFSar4hzfAaCulaMD+b3Mcsjlh0yvSq7g
|
||||
6swiIasEU3qNLKaJAZEzfywroVYr3BwM1IiVbQeKgIkyPS/85M4Y6Ss/T+OWi1Oe
|
||||
K49NdYBvFP+hNVEoeZzJz5K/nd6C35IX0t2bN5CVXchUFmaUMYk2iPdhXdsC720t
|
||||
BwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
52
externals/cpp-jwt/tests/certs/rsa_certs/rsa384_priv.pem
vendored
Executable file
52
externals/cpp-jwt/tests/certs/rsa_certs/rsa384_priv.pem
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJQAIBADANBgkqhkiG9w0BAQEFAASCCSowggkmAgEAAoICAQDJuL/eC5zvQ0ug
|
||||
Z5wB3ICjR0lgtFcJgV3HshqrbRERdvlKzKpKMZX8oSvyx3IWGv89qwpvVdtXsbz+
|
||||
B23FT5KXl0Yj2HybKYhDtXNvISHBCqPN3IIqjPaV68o+COxMM33chCI19I59zipS
|
||||
7Hm+JZBo9a3dvOm85lcdwxRvMTP+NqEpk9T+Eyr83cOugTrEVgH3V9vvioc4LlEY
|
||||
w+OyRRgo6MK2P6/6xmrOe5yR/bHRravlf76CyoZlPx0dpf2ybKukFtX1j+DVVn4I
|
||||
7xcV1GIda2H3wWeVsR4eytduGj0ITYYQAJa9FECkyfW5KmCGkQ1uR5+ltgIg3u2r
|
||||
pfiUq9JhBkBGIuQPUQsdyZYJf5ykiV/GKGsqlWdFHiIsk2XfdW04Eg9oy+2J+iOQ
|
||||
vGyLd23ImRwQVAj+Rdspbwp3DkV35Q5yxB/w8qTuT0uAVofwZlEWFvBPRsuOPLRQ
|
||||
hXk0MdxKjPJ1Xa5CH443oGzKAJK8wTxXiW73PvhGrdPt4/bmkL5DSY37WftAZAvj
|
||||
MqyGQo2HpHH5AI/SFUY2iwvoygvOx6W5qlOqcetAQdNsbUmb5Yv9x6ze2Efs/JLJ
|
||||
YolxRD+JYEPQUWTJrQpO9N9a8GD9Y92oEcshCHqJ7/uU4XITnoVtFi5FTRwXz43K
|
||||
QD/oc3bjukW3DU9KBDrwOq2/1tkwVQIDAQABAoICACMGO/IezBHS+meQdcrw8Tjo
|
||||
YLo0tcQFvTW2G+FV35fLs38kSBD3yRYDGfFeZdWmvFiFwRsRqjLwvmLRAWM37Lj7
|
||||
YAdLSF9cd7dh4vgRpZ2x7j0JI2Sl8w6W0ReyTuzwJ9NI8fOyUadQS5L4Ui8MsKU4
|
||||
uwZ8DY1p5Qha3cpsnZ1u+M6SR3IR++3Jx3ceIwkB8fdzPtG5mL7Nc/E72eYTDx3T
|
||||
RDOGnVSKbPMLDWVfyicg427GnlpxNaKQscp7DrCTI74q5N1tLNl92gZNFRIKPTrk
|
||||
cS8mWojoJtWr3HnWfnBZnYRbxdBwmsTB+DM9Q2M5/j3+m56XGomAi325JI8TwkQd
|
||||
W1I7ArELEbN96LPFQb3ynjyvwf2OWw7CU4f73yYlX5aoHJHa9kf0Q0OdASy/hKeO
|
||||
KAI7d8IfV/OXHAEF6FSm30sCwA4di7GRVf4LIlS1oxmr71eN830c8Lm1bB/9sNh+
|
||||
4H1ztyaFx7jV9zvuVt4X6zMRUOzs42963KtvK5Go05aBu3wVUpTZkHN93H77ygi3
|
||||
XTfni+sSuJP8anfdgwvgxH6kIEyrFbMw5ZlYkTDjF9hG5573ucbLgMoXXRXUWpq6
|
||||
62doFjvlr00eTTKPdb4pbqlsWw1lqgJ86b2Nl6QHlr3Mjbsee1CKlrG7iekQwYwM
|
||||
lbG7xUSMwcTWynxM0ebhAoIBAQDwUVULbMcFLz6jeLyeK7c1jmdwm2aRP7mGlqDn
|
||||
rutZ8/lXOu+6KHQEBbi3SAcJAJxLy6v+lDubvYJ/wUDrRrxLZ2N61OrzFt/WNDRp
|
||||
K6qYm1EEfUNPaoplPo4dj0Q6Epmk5DMU+T+uxwcdUf2rw8O8dVrPzl3BFtvUPwSp
|
||||
EMNy9uqnJbDAxaSCd3HQjqpX0ZNwrofMK0khkdCxOXWTYgR2F5rCFmtdiU8QjVhB
|
||||
tHjiXHF4FUf4/7V0SGISdBDCP13OV8+x6pjmR/zVJPhhlk+ixl5DgXI678jGwmoG
|
||||
Y7bum46SZhd9tuFMyRIlJ15LsFq2pCdtQGLXSulkI/a8NtXZAoIBAQDW4qUWXYV+
|
||||
wRB+rt3saI2o2sRifErnaUfX1i+C9/Lbsu2cOmkERKvlQs9lwIVn2R1j7xTFig1m
|
||||
Madn4dUEQWFs4jVfrTp4uy8jiucz4cbfdwRhJUi5x5R9z44eQq5Yu85LZ8T3xQuC
|
||||
NU0i1gC83UV+JSmS3TmiOn/g49kxYeZ0NXbi7j8EPOqv2noD62aEo8e3LF1pfbIh
|
||||
czqcU3Hi+WaGAtn7rbGmstZW5PlIKjfQ+icq2xuCmQn9sT/H+Bpwwfwn40Qay23+
|
||||
gOy8e+9PdEYmIa941NA9naYqaRlpnnHxNOmTssTDno8KfbWl+0G4fRuD9oy8Lh9Z
|
||||
+Hju5VOAlrTdAoIBABY5n2DgHYPYO7XIm8ERD++PDPf4F0NFnnXZBmaG4dM+4gd0
|
||||
NumDhj88/DlPGv91I/9KhcyUjvK3UxNXnxZjQ1TB6gxZFqWGrwrTZyl21V8pthNx
|
||||
NkFo/AWjBGetcUThpX3/cM32wzH5zCmlBI3XHAoY3F4tmrQZ1hjJ/zdXioveVBND
|
||||
RBZ/8Nf0Df2YxB49DqK0MXDra+cD4kYRp1MLFJiLVE+w3RsYcMx6Ffh1pVxh6kiN
|
||||
x0s68uAfNZq5Szd7vsQvkNDGfn+FltdrhOEZkqHeMKeTmCnlNS9UmZOfszJcBpJ5
|
||||
iKCiwjFkwx3Whzz+wVT014SeGMYKco1FWjNL6vkCgf804ZG+70Tq7JgilOYIR7KU
|
||||
20F4+x1z1XTYqN0IXfxmFKJkz/sIEd47jTV81OP/qm6RKUTzWAX0IEQSTIEfivdu
|
||||
1DxOT1MUYvw2wvgizG0kkSWCwqojDfp8+5b922sMaytZYzAVyWgLoxJYgFGuKMXx
|
||||
RTP18Hs+cScHMQtCG9Waw41+SyM258bZf+qHDGcuPR/o9AII8+XiVXkW/3IHaVjR
|
||||
oeIDDbuqSlh1CeRO3hTeWLFK2qDqgr7yr6wCigv3s8VaC5O3BFkNSKz5tYYvB247
|
||||
9A46riSRBTrfNP4L//IKafsRXe0ONvb8nfMV5b9Gp4Md9o6rwK32di9MmyLxgiUC
|
||||
ggEBAM/lJVgsyIlU1ug/DmeGZQmth0JQdkgVsk7vxM673y/0syLxM3Wk/1BbySQ/
|
||||
lcIckFN43kAZze9bHOPYtiLvvqb3EZpK8il133LagzddzsXvKiM8xu9GElGTScaG
|
||||
oNmyVk5vL8s6cKHexB0Ce0y1Ri23KywDY6RUgqclYyVpyBRZYrAm4E24voRrWIOu
|
||||
cYb0yjOeMJV4pmEzm8eN+Pqt6Qc60Zl+izvlDIa8qMq7ksFVckB0RR34iqka8y0A
|
||||
hK4V1zZvQ9ZENlO2uUj/WR+/C4NWWRYtfsKYU84XuSy3IuUfwaBHHychmyna1eni
|
||||
nfictCHvTZXlDWYlp5Uf8IDXrd4=
|
||||
-----END PRIVATE KEY-----
|
14
externals/cpp-jwt/tests/certs/rsa_certs/rsa384_pub.pem
vendored
Executable file
14
externals/cpp-jwt/tests/certs/rsa_certs/rsa384_pub.pem
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAybi/3guc70NLoGecAdyA
|
||||
o0dJYLRXCYFdx7Iaq20REXb5SsyqSjGV/KEr8sdyFhr/PasKb1XbV7G8/gdtxU+S
|
||||
l5dGI9h8mymIQ7VzbyEhwQqjzdyCKoz2levKPgjsTDN93IQiNfSOfc4qUux5viWQ
|
||||
aPWt3bzpvOZXHcMUbzEz/jahKZPU/hMq/N3DroE6xFYB91fb74qHOC5RGMPjskUY
|
||||
KOjCtj+v+sZqznuckf2x0a2r5X++gsqGZT8dHaX9smyrpBbV9Y/g1VZ+CO8XFdRi
|
||||
HWth98FnlbEeHsrXbho9CE2GEACWvRRApMn1uSpghpENbkefpbYCIN7tq6X4lKvS
|
||||
YQZARiLkD1ELHcmWCX+cpIlfxihrKpVnRR4iLJNl33VtOBIPaMvtifojkLxsi3dt
|
||||
yJkcEFQI/kXbKW8Kdw5Fd+UOcsQf8PKk7k9LgFaH8GZRFhbwT0bLjjy0UIV5NDHc
|
||||
SozydV2uQh+ON6BsygCSvME8V4lu9z74Rq3T7eP25pC+Q0mN+1n7QGQL4zKshkKN
|
||||
h6Rx+QCP0hVGNosL6MoLzseluapTqnHrQEHTbG1Jm+WL/ces3thH7PySyWKJcUQ/
|
||||
iWBD0FFkya0KTvTfWvBg/WPdqBHLIQh6ie/7lOFyE56FbRYuRU0cF8+NykA/6HN2
|
||||
47pFtw1PSgQ68Dqtv9bZMFUCAwEAAQ==
|
||||
-----END PUBLIC KEY-----
|
100
externals/cpp-jwt/tests/certs/rsa_certs/rsa512_priv.pem
vendored
Executable file
100
externals/cpp-jwt/tests/certs/rsa_certs/rsa512_priv.pem
vendored
Executable file
@@ -0,0 +1,100 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIISQwIBADANBgkqhkiG9w0BAQEFAASCEi0wghIpAgEAAoIEAQCzRcxyS9jTopbz
|
||||
Q38XPmsElQ3cGWxShWJliOlnLlRuE0C33q12egwxcnDq93378NbAESCmrtxFSxar
|
||||
WpGSpIvPx3FNDw4azFq4VVNZFNfdkxD9i1kkMZrX6yeTGGwvGe+lfH8o+BhTVZOo
|
||||
HjoZX6K3Cxnr1LSer5w0yMgWLPpMkw1U3AjnIR1hSKV3FvRiYa79kFAyKFyth6wA
|
||||
lJB7M27XRi+KhIhBQBIeN9VwUwwu1lFi+LuJ0h96NvuJbas+U7uwXhk2FNpKizMH
|
||||
TcG+c1mOKQ5EGcPPvUCAwqpb8i2Wr+4y4xvReU8KItmBLzegt9K8xBCyl46SzfK/
|
||||
nDce/6wQVetJnLK3dI/Ee5zeCCBKotx/MJXg8b+nYfvLlDqL1Uc9oDz1lBeUpZAL
|
||||
jqyuKk862RICTIlT00n9aRg2edfNCIoDeR83aYsI7Om/rZIahSsSyzJxO5UtQpPM
|
||||
zvotphD+UZultKtMa9kSabc4mOMWvmvYlI+bMbD7l05Skn6Lev366b6JQoqk6RMh
|
||||
JjIJdjXvD3J/XdbgaazuXlclT6lEiUGVvcfZAU3a73CnuYRdg4nMY0akDegcUpSa
|
||||
fjSOXPnT102kZobhJfMkbxSS76ZauNZayeH1VxlCGAspWhsmyaZIiSpykkKK3KXb
|
||||
UsCTsOhQHQZ4wIU6PM+FnSdwPtFUHCrvrYDqtyjC65jwvBuun1q42DPOEcev5zTV
|
||||
oW+pltRPihrFIUifKuhyzIKolhAQbewMro0zE0g+z00jIL4hY9uq/ERI4Ykrqsua
|
||||
HZYJoPSKsK9uhbnLF/ERoK67dZZQUUR5xHQq8dFCKD90VvYnKjh/KnOp1JG0C7RH
|
||||
v+o6fqkuwQ71ex5CHu5HN1qDBv0KN0EHycoHnNVDv2CzAENjb6AOXVSmHLC1P4hK
|
||||
viQtSbe284VBmOPVI1pl0tMNBvE70ZaPBqKMhBsB0xTR/2QTsUchHe88Qwt/A2Cm
|
||||
jqETK6RMF8FNPVyrx4dC3RZsMsNgVy4DV8Vr1catk+aYYKhXwAUpBpQ1Fwht9Faf
|
||||
KQ+z2gkqLrSApuGghK0ir8ORX8Hw49MxFNsWtqdIkNo7Y/o7QDljtF7OGOerJvSi
|
||||
ImwqDvj79NyAv+1kH5gHcAbeB0SVWe71xa5HYWljfkvVYCT3MDjpnh3FDIvuc2lA
|
||||
ODmlfhDyxcrbHc6/VWZjLVOZTGm/V4tMzG2zTJdgNAUZwNLhW4N9lk2Qhcw4wSjj
|
||||
Ll9DDXU45wSWm/JUxSRiXQuAm8iptQLMK6WSuu4oo890eu0m+EibKyBPjqVuMo8Y
|
||||
NPgP/qoi3hSpX0H3r081up+oU5GeaBofegXfHFsBB9xqx9TEI/EKFik4+zbmV20A
|
||||
BIACoM5HAgMBAAECggQAazXNy3iyhfZRIc/2vFbWt1nQfRUzI7KjIqebNdqOIXog
|
||||
FRX1VMouao/PGaXC0R25wAk+JpCiKEp8lyNFtZX0CuFyT6w2Oi6F/oEApGCDq/3c
|
||||
hlSEjdGgkYoPE7fiUtTG7YejoEOmgIfIEx1oj24TKDZaXR/KmK/a0fJVPnXNhmfW
|
||||
7C3eoSK7qEdCtRKkOgXDGd7pJuXebuSZJ4uxUAx1OAbAPa1+ss73Rt0LJu5zdbsz
|
||||
1uV7ejOQIY2qJgjRBSgcMaBEoYQc+8F9VdvZhuUC5LKG1pE1+hFq9tXz/aK6QsiZ
|
||||
whLxuvc6Hoyy2L/9G39zZvI2LifW2tKRXqe0izRJmUdYu6AbfP0XUWC/ckUX0qrN
|
||||
BL9wkqLgg+BkLd5KmP+GaENg0VisNXhBybeca1fgJAhW7csJwXi1Yfgsw79gID0A
|
||||
FI2l7oSO4lqUe834dyW2mbmtQ+xnDTconq4VDaGnvf/d/l4qpzxEB+/y48UC4cIl
|
||||
StOlgiFYf02ASH9VcGKwaxLIoNuLgI3mo8ds2x23qWzqg2MCMxjfk3oV0blvOA6B
|
||||
i2SAlLVj8w+IprWahDY6/WFNiKTMb8uvFSluksjlmxvCUhQCi7kfTGWlvy3UpaKu
|
||||
hoL/P7LD5zPr0OITJMIpUG2/Vd9ELjlAcwZtJqYAeJCzIxm3Uxm03WobgNQAabSh
|
||||
rQCpUF+sZEqOPfQIa4bpRk+IzboCzdBBuQw9S8H1+yI/R718EvbmS3QhKAG6C6BR
|
||||
bafo+SLTfMGKARMACqq68w2FNYLblodBYGOdSf7LeSc8g6uA9UPncMfg06HOmkw/
|
||||
lIaOVseJG006u9LsUE6obCzNKGy5vtz0gCawbuc+S5ZaR3tE18Nu3ukNtZVv+L+U
|
||||
ThAlVn/QDm4uMUmNy6Uxn7rta98auPE18InaVKJEDAFJ/pljX/XI6M0Nnz+lJfrl
|
||||
YTqPWjQtazaoohJt+OaVeK8MLOzRfu1FLllv8w2I1VXZR2rEW0UiwOC7+q5PgZE2
|
||||
qo7pHFnG/XfnP64vxa3I4Bv+a6zAbga1fgBbvTooRgqf6EExklZyfipMCtpnbG4c
|
||||
Ght//zwUOvhUn6POHCgGO3OYhXjr8ArUhg2oQwGyUkGlzQGLGeopocFCbDMb7i+k
|
||||
GMhuigwKLjBMUF6U3TdC532wse0DPyDHBCLyxD4dPiPvFspgcNaw7x6sVWB9vN2J
|
||||
xXUJVGtnIrHAZQ2evGDtIeJnyFhmQ3Fa8RF+519xHYyX6Vu1KGEI1yT+ALSkUvYy
|
||||
cUip4zyT70+GdknExutxIWtEMVpfXzxIJVt9S6gm8pUZ73OHVByUV92FgQCWPXnk
|
||||
jVPRBU/nnmav05YqCikvPx5SOVV/r64h5eNklhelmQKCAgEA586CvRRJQLPsOzFO
|
||||
jH6k0aCQOdvi5MwuLkdaBnAKOZRGiXtVFV/QwnXELmIiDCcPCLXagZ5R9XKwQp8H
|
||||
nzgvbGii2EjOFZ0GQC9FtOXX+E5vpFrg8eYRrjCAHB2yZ+B/1QrLOYbJhZZfaSZ5
|
||||
8WC0jrrJqa1zvauBjy2EdtWykIbCV29UWdzIm0kH3Tgi0f3chgt7voOMHJ87jknE
|
||||
4jGLYbRM4Gje92Gi3WWymTSwN3ZuqWZvWdjPTuz2dk2T6sGusyN4cXTjmRy8yDMg
|
||||
xifJkhyxshW1ZHIK/6RacDi0w562rhz9kRRvbwtK9copeNaudQpvUJL+aPtVWc4f
|
||||
KNNatpaFhhsHo1jTOdMvx2Mn7AxDreUiTuUO2gDEJu7/LR7MhSdaXBVUUQVFNZXw
|
||||
Hm0tVM1OH7rylU+OBNUOjb14zaClRtZ/97GoQIgRXQRqJ4K6nXFwGXycyYc4bZt2
|
||||
+tS4HVjUPViT4hZr4JXKeUSfY/rzE3i9QjLhguKaRXJexh8TxGMKg1DxMUv8kEYS
|
||||
4Dt5V1ZHQnGwN/lRR91B8OoreelOQTX4YIfi7ZWBaeNqBK4YRTQ5k2pHIi3THpFK
|
||||
hyQQGXXuAcwUcxhdOOWoVmlM37Qmfty/P+Jac8z7Gos4aXDRS0NXfkLLCFGWzhoQ
|
||||
Z0jh/p34xiF3cO0J94Wu/xHJPsMCggIBAMX7qnjl9kPyqA8YZUFHe/8mFYSCbPX5
|
||||
/ufVt55DSwA9wscairG2fETKO2xeu4m0zO9iShOvzEydTs2SDMtl1tSHf4h43Hdb
|
||||
Lg1ekfPMDmU76pPnsPO0bCH+c+1kPvhaXLhAUPBNBjhU3SuaMH5vRGBJIpCrAzu4
|
||||
tCKnAP56QZoJ702CAAtvbU/ZUGl9lV16mcgE0BVjQVVqs1srno0WTtV6Yu4J4oRO
|
||||
z8KI7Bfbvq6UhaErNpb0m1Bb5IExdbNjh43Eot/F7+WooOKSh9kzpy8KzrgrmI0k
|
||||
CRR6bibh91oY66SDJMmwsNQi4ajKrNUmP0qlQHRoXw4Q1Ot9kea/DCarm0ou6jwh
|
||||
NlSyl51PNrZMgN16SJR1sAsoeR1tSmQdQViu8icYjvIraWDixSXyi986c+KJ5QBR
|
||||
o1GMxxDuGVahSTjo1cj1Ps/sqq+JRqHIkwlt8J4Oujlwzxjy9pr/omZw49iF1GGu
|
||||
CwIAKJZMp526TkAYoVzCwCELv+ZGdVRfpo2NEqL9J8fv/E9+FJbvbvsxTILjhkkt
|
||||
2XTGlqzt1Mcb5/iXmzme6Wd0S22i2MG+u5FleU3C2qAenOU7/l1YgSbMe3sJ6SQD
|
||||
fvpCLP0nZMv2cM2s0Zr5msvfqqRaDbMshgcY2hVgILhxIF+4FPwZyff1lDKpNTcr
|
||||
G8tEH/dTe8ItAoICAF6UkBt9z3Wq89QjBh2k/rLZhH9XDHi2JpGTY1QFGubrbOxj
|
||||
eg/CjHcLfgQ+3g1/Uk8HhCQm6OHw7aIBKSb50b+14dvFuPBwpUBDCXoJ3djeiAbT
|
||||
XbzVVplwCJVwOH7RxtayFMFgEZGEDWHl5RNrlcA2zlmBABx/gdldhRLHlpgJo/nw
|
||||
3sXbo65YWfEVGn/7yKKYxOCy49Q51B72UnLILEqtOkDGCVN+bulOuVRxfwTiOby8
|
||||
oupR4CQf41/Zv2SlqhZFfrssKkEqzIwS8Ghpi4EmXAqBeQWG0p4D/TKUsIywkXDx
|
||||
OzSa1ezE+szWs50uWvg+TbTehRdolSaTR3ts4TJmsAxLsw4fC/AoDvKXro5NYr/t
|
||||
IdZ291xTu7T3Bv7t9hzONbwkp8Z3FAoNJ3ACs+BJ9HpV2Oy7DQNDuzByAnxD86u3
|
||||
kXcK8c+CtTLyvi1o1aOvyUFc6sv/dDKkoCMv7/9pYw+0uIIjC9kSxQ49xZsRpWRo
|
||||
ezAren/g3XlAdRL5UyNqFbwGpqKqkl57ePAs1BGijmi54mC0RUnBKUqXAS4410kc
|
||||
MD+SsjCmM6t0sqk+L4DtEiDn2CZF9EIgnfwN5tO8nmP1VNKxOjgg3FKFnGwaISrZ
|
||||
/t6eCLH/DOWDsHy1H3BKBcTqk9TNFW76i37Y6fztj7enqAhXbx2jWgeQxj/pAoIC
|
||||
AQDBKJxVf+cYu/KDZ8XCPsAXW0y7D5THF7U+8yBGZFkUTy1tm9OdNvFfG/+F55cI
|
||||
70DSfQ7Qzj+AsClmHwwklaNXjys6NtDCEk+H87BqL7gLxL1EuFPIMUsej2cDQT6+
|
||||
h0rW6MkO6dcbtpBiLfkKIfyQBEqY4oAxEC+Pb2hk31qJsw+qix8ICRqZQOhXQ5Mq
|
||||
tKa8oxVxCHmBoKyEUrZJ6G3ZkaJbo4FAnLPOlE/jpx0OrxEBAWwtM1EkwcLa2SqA
|
||||
bqaeBi7yK+e2JSNyaovnuaFvIBg3TzFy4qmJNTmq7eOqH44n31tQ+/ZJwg5v4+1j
|
||||
uAEgDsIn0HyM+JcDemuSuOpeACdt5P/a0nxzfhq1+8bhbRp8+wU88uVivYYM08g0
|
||||
jOZoY6cVxbwRQZF6WUUHlPAqRpkxeF/YQ84XjkXZmrNV9d2+jEun2L4Dll+hC0nC
|
||||
JjJujLipPK0rxYgIS2OWLbqAP7vMUCW5d1h+BzGSEg+mr1IQ7vbfzZItq4z6Wdu3
|
||||
CesxR2XbZyocw2NjGxtzdv7MTHjdaqZlVzpF2ErBRPjHmc5kl2V2fjgyGyBMQwk/
|
||||
XZsaa+pBl849UiC49iNhZyv6cp42mKDB5jdIarAB/SE2baX4xJdroAMKzZlq6AFd
|
||||
wh6xZem/2R2TVavEN5EhtPd72DlShAvLW1+unTSi1Ox1sQKCAgEAg9n+wQtZ60IW
|
||||
CxAuc4uHUofpCQoIeGrZ9xLnH0tmFRJnJ5ufNxzHj5oWwKSxpm90bDMnWutfirGH
|
||||
h5RQ7y44IbYUV2Pbhz7+gwSjNlhLec37PCWuVyUmkHLma07N2ZspUOT21/uJ4WD1
|
||||
XazuP+gA4sGiVcLs73q21mUqVgXR+s+bCM0tG1ZrwgoYsKg5Dek34HsdlzYpWYMs
|
||||
qXgKmwJ691ZXlRR/HOLOKsfNfoprW9QQ2kVGfXO/0lKK5p9f7CceOPguLqHn0zk7
|
||||
CB09OVjCv6eTUL8UzswQMo67nO210Q7JKuXAWxGYApQB4HubNe5Ic+pdiHz8Iwbm
|
||||
fcTYyOGs4RtQZY3qzB8z9p66y62rzasPnUXSYs3w4nrKtfphC8b5voJB+QDJGe1y
|
||||
WqL95dHYJxdGHa4Kcjc8jQtOCty8pItvGdrVkmuzr0P5LziY1jJz/sPj5b4l2jJB
|
||||
56g1UnKzBmaxgPIQrIdqlDiuEBOerdYKVLiq7np2JC5rKfoYQhdTCj12Nwm8cpOP
|
||||
3jymz1XYEUqYc46oggBPor09edLwhOqr+30Bv8QCAsvwaBYG0Ru2P5l5mgCOmf++
|
||||
dW50xYg+MPHJr9WK38x65kAi+vG9yHeoS++bm26CbVkSGrwKPZI34Fku6i/FUayW
|
||||
EtoiU3WKndSOrpIVOqOQTQU54puQoOE=
|
||||
-----END PRIVATE KEY-----
|
25
externals/cpp-jwt/tests/certs/rsa_certs/rsa512_pub.pem
vendored
Executable file
25
externals/cpp-jwt/tests/certs/rsa_certs/rsa512_pub.pem
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEAs0XMckvY06KW80N/Fz5r
|
||||
BJUN3BlsUoViZYjpZy5UbhNAt96tdnoMMXJw6vd9+/DWwBEgpq7cRUsWq1qRkqSL
|
||||
z8dxTQ8OGsxauFVTWRTX3ZMQ/YtZJDGa1+snkxhsLxnvpXx/KPgYU1WTqB46GV+i
|
||||
twsZ69S0nq+cNMjIFiz6TJMNVNwI5yEdYUildxb0YmGu/ZBQMihcrYesAJSQezNu
|
||||
10YvioSIQUASHjfVcFMMLtZRYvi7idIfejb7iW2rPlO7sF4ZNhTaSoszB03BvnNZ
|
||||
jikORBnDz71AgMKqW/Itlq/uMuMb0XlPCiLZgS83oLfSvMQQspeOks3yv5w3Hv+s
|
||||
EFXrSZyyt3SPxHuc3gggSqLcfzCV4PG/p2H7y5Q6i9VHPaA89ZQXlKWQC46sripP
|
||||
OtkSAkyJU9NJ/WkYNnnXzQiKA3kfN2mLCOzpv62SGoUrEssycTuVLUKTzM76LaYQ
|
||||
/lGbpbSrTGvZEmm3OJjjFr5r2JSPmzGw+5dOUpJ+i3r9+um+iUKKpOkTISYyCXY1
|
||||
7w9yf13W4Gms7l5XJU+pRIlBlb3H2QFN2u9wp7mEXYOJzGNGpA3oHFKUmn40jlz5
|
||||
09dNpGaG4SXzJG8Uku+mWrjWWsnh9VcZQhgLKVobJsmmSIkqcpJCityl21LAk7Do
|
||||
UB0GeMCFOjzPhZ0ncD7RVBwq762A6rcowuuY8Lwbrp9auNgzzhHHr+c01aFvqZbU
|
||||
T4oaxSFInyrocsyCqJYQEG3sDK6NMxNIPs9NIyC+IWPbqvxESOGJK6rLmh2WCaD0
|
||||
irCvboW5yxfxEaCuu3WWUFFEecR0KvHRQig/dFb2Jyo4fypzqdSRtAu0R7/qOn6p
|
||||
LsEO9XseQh7uRzdagwb9CjdBB8nKB5zVQ79gswBDY2+gDl1UphywtT+ISr4kLUm3
|
||||
tvOFQZjj1SNaZdLTDQbxO9GWjwaijIQbAdMU0f9kE7FHIR3vPEMLfwNgpo6hEyuk
|
||||
TBfBTT1cq8eHQt0WbDLDYFcuA1fFa9XGrZPmmGCoV8AFKQaUNRcIbfRWnykPs9oJ
|
||||
Ki60gKbhoIStIq/DkV/B8OPTMRTbFranSJDaO2P6O0A5Y7Rezhjnqyb0oiJsKg74
|
||||
+/TcgL/tZB+YB3AG3gdElVnu9cWuR2FpY35L1WAk9zA46Z4dxQyL7nNpQDg5pX4Q
|
||||
8sXK2x3Ov1VmYy1TmUxpv1eLTMxts0yXYDQFGcDS4VuDfZZNkIXMOMEo4y5fQw11
|
||||
OOcElpvyVMUkYl0LgJvIqbUCzCulkrruKKPPdHrtJvhImysgT46lbjKPGDT4D/6q
|
||||
It4UqV9B969PNbqfqFORnmgaH3oF3xxbAQfcasfUxCPxChYpOPs25ldtAASAAqDO
|
||||
RwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
1
externals/cpp-jwt/tests/compile.txt
vendored
Executable file
1
externals/cpp-jwt/tests/compile.txt
vendored
Executable file
@@ -0,0 +1 @@
|
||||
g++ -std=c++14 -I /usr/local/Cellar/openssl/1.0.2j/include/ -I /Users/amuralid/dev_test/cpp-jwt/include/ -o test_jwt_encode test_jwt_encode.cc -L /usr/local/Cellar//openssl/1.0.2j/lib/ -lssl -lcrypto -lgtest
|
188
externals/cpp-jwt/tests/test_jwt_decode.cc
vendored
Executable file
188
externals/cpp-jwt/tests/test_jwt_decode.cc
vendored
Executable file
@@ -0,0 +1,188 @@
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
TEST (DecodeTest, InvalidFinalDotForNoneAlg)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
const char* inv_enc_str =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(inv_enc_str, algorithms({"none", "HS256"}), ec);
|
||||
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::SignatureFormatError));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeNoneAlgSign)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjo0NTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none"}), ec, verify(true));
|
||||
EXPECT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::AlgorithmErrc::NoneAlgorithmUsed));
|
||||
|
||||
std::cout << obj.payload() << std::endl;
|
||||
|
||||
EXPECT_FALSE (obj.has_claim("iss"));
|
||||
EXPECT_FALSE (obj.has_claim("ISS"));
|
||||
|
||||
EXPECT_TRUE (obj.has_claim("aud"));
|
||||
EXPECT_TRUE (obj.has_claim("exp"));
|
||||
|
||||
EXPECT_EQ (obj.payload().get_claim_value<uint64_t>("exp"), static_cast<uint64_t>(4513863371));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeWrongAlgo)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret(""), verify(true));
|
||||
EXPECT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::InvalidAlgorithm));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeInvalidHeader)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"ehbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret(""), verify(true));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::JsonParseError));
|
||||
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeEmptyHeader)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
".eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret(""), verify(true));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::JsonParseError));
|
||||
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeInvalidPayload)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyfhuWcikiJyaWZ0LmlvIiwiZXhwIsexNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none"}), ec, verify(true));
|
||||
ASSERT_TRUE (ec);
|
||||
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::JsonParseError));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeHS256)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJpYXQiOjE1MTM4NjIzNzEsImlkIjoiYS1iLWMtZC1lLWYtMS0yLTMiLCJpc3MiOiJhcnVuLm11cmFsaWRoYXJhbiIsInN1YiI6ImFkbWluIn0."
|
||||
"jk7bRQKTLvs1RcuvMc2B_rt6WBYPoVPirYi_QRBPiuk";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none", "HS256"}), ec, verify(false), secret("secret"));
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
EXPECT_TRUE (obj.has_claim("iss"));
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value("iss", "arun.muralidharan"));
|
||||
|
||||
//Case sensitive search
|
||||
EXPECT_FALSE (obj.has_claim("IAT"));
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value(jwt::registered_claims::issued_at, 1513862371));
|
||||
|
||||
EXPECT_FALSE (obj.payload().has_claim_with_value(jwt::registered_claims::issued_at, 1513862372));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, SecretKeyNotPassed)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJpYXQiOjE1MTM4NjIzNzEsImlkIjoiYS1iLWMtZC1lLWYtMS0yLTMiLCJpc3MiOiJhcnVuLm11cmFsaWRoYXJhbiIsInN1YiI6ImFkbWluIn0."
|
||||
"jk7bRQKTLvs1RcuvMc2B_rt6WBYPoVPirYi_QRBPiuk";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none", "HS256"}), ec, verify(true));
|
||||
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::KeyNotPresent));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeHS384)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9."
|
||||
"eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ."
|
||||
"cGN4FZCe9Y2c1dA-jP71IXGnYbJRc4OaUTa5m7N7ybF5h6wBwxWQ-pdcxYchjDBL";
|
||||
|
||||
const jwt::string_view key = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none", "HS384"}), ec, verify(false), secret(key));
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
EXPECT_TRUE (obj.has_claim("sub"));
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value("sub", "nothing much"));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, DecodeHS512)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ."
|
||||
"vQ-1JSFN1kPjUI3URP6AFK5z8V7xLhyhw-76QWhQg9Xcy-IgrJ-bCTYLBjgaprrcEWwpSnBQnP3QnIxYK0HEaQ";
|
||||
|
||||
const jwt::string_view key = "00112233445566778899";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none", "HS384", "HS512"}), ec, verify(false), secret(key));
|
||||
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
EXPECT_TRUE (obj.has_claim("sub"));
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value("sub", "nothing much"));
|
||||
}
|
||||
|
||||
TEST (DecodeTest, TypHeaderMiss)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzI1NiJ9."
|
||||
"eyJleHAiOjE1MzM0NjE1NTMsImlhdCI6MTUxMzg2MjM3MSwiaWQiOiJhLWItYy1kLWUtZi0xLTItMyIsImlzcyI6ImFydW4ubXVyYWxpZGhhcmFuIiwic3ViIjoiYWRtaW4ifQ."
|
||||
"pMWBLSWl1p4V958lfe_6ZhvgFMOQv9Eq5mlndVKFKkA";
|
||||
|
||||
std::error_code ec;
|
||||
auto obj = jwt::decode(enc_str, algorithms({"none", "HS256"}), ec, verify(false));
|
||||
std::cout << "Decode header: " << obj.header() << std::endl;
|
||||
|
||||
EXPECT_FALSE (ec);
|
||||
}
|
||||
|
196
externals/cpp-jwt/tests/test_jwt_decode_verifiy.cc
vendored
Executable file
196
externals/cpp-jwt/tests/test_jwt_decode_verifiy.cc
vendored
Executable file
@@ -0,0 +1,196 @@
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
#include "jwt/jwt.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST (DecodeVerify, BeforeExpiryTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() + std::chrono::seconds{10})
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), verify(true));
|
||||
ASSERT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, AfterExpiryTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), verify(true));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::TokenExpired));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, AfterExpiryWithLeeway)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), verify(true), leeway(2));
|
||||
ASSERT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, ValidIssuerTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "test")
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), issuer("arun.muralidharan"));
|
||||
ASSERT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, InvalidIssuerTest_1)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), issuer("arun.muralidharan"));
|
||||
ASSERT_TRUE (ec);
|
||||
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::InvalidIssuer));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, InvalidIssuerTest_2)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim("iss", "arun.muralidharan");
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), issuer("arun.murali"));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::InvalidIssuer));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, NotImmatureSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() - std::chrono::seconds{10});
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"));
|
||||
ASSERT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, ImmatureSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() + std::chrono::seconds{10});
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::ImmatureSignature));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, ImmatureSignatureTestWithLeeway)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() + std::chrono::seconds{10});
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), leeway(10));
|
||||
ASSERT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, InvalidAudienceTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}, {"aud", "www"}})};
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), aud("ww"));
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::InvalidAudience));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, InvalidIATTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}, {"aud", "www"}})};
|
||||
|
||||
obj.add_claim("iat", "what?");
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
std::error_code ec;
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), ec, secret("secret"), validate_iat(true));
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::VerificationErrc::TypeConversionError));
|
||||
}
|
||||
|
||||
TEST (DecodeVerify, InvalidSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::error_code ec;
|
||||
auto dec_obj = jwt::decode("", algorithms({"HS256"}), ec, secret("secret"), validate_iat(true));
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::SignatureFormatError));
|
||||
|
||||
ec.clear();
|
||||
dec_obj = jwt::decode("abcdsdfhbsdhjfbsdj.", algorithms({"HS256"}), ec, secret("secret"), validate_iat(true));
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::DecodeErrc::SignatureFormatError));
|
||||
}
|
||||
|
178
externals/cpp-jwt/tests/test_jwt_decode_verifiy_with_exception.cc
vendored
Executable file
178
externals/cpp-jwt/tests/test_jwt_decode_verifiy_with_exception.cc
vendored
Executable file
@@ -0,0 +1,178 @@
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
#include "jwt/jwt.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST (DecodeVerifyExp, BeforeExpiryTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() + std::chrono::seconds{10})
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), verify(true));
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, AfterExpiryTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), verify(true)),
|
||||
jwt::TokenExpiredError);
|
||||
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, AfterExpiryWithLeeway)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("exp", std::chrono::system_clock::now() - std::chrono::seconds{1})
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), verify(true), leeway(2));
|
||||
(void)dec_obj;
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, ValidIssuerTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "test")
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), issuer("arun.muralidharan"));
|
||||
(void)dec_obj;
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, InvalidIssuerTest_1)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), issuer("arun.muralidharan")),
|
||||
jwt::InvalidIssuerError);
|
||||
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, InvalidIssuerTest_2)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim("iss", "arun.muralidharan");
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), issuer("arun.murali")),
|
||||
jwt::InvalidIssuerError);
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, NotImmatureSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() - std::chrono::seconds{10});
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"));
|
||||
(void)dec_obj;
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, ImmatureSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() + std::chrono::seconds{10});
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret")),
|
||||
jwt::ImmatureSignatureError);
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, ImmatureSignatureTestWithLeeway)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}})};
|
||||
obj.add_claim(jwt::registered_claims::not_before, std::chrono::system_clock::now() + std::chrono::seconds{10});
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), leeway(10));
|
||||
(void)dec_obj;
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, InvalidAudienceTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}, {"aud", "www"}})};
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), aud("ww")),
|
||||
jwt::InvalidAudienceError);
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, InvalidSignatureTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* inv_enc_str =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ";
|
||||
|
||||
EXPECT_THROW (jwt::decode(inv_enc_str, algorithms({"none", "HS256"})),
|
||||
jwt::SignatureFormatError);
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, KeyNotPresentTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* enc_str =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJpYXQiOjE1MTM4NjIzNzEsImlkIjoiYS1iLWMtZC1lLWYtMS0yLTMiLCJpc3MiOiJhcnVuLm11cmFsaWRoYXJhbiIsInN1YiI6ImFkbWluIn0."
|
||||
"jk7bRQKTLvs1RcuvMc2B_rt6WBYPoVPirYi_QRBPiuk";
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"none", "HS256"}), verify(true)),
|
||||
jwt::KeyNotPresentError);
|
||||
}
|
||||
|
||||
TEST (DecodeVerifyExp, InvalidSubjectTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret"), payload({{"sub", "test"}, {"aud", "www"}})};
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"HS256"}), secret("secret"), sub("TEST")),
|
||||
jwt::InvalidSubjectError);
|
||||
}
|
||||
|
314
externals/cpp-jwt/tests/test_jwt_encode.cc
vendored
Executable file
314
externals/cpp-jwt/tests/test_jwt_encode.cc
vendored
Executable file
@@ -0,0 +1,314 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
#include "gtest/gtest.h"
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
TEST (EncodeTest, TestRemoveClaim)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "admin")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
.add_claim("exp", std::chrono::system_clock::now());
|
||||
|
||||
EXPECT_TRUE (obj.has_claim(jwt::registered_claims::expiration));
|
||||
|
||||
obj.remove_claim("exp");
|
||||
EXPECT_FALSE (obj.has_claim(jwt::registered_claims::expiration));
|
||||
|
||||
obj.remove_claim(jwt::registered_claims::subject);
|
||||
EXPECT_FALSE (obj.has_claim("sub"));
|
||||
}
|
||||
|
||||
TEST (EncodeTest, TestRemoveTypHeader)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "admin")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
.add_claim("exp", std::chrono::system_clock::now());
|
||||
|
||||
EXPECT_TRUE (obj.header().has_header("typ"));
|
||||
obj.header().remove_header("typ");
|
||||
EXPECT_FALSE (obj.header().has_header("typ"));
|
||||
|
||||
std::cout << "Header: " << obj.header() << '\n';
|
||||
std::cout << "Signature: " << obj.signature() << '\n';
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeHS256_1)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJpYXQiOjE1MTM4NjIzNzEsImlkIjoiYS1iLWMtZC1lLWYtMS0yLTMiLCJpc3MiOiJhcnVuLm11cmFsaWRoYXJhbiIsInN1YiI6ImFkbWluIn0."
|
||||
"jk7bRQKTLvs1RcuvMc2B_rt6WBYPoVPirYi_QRBPiuk";
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("sub", "admin")
|
||||
.add_claim("id", "a-b-c-d-e-f-1-2-3")
|
||||
.add_claim("iat", 1513862371)
|
||||
;
|
||||
|
||||
std::cout << "Header: " << obj.header() << std::endl;
|
||||
std::cout << "Payload: "<< obj.payload() << std::endl;
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
std::cout << "Signature: " << enc_str << std::endl;
|
||||
|
||||
EXPECT_EQ (enc_str, expected_sign);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeHS256_2)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJpYXQiOjE1MTM4NjIzNzEsImlkIjoiYS1iLWMtZC1lLWYtMS0yLTMiLCJpc3MiOiJhcnVuLm11cmFsaWRoYXJhbiIsInN1YiI6ImFkbWluIn0."
|
||||
"jk7bRQKTLvs1RcuvMc2B_rt6WBYPoVPirYi_QRBPiuk";
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"),
|
||||
secret("secret"),
|
||||
payload(
|
||||
{
|
||||
{"iss", "arun.muralidharan"},
|
||||
{"sub", "admin"},
|
||||
{"id", "a-b-c-d-e-f-1-2-3"}
|
||||
})
|
||||
};
|
||||
|
||||
obj.add_claim("iat", 1513862371);
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
EXPECT_EQ (enc_str, expected_sign);
|
||||
}
|
||||
|
||||
|
||||
TEST (EncodeTest, StrEncodeNONE)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
jwt::jwt_object obj{algorithm("none")};
|
||||
|
||||
obj.add_claim("aud", "rift.io")
|
||||
.add_claim("exp", 1513863371)
|
||||
.add_claim("sub", "nothing much")
|
||||
;
|
||||
|
||||
std::cout << "Header: " << obj.header() << std::endl;
|
||||
std::cout << "Payload: " << obj.payload() << std::endl;
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
EXPECT_EQ (enc_str, expected_sign);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeHS256WithKey)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ."
|
||||
"W6t7mUX6ZJwOVTsVhHSKyBSwi0wnibobdsk456wSmJg";
|
||||
|
||||
jwt::jwt_object obj{algorithm(jwt::algorithm::HS256),
|
||||
secret("0123456789abcdefghijklmnopqrstuvwxyz"),
|
||||
payload(
|
||||
{
|
||||
{"aud", "rift.io"},
|
||||
{"sub", "nothing much"}
|
||||
})
|
||||
};
|
||||
obj.add_claim("exp", 1513863371);
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
EXPECT_EQ (expected_sign, enc_str);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeHS384WithKey)
|
||||
{
|
||||
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9."
|
||||
"eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ."
|
||||
"cGN4FZCe9Y2c1dA-jP71IXGnYbJRc4OaUTa5m7N7ybF5h6wBwxWQ-pdcxYchjDBL";
|
||||
|
||||
jwt::jwt_object obj{algorithm(jwt::algorithm::HS384),
|
||||
secret("0123456789abcdefghijklmnopqrstuvwxyz"),
|
||||
payload(
|
||||
{
|
||||
{"aud", "rift.io"},
|
||||
{"sub", "nothing much"}
|
||||
})
|
||||
};
|
||||
obj.add_claim("exp", 1513863371);
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
EXPECT_EQ (expected_sign, enc_str);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeHS512WithKey)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9."
|
||||
"eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ."
|
||||
"vQ-1JSFN1kPjUI3URP6AFK5z8V7xLhyhw-76QWhQg9Xcy-IgrJ-bCTYLBjgaprrcEWwpSnBQnP3QnIxYK0HEaQ";
|
||||
|
||||
jwt::string_view key = "00112233445566778899";
|
||||
|
||||
std::map<jwt::string_view, jwt::string_view> p;
|
||||
p["aud"] = "rift.io";
|
||||
p["sub"] = "nothing much";
|
||||
|
||||
jwt::jwt_object obj{algorithm(jwt::algorithm::HS512),
|
||||
secret(key),
|
||||
payload(std::move(p))
|
||||
};
|
||||
obj.add_claim("exp", 1513863371);
|
||||
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
EXPECT_EQ (enc_str, expected_sign);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeChangeAlg)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_none_sign =
|
||||
"eyJhbGciOiJOT05FIiwidHlwIjoiSldUIn0.eyJhdWQiOiJyaWZ0LmlvIiwiZXhwIjoxNTEzODYzMzcxLCJzdWIiOiJub3RoaW5nIG11Y2gifQ.";
|
||||
|
||||
jwt::string_view key = "00112233445566778899";
|
||||
|
||||
std::map<std::string, jwt::string_view> p;
|
||||
p["aud"] = "rift.io";
|
||||
p["sub"] = "nothing much";
|
||||
|
||||
jwt::jwt_object obj{algorithm(jwt::algorithm::HS512),
|
||||
secret(key),
|
||||
payload(std::move(p))
|
||||
};
|
||||
obj.add_claim("exp", 1513863371);
|
||||
|
||||
obj.header().algo("none");
|
||||
std::string enc_str = obj.signature();
|
||||
|
||||
EXPECT_EQ (expected_none_sign, enc_str);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeNoKey)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm(jwt::algorithm::HS512),
|
||||
payload({{"iss", "arn-ml"}})
|
||||
};
|
||||
|
||||
std::error_code ec;
|
||||
std::string enc_str = obj.signature(ec);
|
||||
|
||||
ASSERT_TRUE (ec);
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::AlgorithmErrc::KeyNotFoundErr));
|
||||
}
|
||||
|
||||
TEST (EncodeTest, StrEncodeNoneAlgWithKey)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const jwt::string_view secret1 = "abcdefghijklmnopqrstuvwxyz";
|
||||
const jwt::string_view secret2 = "0123456789qwertybabe";
|
||||
|
||||
jwt::jwt_object obj{algorithm("none"),
|
||||
payload({{"iss", "arn-ml"}}),
|
||||
secret(secret1)};
|
||||
|
||||
std::error_code ec;
|
||||
std::string enc_str1 = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
obj.secret(secret2);
|
||||
std::string enc_str2 = obj.signature(ec);
|
||||
ASSERT_FALSE (ec);
|
||||
|
||||
EXPECT_EQ (enc_str1, enc_str2);
|
||||
}
|
||||
|
||||
TEST (EncodeTest, OverwriteClaimsTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("none"),
|
||||
payload({
|
||||
{"iss", "arn-ml"},
|
||||
{"x-pld1", "data1"},
|
||||
{"x-pld2", "data2"},
|
||||
{"x-pld3", "123"}
|
||||
})
|
||||
};
|
||||
|
||||
bool ret = obj.payload().add_claim("x-pld1", "1data");
|
||||
EXPECT_FALSE (ret);
|
||||
|
||||
ret = obj.payload().add_claim("x-pld1", "1data", true/*overwrite*/);
|
||||
EXPECT_TRUE (ret);
|
||||
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value("x-pld1", "1data"));
|
||||
}
|
||||
|
||||
TEST (EncodeTest, HeaderParamTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{
|
||||
headers({
|
||||
{"alg", "none"},
|
||||
{"typ", "jwt"},
|
||||
}),
|
||||
payload({
|
||||
{"iss", "arun.muralidharan"},
|
||||
{"sub", "nsfw"},
|
||||
{"x-pld", "not my ex"}
|
||||
})
|
||||
};
|
||||
|
||||
bool ret = obj.header().add_header("kid", 1234567);
|
||||
EXPECT_TRUE (ret);
|
||||
|
||||
ret = obj.header().add_header("crit", std::array<std::string, 1>{ {"exp"} });
|
||||
EXPECT_TRUE (ret);
|
||||
|
||||
std::cout << obj.header() << std::endl;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"none"}), ec, verify(true));
|
||||
EXPECT_EQ (ec.value(), static_cast<int>(jwt::AlgorithmErrc::NoneAlgorithmUsed));
|
||||
|
||||
std::cout << dec_obj.header() << std::endl;
|
||||
}
|
||||
|
149
externals/cpp-jwt/tests/test_jwt_es.cc
vendored
Executable file
149
externals/cpp-jwt/tests/test_jwt_es.cc
vendored
Executable file
@@ -0,0 +1,149 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
#define EC384_PUB_KEY CERT_ROOT_DIR "/ec_certs/ec384_pub.pem"
|
||||
#define EC384_PRIV_KEY CERT_ROOT_DIR "/ec_certs/ec384_priv.pem"
|
||||
|
||||
std::string read_from_file(const std::string& path)
|
||||
{
|
||||
std::string contents;
|
||||
std::ifstream is{path, std::ifstream::binary};
|
||||
|
||||
if (is) {
|
||||
// get length of file:
|
||||
is.seekg (0, is.end);
|
||||
auto length = is.tellg();
|
||||
is.seekg (0, is.beg);
|
||||
contents.resize(length);
|
||||
|
||||
is.read(&contents[0], length);
|
||||
if (!is) {
|
||||
is.close();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
is.close();
|
||||
return contents;
|
||||
}
|
||||
|
||||
TEST (ESAlgo, ES256EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(EC384_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("ES256"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862371)
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
EXPECT_FALSE (ec);
|
||||
|
||||
key = read_from_file(EC384_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"ES256"}), ec, verify(false), secret(key));
|
||||
EXPECT_FALSE (ec);
|
||||
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::ES256);
|
||||
EXPECT_TRUE (dec_obj.has_claim("iss"));
|
||||
EXPECT_TRUE (dec_obj.has_claim("aud"));
|
||||
EXPECT_TRUE (dec_obj.has_claim("exp"));
|
||||
|
||||
EXPECT_FALSE (dec_obj.has_claim("sub"));
|
||||
}
|
||||
|
||||
TEST (ESAlgo, ES384EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(EC384_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("ES384"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862371)
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
key = read_from_file(EC384_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"ES384"}), verify(false), secret(key));
|
||||
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::ES384);
|
||||
}
|
||||
|
||||
TEST (ESAlgo, ES512EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(EC384_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("ES512"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862371)
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
key = read_from_file(EC384_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"ES512"}), verify(false), secret(key));
|
||||
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::ES512);
|
||||
}
|
||||
|
||||
TEST (ESAlgo, ES384EncodingDecodingValidTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(EC384_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("ES384"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 4682665886) // Expires on Sunday, May 22, 2118 12:31:26 PM GMT
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
|
||||
key = read_from_file(EC384_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"ES384"}), verify(true), secret(key));
|
||||
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::ES384);
|
||||
EXPECT_TRUE (dec_obj.has_claim("exp"));
|
||||
EXPECT_TRUE (obj.payload().has_claim_with_value("exp", 4682665886));
|
||||
|
||||
std::map<std::string, std::string> keystore{{"arun.muralidharan", key}};
|
||||
|
||||
auto l = [&keystore](const jwt::jwt_payload& payload){
|
||||
auto iss = payload.get_claim_value<std::string>("iss");
|
||||
return keystore[iss];
|
||||
};
|
||||
auto dec_obj2 = jwt::decode(enc_str, algorithms({"ES384"}), verify(true), secret(l));
|
||||
EXPECT_EQ (dec_obj2.header().algo(), jwt::algorithm::ES384);
|
||||
}
|
||||
|
30
externals/cpp-jwt/tests/test_jwt_object.cc
vendored
Executable file
30
externals/cpp-jwt/tests/test_jwt_object.cc
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
struct Wrapper
|
||||
{
|
||||
// The std::move here is required to resolve to the move ctor
|
||||
// rather than to the universal reference ctor.
|
||||
Wrapper(jwt::jwt_object&& obj) : object{std::move(obj)} {}
|
||||
jwt::jwt_object object;
|
||||
};
|
||||
|
||||
} // END namespace
|
||||
|
||||
TEST (ObjectTest, MoveConstructor)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
jwt::jwt_object obj{algorithm("HS256"), secret("secret")};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan");
|
||||
|
||||
auto wrapper = Wrapper{std::move(obj)};
|
||||
|
||||
EXPECT_EQ(wrapper.object.header().algo(), jwt::algorithm::HS256);
|
||||
EXPECT_EQ(wrapper.object.secret(), "secret");
|
||||
EXPECT_TRUE(wrapper.object.payload().has_claim_with_value("iss", "arun.muralidharan"));
|
||||
}
|
||||
|
145
externals/cpp-jwt/tests/test_jwt_rsa.cc
vendored
Executable file
145
externals/cpp-jwt/tests/test_jwt_rsa.cc
vendored
Executable file
@@ -0,0 +1,145 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "jwt/jwt.hpp"
|
||||
|
||||
#define RSA256_PUB_KEY CERT_ROOT_DIR "/rsa_certs/rsa256_pub.pem"
|
||||
#define RSA256_PRIV_KEY CERT_ROOT_DIR "/rsa_certs/rsa256_priv.pem"
|
||||
#define RSA384_PUB_KEY CERT_ROOT_DIR "/rsa_certs/rsa384_pub.pem"
|
||||
#define RSA384_PRIV_KEY CERT_ROOT_DIR "/rsa_certs/rsa384_priv.pem"
|
||||
#define RSA512_PUB_KEY CERT_ROOT_DIR "/rsa_certs/rsa512_pub.pem"
|
||||
#define RSA512_PRIV_KEY CERT_ROOT_DIR "/rsa_certs/rsa512_priv.pem"
|
||||
|
||||
std::string read_from_file(const std::string& path)
|
||||
{
|
||||
std::string contents;
|
||||
std::ifstream is{path, std::ifstream::binary};
|
||||
|
||||
if (is) {
|
||||
// get length of file:
|
||||
is.seekg (0, is.end);
|
||||
auto length = is.tellg();
|
||||
is.seekg (0, is.beg);
|
||||
contents.resize(length);
|
||||
|
||||
is.read(&contents[0], length);
|
||||
if (!is) {
|
||||
is.close();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
is.close();
|
||||
return contents;
|
||||
}
|
||||
|
||||
TEST (RSAAlgo, RSA256EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_sign =
|
||||
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhbGwiLCJleHAiOjE1MTM4NjIzNzEsImlzcyI6ImFydW4ubXVyYWxpZGhhcmFuIn0.jr-Nrny0yGFuIUH8zHLuxpGH5aClwQVin2As2ISsgclu-9IDi1cVCtloIUNRb_ock6X7X41FtGMA_lt_T9wGyLmMzNf4Vu7OPBGfzjEdCHKD8OgcvI0Z4qw7_TFuXEuNSnbwkYFZ9S2g8uPzO0raVk4aIuczo58btwEDrsoE7TNBMTHjfL92zZ90YcFqW5WZKn9Y_dF1rb5UXARF6YSzzVjaNC86FWUl86wwo9cir0nxVPD4zKol_x2xyiP6n4n-sUX0_dM_-KMSfDqdr34quq3ZxcP5vjT-8FWb4t_IWHBmLrNsjS1so9a_5u7vcSBX1llX9Vgztv0zB7B8rEkFTw";
|
||||
|
||||
std::string key = read_from_file(RSA256_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("RS256"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862371)
|
||||
;
|
||||
|
||||
std::error_code ec;
|
||||
auto enc_str = obj.signature(ec);
|
||||
EXPECT_FALSE (ec);
|
||||
|
||||
EXPECT_EQ (enc_str, expected_sign);
|
||||
|
||||
//Decode
|
||||
key = read_from_file(RSA256_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"RS256"}), ec, verify(false), secret(key));
|
||||
EXPECT_FALSE (ec);
|
||||
}
|
||||
|
||||
TEST (RSAAlgo, RSA384EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(RSA384_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
const char* expected_str =
|
||||
"eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhbGwiLCJleHAiOjE1MTM4NjIzNzIsImlzcyI6ImFydW4ubXVyYWxpZGhhcmFuIn0.iXQyGTmHAjdfXXgcMZn31xqv05h8Qoa3GGlSF5-42kPkd6iLPWzxky15FFW8qkvO-DiXDpOM4BoDANYCKNTSOToyuhCZ6dn_WH8RQzU6KOqRccYe2Fgvo7XnrgE_iHIMYPejc2kAUh1xLpE31WCU2P1afo2KN_-DV7kCmDJY6qpFtCctbbPNOhv6XbYpQlTblZeYDh1HVO--KWuhYl17kgjj3W-3fEoQjgaiprZ_JsTxRTN05aGT_AY15-FW0jPgPPBw5FnIX6P-j18F3BrG-lji7BuNrvyCUT3ZX35yBkBv9Ri5B3SLALy2bD0qGGE_G9_Orfm9yU9oQySLMO1qLiMbKLakLB5kMSy049C2Pdx9Nz47hqQWOHOWNRGwwTkKAwjeu1dTjv14QOmLcefM6GoXoCMZaFcmEqr63CgyLrnlsVS6vLkazyWcKD6eg51vPa8Rnn1V5u1EgNNnT6nU6iZ9_POJcf9_s-7HNpAXtlckia-OIrdLG-5cm93h1rAfVois43m0EwNtTr_DZ2JDtM9BifaS5MsktztUjrh1hjF5vDLBQc8vAYX0YbWOx_0NTn0aRYzOZ9kIhFxkaY320h8AS_7iFa5sA-ygeJdR-EvdlUZcoRzPzQFkrtatK-UE_VlSisUCsqoxHefx799aNjqz4FDLcyQRekdmVMb8Ew8";
|
||||
|
||||
jwt::jwt_object obj{algorithm("RS384"), secret(key)};
|
||||
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862372)
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
EXPECT_EQ (enc_str, expected_str);
|
||||
|
||||
//Decode
|
||||
key = read_from_file(RSA384_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"none", "HS384", "RS384"}), verify(false), secret(key));
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::RS384);
|
||||
}
|
||||
|
||||
TEST (RSAAlgo, RSA512EncodingDecodingTest)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
const char* expected_str =
|
||||
"eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhbGwiLCJleHAiOjE1MTM4NjIzNzIsImlzcyI6ImFydW4ubXVyYWxpZGhhcmFuIn0.ZNkLnf565-NFfxkbosJra1CJEgCLFf0jmgb7Q8eZrzxIrE4C4dOjpGD13f0jm2FqidUxAvFVrHI2ahhZi4Bu65qQtV4mVVftiD0qTaYzh26ql0MFqTKYEeKtU0kFXAzH7f9689z7mQ2n8aw7H8WHrfe17ub19Xyj-MirCECcWjcuGWBhsdz0y-dKy_GJYnpf8mHvmQAjkH5ynUV5NXHIBDO6eKssxX36Ow9_KYZ1HrCCUT_B-TQfNrnHAJgCydO-cX9iaAxV5aKvOdMGopHz14fX4oI9qH4aBzcroRbs77UsJZ-CMoRnUoXQP7DPORvEEUOQepANu9gqmymfJin8oEDotlj7eoJkFD3j64dkMT2bnRe8k2akPgUiDTeIrvNBuOIMDJtekoVpTo0fytveeDVPpDli9uX6DkJW1GGFLSRR-J-I8WbKRMKadmKOpDn3LF71hOo2mcXAsSwleFi9xB39bLBKJcqL_DtBoZBt0QSqMs6nRVj1U-3vYtuaa_eM3TfxhWWPZULaGVaVfpefRGdqtjrU0z5oO_vjviYujXK5_vM8zTroLVEaOyJYCeh2h_5N5LaOlf8BDu2PF3epNuCmM7G2PWEH7aPn5o-vvKTg_SM32jJXbXp2gkplEdQIWFh3jtjcRe9wNa9aPJE3I1hn1ZbqiAGUzBLWYUYpvstWXGbmxOoh6FkNJERb2hOIZgGLMvwWZXUU3GICcI5DMFOdDsuANpLg5FygsQ68JpuqKrUxu1Yh55--GHuDI7tqdHsPhPUzTmZrSvRog0w07dUAZCIBsGsSLX3wViobWbpVuY4pB7KXGIfdXgLfLgcERe_CxtnoPGF36zsqBflSXcqXwJ4qRK6BpTvKyUXf6pWEWOnuKomk8aENbT6nTr7naRJb5L3J4zhE-5O_Yetw9aCTzy9vN8a22n0JHXeroAwTpLR_wsQwDPwN-K99JVUKwR-FvOkJhE7_wwbUXmjiacKjXrwQ0OWnhXigQRLfdHG2OyH6_It5dpBmBOyWx2X-tfQ6Wz-_2bKCALl487Amq56hhNJhbQuJFIR59RylVAWKmfeeno2qcTZgrI_mO3PJCCUxBn5hK81HJuOtZ4YmeDHPvLW8Tiv5KqfRMWJKhyFthB74FvUINiEn0jvbuLR3YuyTgpf22lohT4-mHq5FrEd3plGvj0fVI_zeGhAFBhQYMW-MAJo7oylTOMtSZ1JHHuvBPR6FvMTgaPTAum6Dsl-I4_O_OKgtgovefBgwh4TOm_vsJmjVYFRr0Eo3OqsfNw3OwSKnuv5I76thh6DN879UZiyJG_7lcz_L6d0g4fGCvdM45zgQp3U3l8fJN1MRYCx5mxJAYeVlnCpmqueuww";
|
||||
|
||||
std::string key = read_from_file(RSA512_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("RS512"), secret(key)};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862372)
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
EXPECT_EQ (enc_str, expected_str);
|
||||
|
||||
|
||||
key = read_from_file(RSA512_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
auto dec_obj = jwt::decode(enc_str, algorithms({"none", "HS384", "RS512"}), verify(false), secret(key));
|
||||
EXPECT_EQ (dec_obj.header().algo(), jwt::algorithm::RS512);
|
||||
}
|
||||
|
||||
TEST (RSAAlgo, NoSpecificAlgo)
|
||||
{
|
||||
using namespace jwt::params;
|
||||
|
||||
std::string key = read_from_file(RSA512_PRIV_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
jwt::jwt_object obj{algorithm("RS512"), secret(key)};
|
||||
obj.add_claim("iss", "arun.muralidharan")
|
||||
.add_claim("aud", "all")
|
||||
.add_claim("exp", 1513862372)
|
||||
;
|
||||
|
||||
auto enc_str = obj.signature();
|
||||
key = read_from_file(RSA512_PUB_KEY);
|
||||
ASSERT_TRUE (key.length());
|
||||
|
||||
EXPECT_THROW (jwt::decode(enc_str, algorithms({"none", "HS384", "RS384"}), verify(true), secret(key)),
|
||||
jwt::InvalidAlgorithmError);
|
||||
}
|
||||
|
11
externals/cpp-jwt/vcpkg.json
vendored
Executable file
11
externals/cpp-jwt/vcpkg.json
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "cpp-jwt",
|
||||
"version": "1.5",
|
||||
"description": "JSON Web Token library for C++",
|
||||
"homepage": "https://github.com/arun11299/cpp-jwt",
|
||||
"dependencies": [
|
||||
"nlohmann-json",
|
||||
"openssl",
|
||||
"gtest"
|
||||
]
|
||||
}
|
94
externals/enet/CMakeLists.txt
vendored
Executable file
94
externals/enet/CMakeLists.txt
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
project(enet)
|
||||
|
||||
# The "configure" step.
|
||||
include(CheckFunctionExists)
|
||||
include(CheckStructHasMember)
|
||||
include(CheckTypeSize)
|
||||
check_function_exists("fcntl" HAS_FCNTL)
|
||||
check_function_exists("poll" HAS_POLL)
|
||||
check_function_exists("getaddrinfo" HAS_GETADDRINFO)
|
||||
check_function_exists("getnameinfo" HAS_GETNAMEINFO)
|
||||
check_function_exists("gethostbyname_r" HAS_GETHOSTBYNAME_R)
|
||||
check_function_exists("gethostbyaddr_r" HAS_GETHOSTBYADDR_R)
|
||||
check_function_exists("inet_pton" HAS_INET_PTON)
|
||||
check_function_exists("inet_ntop" HAS_INET_NTOP)
|
||||
check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" HAS_MSGHDR_FLAGS)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h" "sys/socket.h")
|
||||
check_type_size("socklen_t" HAS_SOCKLEN_T BUILTIN_TYPES_ONLY)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
if(MSVC)
|
||||
add_definitions(-W3)
|
||||
else()
|
||||
add_definitions(-Wno-error)
|
||||
endif()
|
||||
|
||||
if(HAS_FCNTL)
|
||||
add_definitions(-DHAS_FCNTL=1)
|
||||
endif()
|
||||
if(HAS_POLL)
|
||||
add_definitions(-DHAS_POLL=1)
|
||||
endif()
|
||||
if(HAS_GETNAMEINFO)
|
||||
add_definitions(-DHAS_GETNAMEINFO=1)
|
||||
endif()
|
||||
if(HAS_GETADDRINFO)
|
||||
add_definitions(-DHAS_GETADDRINFO=1)
|
||||
endif()
|
||||
if(HAS_GETHOSTBYNAME_R)
|
||||
add_definitions(-DHAS_GETHOSTBYNAME_R=1)
|
||||
endif()
|
||||
if(HAS_GETHOSTBYADDR_R)
|
||||
add_definitions(-DHAS_GETHOSTBYADDR_R=1)
|
||||
endif()
|
||||
if(HAS_INET_PTON)
|
||||
add_definitions(-DHAS_INET_PTON=1)
|
||||
endif()
|
||||
if(HAS_INET_NTOP)
|
||||
add_definitions(-DHAS_INET_NTOP=1)
|
||||
endif()
|
||||
if(HAS_MSGHDR_FLAGS)
|
||||
add_definitions(-DHAS_MSGHDR_FLAGS=1)
|
||||
endif()
|
||||
if(HAS_SOCKLEN_T)
|
||||
add_definitions(-DHAS_SOCKLEN_T=1)
|
||||
endif()
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
|
||||
set(INCLUDE_FILES_PREFIX include/enet)
|
||||
set(INCLUDE_FILES
|
||||
${INCLUDE_FILES_PREFIX}/callbacks.h
|
||||
${INCLUDE_FILES_PREFIX}/enet.h
|
||||
${INCLUDE_FILES_PREFIX}/list.h
|
||||
${INCLUDE_FILES_PREFIX}/protocol.h
|
||||
${INCLUDE_FILES_PREFIX}/time.h
|
||||
${INCLUDE_FILES_PREFIX}/types.h
|
||||
${INCLUDE_FILES_PREFIX}/unix.h
|
||||
${INCLUDE_FILES_PREFIX}/utility.h
|
||||
${INCLUDE_FILES_PREFIX}/win32.h
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
callbacks.c
|
||||
compress.c
|
||||
host.c
|
||||
list.c
|
||||
packet.c
|
||||
peer.c
|
||||
protocol.c
|
||||
unix.c
|
||||
win32.c)
|
||||
|
||||
source_group(include FILES ${INCLUDE_FILES})
|
||||
source_group(source FILES ${SOURCE_FILES})
|
||||
|
||||
add_library(enet STATIC
|
||||
${INCLUDE_FILES}
|
||||
${SOURCE_FILES}
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
target_link_libraries(enet winmm ws2_32)
|
||||
endif()
|
179
externals/enet/ChangeLog
vendored
Executable file
179
externals/enet/ChangeLog
vendored
Executable file
@@ -0,0 +1,179 @@
|
||||
* use getaddrinfo and getnameinfo where available
|
||||
|
||||
ENet 1.3.13 (April 30, 2015):
|
||||
|
||||
* miscellaneous bug fixes
|
||||
* added premake and cmake support
|
||||
* miscellaneous documentation cleanups
|
||||
|
||||
ENet 1.3.12 (April 24, 2014):
|
||||
|
||||
* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of
|
||||
data waiting to be delivered on a peer (beware that the default maximumPacketSize is
|
||||
32MB and should be set higher if desired as should maximumWaitingData)
|
||||
|
||||
ENet 1.3.11 (December 26, 2013):
|
||||
|
||||
* allow an ENetHost to connect to itself
|
||||
* fixed possible bug with disconnect notifications during connect attempts
|
||||
* fixed some preprocessor definition bugs
|
||||
|
||||
ENet 1.3.10 (October 23, 2013);
|
||||
|
||||
* doubled maximum reliable window size
|
||||
* fixed RCVTIMEO/SNDTIMEO socket options and also added NODELAY
|
||||
|
||||
ENet 1.3.9 (August 19, 2013):
|
||||
|
||||
* added duplicatePeers option to ENetHost which can limit the number of peers from duplicate IPs
|
||||
* added enet_socket_get_option() and ENET_SOCKOPT_ERROR
|
||||
* added enet_host_random_seed() platform stub
|
||||
|
||||
ENet 1.3.8 (June 2, 2013):
|
||||
|
||||
* added enet_linked_version() for checking the linked version
|
||||
* added enet_socket_get_address() for querying the local address of a socket
|
||||
* silenced some debugging prints unless ENET_DEBUG is defined during compilation
|
||||
* handle EINTR in enet_socket_wait() so that enet_host_service() doesn't propagate errors from signals
|
||||
* optimized enet_host_bandwidth_throttle() to be less expensive for large numbers of peers
|
||||
|
||||
ENet 1.3.7 (March 6, 2013):
|
||||
|
||||
* added ENET_PACKET_FLAG_SENT to indicate that a packet is being freed because it has been sent
|
||||
* added userData field to ENetPacket
|
||||
* changed how random seed is generated on Windows to avoid import warnings
|
||||
* fixed case where disconnects could be generated with no preceding connect event
|
||||
|
||||
ENet 1.3.6 (December 11, 2012):
|
||||
|
||||
* added support for intercept callback in ENetHost that can be used to process raw packets before ENet
|
||||
* added enet_socket_shutdown() for issuing shutdown on a socket
|
||||
* fixed enet_socket_connect() to not error on non-blocking connects
|
||||
* fixed bug in MTU negotiation during connections
|
||||
|
||||
ENet 1.3.5 (July 31, 2012):
|
||||
|
||||
* fixed bug in unreliable packet fragment queuing
|
||||
|
||||
ENet 1.3.4 (May 29, 2012):
|
||||
|
||||
* added enet_peer_ping_interval() for configuring per-peer ping intervals
|
||||
* added enet_peer_timeout() for configuring per-peer timeouts
|
||||
* added protocol packet size limits
|
||||
|
||||
ENet 1.3.3 (June 28, 2011):
|
||||
|
||||
* fixed bug with simultaneous disconnects not dispatching events
|
||||
|
||||
ENet 1.3.2 (May 31, 2011):
|
||||
|
||||
* added support for unreliable packet fragmenting via the packet flag
|
||||
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT
|
||||
* fixed regression in unreliable packet queuing
|
||||
* added check against received port to limit some forms of IP-spoofing
|
||||
|
||||
ENet 1.3.1 (February 10, 2011):
|
||||
|
||||
* fixed bug in tracking of reliable data in transit
|
||||
* reliable data window size now scales with the throttle
|
||||
* fixed bug in fragment length calculation when checksums are used
|
||||
|
||||
ENet 1.3.0 (June 5, 2010):
|
||||
|
||||
* enet_host_create() now requires the channel limit to be specified as
|
||||
a parameter
|
||||
* enet_host_connect() now accepts a data parameter which is supplied
|
||||
to the receiving receiving host in the event data field for a connect event
|
||||
* added an adaptive order-2 PPM range coder as a built-in compressor option
|
||||
which can be set with enet_host_compress_with_range_coder()
|
||||
* added support for packet compression configurable with a callback
|
||||
* improved session number handling to not rely on the packet checksum
|
||||
field, saving 4 bytes per packet unless the checksum option is used
|
||||
* removed the dependence on the rand callback for session number handling
|
||||
|
||||
Caveats: This version is not protocol compatible with the 1.2 series or
|
||||
earlier. The enet_host_connect and enet_host_create API functions require
|
||||
supplying additional parameters.
|
||||
|
||||
ENet 1.2.5 (June 28, 2011):
|
||||
|
||||
* fixed bug with simultaneous disconnects not dispatching events
|
||||
|
||||
ENet 1.2.4 (May 31, 2011):
|
||||
|
||||
* fixed regression in unreliable packet queuing
|
||||
* added check against received port to limit some forms of IP-spoofing
|
||||
|
||||
ENet 1.2.3 (February 10, 2011):
|
||||
|
||||
* fixed bug in tracking reliable data in transit
|
||||
|
||||
ENet 1.2.2 (June 5, 2010):
|
||||
|
||||
* checksum functionality is now enabled by setting a checksum callback
|
||||
inside ENetHost instead of being a configure script option
|
||||
* added totalSentData, totalSentPackets, totalReceivedData, and
|
||||
totalReceivedPackets counters inside ENetHost for getting usage
|
||||
statistics
|
||||
* added enet_host_channel_limit() for limiting the maximum number of
|
||||
channels allowed by connected peers
|
||||
* now uses dispatch queues for event dispatch rather than potentially
|
||||
unscalable array walking
|
||||
* added no_memory callback that is called when a malloc attempt fails,
|
||||
such that if no_memory returns rather than aborts (the default behavior),
|
||||
then the error is propagated to the return value of the API calls
|
||||
* now uses packed attribute for protocol structures on platforms with
|
||||
strange alignment rules
|
||||
* improved autoconf build system contributed by Nathan Brink allowing
|
||||
for easier building as a shared library
|
||||
|
||||
Caveats: If you were using the compile-time option that enabled checksums,
|
||||
make sure to set the checksum callback inside ENetHost to enet_crc32 to
|
||||
regain the old behavior. The ENetCallbacks structure has added new fields,
|
||||
so make sure to clear the structure to zero before use if
|
||||
using enet_initialize_with_callbacks().
|
||||
|
||||
ENet 1.2.1 (November 12, 2009):
|
||||
|
||||
* fixed bug that could cause disconnect events to be dropped
|
||||
* added thin wrapper around select() for portable usage
|
||||
* added ENET_SOCKOPT_REUSEADDR socket option
|
||||
* factored enet_socket_bind()/enet_socket_listen() out of enet_socket_create()
|
||||
* added contributed Code::Blocks build file
|
||||
|
||||
ENet 1.2 (February 12, 2008):
|
||||
|
||||
* fixed bug in VERIFY_CONNECT acknowledgement that could cause connect
|
||||
attempts to occasionally timeout
|
||||
* fixed acknowledgements to check both the outgoing and sent queues
|
||||
when removing acknowledged packets
|
||||
* fixed accidental bit rot in the MSVC project file
|
||||
* revised sequence number overflow handling to address some possible
|
||||
disconnect bugs
|
||||
* added enet_host_check_events() for getting only local queued events
|
||||
* factored out socket option setting into enet_socket_set_option() so
|
||||
that socket options are now set separately from enet_socket_create()
|
||||
|
||||
Caveats: While this release is superficially protocol compatible with 1.1,
|
||||
differences in the sequence number overflow handling can potentially cause
|
||||
random disconnects.
|
||||
|
||||
ENet 1.1 (June 6, 2007):
|
||||
|
||||
* optional CRC32 just in case someone needs a stronger checksum than UDP
|
||||
provides (--enable-crc32 configure option)
|
||||
* the size of packet headers are half the size they used to be (so less
|
||||
overhead when sending small packets)
|
||||
* enet_peer_disconnect_later() that waits till all queued outgoing
|
||||
packets get sent before issuing an actual disconnect
|
||||
* freeCallback field in individual packets for notification of when a
|
||||
packet is about to be freed
|
||||
* ENET_PACKET_FLAG_NO_ALLOCATE for supplying pre-allocated data to a
|
||||
packet (can be used in concert with freeCallback to support some custom
|
||||
allocation schemes that the normal memory allocation callbacks would
|
||||
normally not allow)
|
||||
* enet_address_get_host_ip() for printing address numbers
|
||||
* promoted the enet_socket_*() functions to be part of the API now
|
||||
* a few stability/crash fixes
|
||||
|
||||
|
2303
externals/enet/Doxyfile
vendored
Executable file
2303
externals/enet/Doxyfile
vendored
Executable file
File diff suppressed because it is too large
Load Diff
191
externals/enet/DoxygenLayout.xml
vendored
Executable file
191
externals/enet/DoxygenLayout.xml
vendored
Executable file
@@ -0,0 +1,191 @@
|
||||
<doxygenlayout version="1.0">
|
||||
<!-- Generated by doxygen 1.8.6 -->
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title="Home"/>
|
||||
<tab type="user" visible="yes" title="Features" url="@ref Features" />
|
||||
<tab type="user" visible="yes" title="Downloads" url="@ref Downloads" />
|
||||
<tab type="user" visible="yes" title="Installation" url="@ref Installation" />
|
||||
<tab type="user" visible="yes" title="Tutorial" url="@ref Tutorial" />
|
||||
<tab type="user" visible="yes" title="Mailing List" url="@ref MailingList" />
|
||||
<tab type="user" visible="yes" title="IRC Channel" url="@ref IRCChannel" />
|
||||
<tab type="user" visible="yes" title="FAQ" url="@ref FAQ" />
|
||||
<tab type="user" visible="yes" title="License" url="@ref License" />
|
||||
<tab type="usergroup" visible="yes" title="Documentation" briefdescription="Documentation">
|
||||
<tab type="modules" visible="yes" title="Functions" intro=""/>
|
||||
<tab type="classlist" visible="yes" title="Data Structures" intro=""/>
|
||||
<tab type="filelist" visible="yes" title="Files" intro=""/>
|
||||
<tab type="globals" visible="yes" title="" intro=""/>
|
||||
</tab>
|
||||
</navindex>
|
||||
|
||||
<!-- Layout definition for a class page -->
|
||||
<class>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||
<memberdecl>
|
||||
<nestedclasses visible="yes" title=""/>
|
||||
<publictypes title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<publicslots title=""/>
|
||||
<signals title=""/>
|
||||
<publicmethods title=""/>
|
||||
<publicstaticmethods title=""/>
|
||||
<publicattributes title=""/>
|
||||
<publicstaticattributes title=""/>
|
||||
<protectedtypes title=""/>
|
||||
<protectedslots title=""/>
|
||||
<protectedmethods title=""/>
|
||||
<protectedstaticmethods title=""/>
|
||||
<protectedattributes title=""/>
|
||||
<protectedstaticattributes title=""/>
|
||||
<packagetypes title=""/>
|
||||
<packagemethods title=""/>
|
||||
<packagestaticmethods title=""/>
|
||||
<packageattributes title=""/>
|
||||
<packagestaticattributes title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
<privatetypes title=""/>
|
||||
<privateslots title=""/>
|
||||
<privatemethods title=""/>
|
||||
<privatestaticmethods title=""/>
|
||||
<privateattributes title=""/>
|
||||
<privatestaticattributes title=""/>
|
||||
<friends title=""/>
|
||||
<related title="" subtitle=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<services title=""/>
|
||||
<interfaces title=""/>
|
||||
<constructors title=""/>
|
||||
<functions title=""/>
|
||||
<related title=""/>
|
||||
<variables title=""/>
|
||||
<properties title=""/>
|
||||
<events title=""/>
|
||||
</memberdef>
|
||||
<allmemberslink visible="yes"/>
|
||||
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||
<authorsection visible="yes"/>
|
||||
</class>
|
||||
|
||||
<!-- Layout definition for a namespace page -->
|
||||
<namespace>
|
||||
<briefdescription visible="yes"/>
|
||||
<memberdecl>
|
||||
<nestednamespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</namespace>
|
||||
|
||||
<!-- Layout definition for a file page -->
|
||||
<file>
|
||||
<briefdescription visible="yes"/>
|
||||
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||
<sourcelink visible="yes"/>
|
||||
<memberdecl>
|
||||
<classes visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<constantgroups visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
</memberdef>
|
||||
<authorsection/>
|
||||
</file>
|
||||
|
||||
<!-- Layout definition for a group page -->
|
||||
<group>
|
||||
<briefdescription visible="yes"/>
|
||||
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||
<memberdecl>
|
||||
<nestedgroups visible="yes" title=""/>
|
||||
<dirs visible="yes" title=""/>
|
||||
<files visible="yes" title=""/>
|
||||
<namespaces visible="yes" title=""/>
|
||||
<classes visible="yes" title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
<membergroups visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
<memberdef>
|
||||
<pagedocs/>
|
||||
<inlineclasses title=""/>
|
||||
<defines title=""/>
|
||||
<typedefs title=""/>
|
||||
<enums title=""/>
|
||||
<enumvalues title=""/>
|
||||
<functions title=""/>
|
||||
<variables title=""/>
|
||||
<signals title=""/>
|
||||
<publicslots title=""/>
|
||||
<protectedslots title=""/>
|
||||
<privateslots title=""/>
|
||||
<events title=""/>
|
||||
<properties title=""/>
|
||||
<friends title=""/>
|
||||
</memberdef>
|
||||
<authorsection visible="yes"/>
|
||||
</group>
|
||||
|
||||
<!-- Layout definition for a directory page -->
|
||||
<directory>
|
||||
<briefdescription visible="yes"/>
|
||||
<directorygraph visible="yes"/>
|
||||
<memberdecl>
|
||||
<dirs visible="yes"/>
|
||||
<files visible="yes"/>
|
||||
</memberdecl>
|
||||
<detaileddescription title=""/>
|
||||
</directory>
|
||||
</doxygenlayout>
|
7
externals/enet/LICENSE
vendored
Executable file
7
externals/enet/LICENSE
vendored
Executable file
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2002-2016 Lee Salzman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
externals/enet/Makefile.am
vendored
Executable file
22
externals/enet/Makefile.am
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
nodist_pkgconfig_DATA = libenet.pc
|
||||
|
||||
enetincludedir=$(includedir)/enet
|
||||
enetinclude_HEADERS = \
|
||||
include/enet/callbacks.h \
|
||||
include/enet/enet.h \
|
||||
include/enet/list.h \
|
||||
include/enet/protocol.h \
|
||||
include/enet/time.h \
|
||||
include/enet/types.h \
|
||||
include/enet/unix.h \
|
||||
include/enet/utility.h \
|
||||
include/enet/win32.h
|
||||
|
||||
lib_LTLIBRARIES = libenet.la
|
||||
libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c
|
||||
# see info '(libtool) Updating version info' before making a release
|
||||
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:1:0
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
ACLOCAL_AMFLAGS = -Im4
|
15
externals/enet/README
vendored
Executable file
15
externals/enet/README
vendored
Executable file
@@ -0,0 +1,15 @@
|
||||
Please visit the ENet homepage at http://enet.bespin.org for installation
|
||||
and usage instructions.
|
||||
|
||||
If you obtained this package from github, the quick description on how to build
|
||||
is:
|
||||
|
||||
# Generate the build system.
|
||||
|
||||
autoreconf -vfi
|
||||
|
||||
# Compile and install the library.
|
||||
|
||||
./configure && make && make install
|
||||
|
||||
|
53
externals/enet/callbacks.c
vendored
Executable file
53
externals/enet/callbacks.c
vendored
Executable file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
@file callbacks.c
|
||||
@brief ENet callback functions
|
||||
*/
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include "enet/enet.h"
|
||||
|
||||
static ENetCallbacks callbacks = { malloc, free, abort };
|
||||
|
||||
int
|
||||
enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
|
||||
{
|
||||
if (version < ENET_VERSION_CREATE (1, 3, 0))
|
||||
return -1;
|
||||
|
||||
if (inits -> malloc != NULL || inits -> free != NULL)
|
||||
{
|
||||
if (inits -> malloc == NULL || inits -> free == NULL)
|
||||
return -1;
|
||||
|
||||
callbacks.malloc = inits -> malloc;
|
||||
callbacks.free = inits -> free;
|
||||
}
|
||||
|
||||
if (inits -> no_memory != NULL)
|
||||
callbacks.no_memory = inits -> no_memory;
|
||||
|
||||
return enet_initialize ();
|
||||
}
|
||||
|
||||
ENetVersion
|
||||
enet_linked_version (void)
|
||||
{
|
||||
return ENET_VERSION;
|
||||
}
|
||||
|
||||
void *
|
||||
enet_malloc (size_t size)
|
||||
{
|
||||
void * memory = callbacks.malloc (size);
|
||||
|
||||
if (memory == NULL)
|
||||
callbacks.no_memory ();
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
void
|
||||
enet_free (void * memory)
|
||||
{
|
||||
callbacks.free (memory);
|
||||
}
|
||||
|
654
externals/enet/compress.c
vendored
Executable file
654
externals/enet/compress.c
vendored
Executable file
@@ -0,0 +1,654 @@
|
||||
/**
|
||||
@file compress.c
|
||||
@brief An adaptive order-2 PPM range coder
|
||||
*/
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include <string.h>
|
||||
#include "enet/enet.h"
|
||||
|
||||
typedef struct _ENetSymbol
|
||||
{
|
||||
/* binary indexed tree of symbols */
|
||||
enet_uint8 value;
|
||||
enet_uint8 count;
|
||||
enet_uint16 under;
|
||||
enet_uint16 left, right;
|
||||
|
||||
/* context defined by this symbol */
|
||||
enet_uint16 symbols;
|
||||
enet_uint16 escapes;
|
||||
enet_uint16 total;
|
||||
enet_uint16 parent;
|
||||
} ENetSymbol;
|
||||
|
||||
/* adaptation constants tuned aggressively for small packet sizes rather than large file compression */
|
||||
enum
|
||||
{
|
||||
ENET_RANGE_CODER_TOP = 1<<24,
|
||||
ENET_RANGE_CODER_BOTTOM = 1<<16,
|
||||
|
||||
ENET_CONTEXT_SYMBOL_DELTA = 3,
|
||||
ENET_CONTEXT_SYMBOL_MINIMUM = 1,
|
||||
ENET_CONTEXT_ESCAPE_MINIMUM = 1,
|
||||
|
||||
ENET_SUBCONTEXT_ORDER = 2,
|
||||
ENET_SUBCONTEXT_SYMBOL_DELTA = 2,
|
||||
ENET_SUBCONTEXT_ESCAPE_DELTA = 5
|
||||
};
|
||||
|
||||
/* context exclusion roughly halves compression speed, so disable for now */
|
||||
#undef ENET_CONTEXT_EXCLUSION
|
||||
|
||||
typedef struct _ENetRangeCoder
|
||||
{
|
||||
/* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */
|
||||
ENetSymbol symbols[4096];
|
||||
} ENetRangeCoder;
|
||||
|
||||
void *
|
||||
enet_range_coder_create (void)
|
||||
{
|
||||
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder));
|
||||
if (rangeCoder == NULL)
|
||||
return NULL;
|
||||
|
||||
return rangeCoder;
|
||||
}
|
||||
|
||||
void
|
||||
enet_range_coder_destroy (void * context)
|
||||
{
|
||||
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
|
||||
if (rangeCoder == NULL)
|
||||
return;
|
||||
|
||||
enet_free (rangeCoder);
|
||||
}
|
||||
|
||||
#define ENET_SYMBOL_CREATE(symbol, value_, count_) \
|
||||
{ \
|
||||
symbol = & rangeCoder -> symbols [nextSymbol ++]; \
|
||||
symbol -> value = value_; \
|
||||
symbol -> count = count_; \
|
||||
symbol -> under = count_; \
|
||||
symbol -> left = 0; \
|
||||
symbol -> right = 0; \
|
||||
symbol -> symbols = 0; \
|
||||
symbol -> escapes = 0; \
|
||||
symbol -> total = 0; \
|
||||
symbol -> parent = 0; \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_CREATE(context, escapes_, minimum) \
|
||||
{ \
|
||||
ENET_SYMBOL_CREATE (context, 0, 0); \
|
||||
(context) -> escapes = escapes_; \
|
||||
(context) -> total = escapes_ + 256*minimum; \
|
||||
(context) -> symbols = 0; \
|
||||
}
|
||||
|
||||
static enet_uint16
|
||||
enet_symbol_rescale (ENetSymbol * symbol)
|
||||
{
|
||||
enet_uint16 total = 0;
|
||||
for (;;)
|
||||
{
|
||||
symbol -> count -= symbol->count >> 1;
|
||||
symbol -> under = symbol -> count;
|
||||
if (symbol -> left)
|
||||
symbol -> under += enet_symbol_rescale (symbol + symbol -> left);
|
||||
total += symbol -> under;
|
||||
if (! symbol -> right) break;
|
||||
symbol += symbol -> right;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_RESCALE(context, minimum) \
|
||||
{ \
|
||||
(context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \
|
||||
(context) -> escapes -= (context) -> escapes >> 1; \
|
||||
(context) -> total += (context) -> escapes + 256*minimum; \
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_OUTPUT(value) \
|
||||
{ \
|
||||
if (outData >= outEnd) \
|
||||
return 0; \
|
||||
* outData ++ = value; \
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_ENCODE(under, count, total) \
|
||||
{ \
|
||||
encodeRange /= (total); \
|
||||
encodeLow += (under) * encodeRange; \
|
||||
encodeRange *= (count); \
|
||||
for (;;) \
|
||||
{ \
|
||||
if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \
|
||||
{ \
|
||||
if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
|
||||
encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
|
||||
} \
|
||||
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
|
||||
encodeRange <<= 8; \
|
||||
encodeLow <<= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_FLUSH \
|
||||
{ \
|
||||
while (encodeLow) \
|
||||
{ \
|
||||
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
|
||||
encodeLow <<= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_FREE_SYMBOLS \
|
||||
{ \
|
||||
if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \
|
||||
{ \
|
||||
nextSymbol = 0; \
|
||||
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \
|
||||
predicted = 0; \
|
||||
order = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \
|
||||
{ \
|
||||
under_ = value*minimum; \
|
||||
count_ = minimum; \
|
||||
if (! (context) -> symbols) \
|
||||
{ \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
(context) -> symbols = symbol_ - (context); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ENetSymbol * node = (context) + (context) -> symbols; \
|
||||
for (;;) \
|
||||
{ \
|
||||
if (value_ < node -> value) \
|
||||
{ \
|
||||
node -> under += update; \
|
||||
if (node -> left) { node += node -> left; continue; } \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
node -> left = symbol_ - node; \
|
||||
} \
|
||||
else \
|
||||
if (value_ > node -> value) \
|
||||
{ \
|
||||
under_ += node -> under; \
|
||||
if (node -> right) { node += node -> right; continue; } \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
node -> right = symbol_ - node; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
count_ += node -> count; \
|
||||
under_ += node -> under - node -> count; \
|
||||
node -> under += update; \
|
||||
node -> count += update; \
|
||||
symbol_ = node; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
static const ENetSymbol emptyContext = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
#define ENET_CONTEXT_WALK(context, body) \
|
||||
{ \
|
||||
const ENetSymbol * node = (context) + (context) -> symbols; \
|
||||
const ENetSymbol * stack [256]; \
|
||||
size_t stackSize = 0; \
|
||||
while (node -> left) \
|
||||
{ \
|
||||
stack [stackSize ++] = node; \
|
||||
node += node -> left; \
|
||||
} \
|
||||
for (;;) \
|
||||
{ \
|
||||
body; \
|
||||
if (node -> right) \
|
||||
{ \
|
||||
node += node -> right; \
|
||||
while (node -> left) \
|
||||
{ \
|
||||
stack [stackSize ++] = node; \
|
||||
node += node -> left; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
if (stackSize <= 0) \
|
||||
break; \
|
||||
else \
|
||||
node = stack [-- stackSize]; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \
|
||||
ENET_CONTEXT_WALK(context, { \
|
||||
if (node -> value != value_) \
|
||||
{ \
|
||||
enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \
|
||||
if (node -> value < value_) \
|
||||
under -= parentCount; \
|
||||
total -= parentCount; \
|
||||
} \
|
||||
})
|
||||
#endif
|
||||
|
||||
size_t
|
||||
enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit)
|
||||
{
|
||||
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
|
||||
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
|
||||
const enet_uint8 * inData, * inEnd;
|
||||
enet_uint32 encodeLow = 0, encodeRange = ~0;
|
||||
ENetSymbol * root;
|
||||
enet_uint16 predicted = 0;
|
||||
size_t order = 0, nextSymbol = 0;
|
||||
|
||||
if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0)
|
||||
return 0;
|
||||
|
||||
inData = (const enet_uint8 *) inBuffers -> data;
|
||||
inEnd = & inData [inBuffers -> dataLength];
|
||||
inBuffers ++;
|
||||
inBufferCount --;
|
||||
|
||||
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ENetSymbol * subcontext, * symbol;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
const ENetSymbol * childContext = & emptyContext;
|
||||
#endif
|
||||
enet_uint8 value;
|
||||
enet_uint16 count, under, * parent = & predicted, total;
|
||||
if (inData >= inEnd)
|
||||
{
|
||||
if (inBufferCount <= 0)
|
||||
break;
|
||||
inData = (const enet_uint8 *) inBuffers -> data;
|
||||
inEnd = & inData [inBuffers -> dataLength];
|
||||
inBuffers ++;
|
||||
inBufferCount --;
|
||||
}
|
||||
value = * inData ++;
|
||||
|
||||
for (subcontext = & rangeCoder -> symbols [predicted];
|
||||
subcontext != root;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
childContext = subcontext,
|
||||
#endif
|
||||
subcontext = & rangeCoder -> symbols [subcontext -> parent])
|
||||
{
|
||||
ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
|
||||
* parent = symbol - rangeCoder -> symbols;
|
||||
parent = & symbol -> parent;
|
||||
total = subcontext -> total;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
|
||||
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0);
|
||||
#endif
|
||||
if (count > 0)
|
||||
{
|
||||
ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, total);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (subcontext -> escapes > 0 && subcontext -> escapes < total)
|
||||
ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, total);
|
||||
subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
|
||||
subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
|
||||
}
|
||||
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
|
||||
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
|
||||
ENET_CONTEXT_RESCALE (subcontext, 0);
|
||||
if (count > 0) goto nextInput;
|
||||
}
|
||||
|
||||
ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
* parent = symbol - rangeCoder -> symbols;
|
||||
parent = & symbol -> parent;
|
||||
total = root -> total;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
|
||||
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
#endif
|
||||
ENET_RANGE_CODER_ENCODE (root -> escapes + under, count, total);
|
||||
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
|
||||
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
|
||||
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
|
||||
nextInput:
|
||||
if (order >= ENET_SUBCONTEXT_ORDER)
|
||||
predicted = rangeCoder -> symbols [predicted].parent;
|
||||
else
|
||||
order ++;
|
||||
ENET_RANGE_CODER_FREE_SYMBOLS;
|
||||
}
|
||||
|
||||
ENET_RANGE_CODER_FLUSH;
|
||||
|
||||
return (size_t) (outData - outStart);
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_SEED \
|
||||
{ \
|
||||
if (inData < inEnd) decodeCode |= * inData ++ << 24; \
|
||||
if (inData < inEnd) decodeCode |= * inData ++ << 16; \
|
||||
if (inData < inEnd) decodeCode |= * inData ++ << 8; \
|
||||
if (inData < inEnd) decodeCode |= * inData ++; \
|
||||
}
|
||||
|
||||
#define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total)))
|
||||
|
||||
#define ENET_RANGE_CODER_DECODE(under, count, total) \
|
||||
{ \
|
||||
decodeLow += (under) * decodeRange; \
|
||||
decodeRange *= (count); \
|
||||
for (;;) \
|
||||
{ \
|
||||
if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \
|
||||
{ \
|
||||
if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
|
||||
decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
|
||||
} \
|
||||
decodeCode <<= 8; \
|
||||
if (inData < inEnd) \
|
||||
decodeCode |= * inData ++; \
|
||||
decodeRange <<= 8; \
|
||||
decodeLow <<= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \
|
||||
{ \
|
||||
under_ = 0; \
|
||||
count_ = minimum; \
|
||||
if (! (context) -> symbols) \
|
||||
{ \
|
||||
createRoot; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ENetSymbol * node = (context) + (context) -> symbols; \
|
||||
for (;;) \
|
||||
{ \
|
||||
enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \
|
||||
visitNode; \
|
||||
if (code >= after) \
|
||||
{ \
|
||||
under_ += node -> under; \
|
||||
if (node -> right) { node += node -> right; continue; } \
|
||||
createRight; \
|
||||
} \
|
||||
else \
|
||||
if (code < after - before) \
|
||||
{ \
|
||||
node -> under += update; \
|
||||
if (node -> left) { node += node -> left; continue; } \
|
||||
createLeft; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
value_ = node -> value; \
|
||||
count_ += node -> count; \
|
||||
under_ = after - before; \
|
||||
node -> under += update; \
|
||||
node -> count += update; \
|
||||
symbol_ = node; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
|
||||
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0)
|
||||
|
||||
#define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
|
||||
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \
|
||||
{ \
|
||||
value_ = code / minimum; \
|
||||
under_ = code - code%minimum; \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
(context) -> symbols = symbol_ - (context); \
|
||||
}, \
|
||||
exclude (node -> value, after, before), \
|
||||
{ \
|
||||
value_ = node->value + 1 + (code - after)/minimum; \
|
||||
under_ = code - (code - after)%minimum; \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
node -> right = symbol_ - node; \
|
||||
}, \
|
||||
{ \
|
||||
value_ = node->value - 1 - (after - before - code - 1)/minimum; \
|
||||
under_ = code - (after - before - code - 1)%minimum; \
|
||||
ENET_SYMBOL_CREATE (symbol_, value_, update); \
|
||||
node -> left = symbol_ - node; \
|
||||
}) \
|
||||
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
typedef struct _ENetExclude
|
||||
{
|
||||
enet_uint8 value;
|
||||
enet_uint16 under;
|
||||
} ENetExclude;
|
||||
|
||||
#define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \
|
||||
{ \
|
||||
enet_uint16 under = 0; \
|
||||
nextExclude = excludes; \
|
||||
ENET_CONTEXT_WALK (context, { \
|
||||
under += rangeCoder -> symbols [node -> parent].count + minimum; \
|
||||
nextExclude -> value = node -> value; \
|
||||
nextExclude -> under = under; \
|
||||
nextExclude ++; \
|
||||
}); \
|
||||
total -= under; \
|
||||
}
|
||||
|
||||
#define ENET_CONTEXT_EXCLUDED(value_, after, before) \
|
||||
{ \
|
||||
size_t low = 0, high = nextExclude - excludes; \
|
||||
for(;;) \
|
||||
{ \
|
||||
size_t mid = (low + high) >> 1; \
|
||||
const ENetExclude * exclude = & excludes [mid]; \
|
||||
if (value_ < exclude -> value) \
|
||||
{ \
|
||||
if (low + 1 < high) \
|
||||
{ \
|
||||
high = mid; \
|
||||
continue; \
|
||||
} \
|
||||
if (exclude > excludes) \
|
||||
after -= exclude [-1].under; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (value_ > exclude -> value) \
|
||||
{ \
|
||||
if (low + 1 < high) \
|
||||
{ \
|
||||
low = mid; \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
before = 0; \
|
||||
after -= exclude -> under; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before)
|
||||
|
||||
size_t
|
||||
enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit)
|
||||
{
|
||||
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
|
||||
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
|
||||
const enet_uint8 * inEnd = & inData [inLimit];
|
||||
enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0;
|
||||
ENetSymbol * root;
|
||||
enet_uint16 predicted = 0;
|
||||
size_t order = 0, nextSymbol = 0;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
ENetExclude excludes [256];
|
||||
ENetExclude * nextExclude = excludes;
|
||||
#endif
|
||||
|
||||
if (rangeCoder == NULL || inLimit <= 0)
|
||||
return 0;
|
||||
|
||||
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
|
||||
ENET_RANGE_CODER_SEED;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ENetSymbol * subcontext, * symbol, * patch;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
const ENetSymbol * childContext = & emptyContext;
|
||||
#endif
|
||||
enet_uint8 value = 0;
|
||||
enet_uint16 code, under, count, bottom, * parent = & predicted, total;
|
||||
|
||||
for (subcontext = & rangeCoder -> symbols [predicted];
|
||||
subcontext != root;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
childContext = subcontext,
|
||||
#endif
|
||||
subcontext = & rangeCoder -> symbols [subcontext -> parent])
|
||||
{
|
||||
if (subcontext -> escapes <= 0)
|
||||
continue;
|
||||
total = subcontext -> total;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > 0)
|
||||
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0);
|
||||
#endif
|
||||
if (subcontext -> escapes >= total)
|
||||
continue;
|
||||
code = ENET_RANGE_CODER_READ (total);
|
||||
if (code < subcontext -> escapes)
|
||||
{
|
||||
ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, total);
|
||||
continue;
|
||||
}
|
||||
code -= subcontext -> escapes;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > 0)
|
||||
{
|
||||
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED);
|
||||
}
|
||||
bottom = symbol - rangeCoder -> symbols;
|
||||
ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, total);
|
||||
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
|
||||
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
|
||||
ENET_CONTEXT_RESCALE (subcontext, 0);
|
||||
goto patchContexts;
|
||||
}
|
||||
|
||||
total = root -> total;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > 0)
|
||||
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
#endif
|
||||
code = ENET_RANGE_CODER_READ (total);
|
||||
if (code < root -> escapes)
|
||||
{
|
||||
ENET_RANGE_CODER_DECODE (0, root -> escapes, total);
|
||||
break;
|
||||
}
|
||||
code -= root -> escapes;
|
||||
#ifdef ENET_CONTEXT_EXCLUSION
|
||||
if (childContext -> total > 0)
|
||||
{
|
||||
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_NOT_EXCLUDED);
|
||||
}
|
||||
bottom = symbol - rangeCoder -> symbols;
|
||||
ENET_RANGE_CODER_DECODE (root -> escapes + under, count, total);
|
||||
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
|
||||
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
|
||||
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
|
||||
|
||||
patchContexts:
|
||||
for (patch = & rangeCoder -> symbols [predicted];
|
||||
patch != subcontext;
|
||||
patch = & rangeCoder -> symbols [patch -> parent])
|
||||
{
|
||||
ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
|
||||
* parent = symbol - rangeCoder -> symbols;
|
||||
parent = & symbol -> parent;
|
||||
if (count <= 0)
|
||||
{
|
||||
patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
|
||||
patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
|
||||
}
|
||||
patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
|
||||
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
|
||||
ENET_CONTEXT_RESCALE (patch, 0);
|
||||
}
|
||||
* parent = bottom;
|
||||
|
||||
ENET_RANGE_CODER_OUTPUT (value);
|
||||
|
||||
if (order >= ENET_SUBCONTEXT_ORDER)
|
||||
predicted = rangeCoder -> symbols [predicted].parent;
|
||||
else
|
||||
order ++;
|
||||
ENET_RANGE_CODER_FREE_SYMBOLS;
|
||||
}
|
||||
|
||||
return (size_t) (outData - outStart);
|
||||
}
|
||||
|
||||
/** @defgroup host ENet host functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/** Sets the packet compressor the host should use to the default range coder.
|
||||
@param host host to enable the range coder for
|
||||
@returns 0 on success, < 0 on failure
|
||||
*/
|
||||
int
|
||||
enet_host_compress_with_range_coder (ENetHost * host)
|
||||
{
|
||||
ENetCompressor compressor;
|
||||
memset (& compressor, 0, sizeof (compressor));
|
||||
compressor.context = enet_range_coder_create();
|
||||
if (compressor.context == NULL)
|
||||
return -1;
|
||||
compressor.compress = enet_range_coder_compress;
|
||||
compressor.decompress = enet_range_coder_decompress;
|
||||
compressor.destroy = enet_range_coder_destroy;
|
||||
enet_host_compress (host, & compressor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
28
externals/enet/configure.ac
vendored
Executable file
28
externals/enet/configure.ac
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
AC_INIT([libenet], [1.3.13])
|
||||
AC_CONFIG_SRCDIR([include/enet/enet.h])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAS_GETADDRINFO)])
|
||||
AC_CHECK_FUNC(getnameinfo, [AC_DEFINE(HAS_GETNAMEINFO)])
|
||||
AC_CHECK_FUNC(gethostbyaddr_r, [AC_DEFINE(HAS_GETHOSTBYADDR_R)])
|
||||
AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAS_GETHOSTBYNAME_R)])
|
||||
AC_CHECK_FUNC(poll, [AC_DEFINE(HAS_POLL)])
|
||||
AC_CHECK_FUNC(fcntl, [AC_DEFINE(HAS_FCNTL)])
|
||||
AC_CHECK_FUNC(inet_pton, [AC_DEFINE(HAS_INET_PTON)])
|
||||
AC_CHECK_FUNC(inet_ntop, [AC_DEFINE(HAS_INET_NTOP)])
|
||||
|
||||
AC_CHECK_MEMBER(struct msghdr.msg_flags, [AC_DEFINE(HAS_MSGHDR_FLAGS)], , [#include <sys/socket.h>])
|
||||
|
||||
AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], ,
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
)
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
libenet.pc])
|
||||
AC_OUTPUT
|
24
externals/enet/docs/FAQ.dox
vendored
Executable file
24
externals/enet/docs/FAQ.dox
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
@page FAQ Frequently Answered Questions
|
||||
|
||||
@section Q1 Is ENet thread-safe?
|
||||
|
||||
ENet does not use any significant global variables, the vast majority
|
||||
of state is encapsulated in the ENetHost structure. As such, as long
|
||||
as the application guards access to this structure, then ENet should
|
||||
operate fine in a multi-threaded environment.
|
||||
|
||||
@section Q2 Isn't ENet just re-inventing TCP?! What's the point?
|
||||
|
||||
In a perfect world, that would be true. But as many have found, using
|
||||
TCP either in lieu of or in conjunction with UDP can lead to all kinds
|
||||
of nightmares. TCP is a good, solid protocol, however it simply isn't
|
||||
up to the task of real-time games. Too much of TCP's implementation
|
||||
dictates a policy that isn't practical for games. If you want to use
|
||||
TCP, then do so -- this library is for people that either don't want
|
||||
to use TCP or have tried and ended up being discouraged with the
|
||||
performance.
|
||||
|
||||
*/
|
||||
|
||||
|
126
externals/enet/docs/design.dox
vendored
Executable file
126
externals/enet/docs/design.dox
vendored
Executable file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
@page Features Features and Architecture
|
||||
|
||||
ENet evolved specifically as a UDP networking layer for the
|
||||
multiplayer first person shooter Cube. Cube necessitated low latency
|
||||
communication with data sent out very frequently, so TCP was an
|
||||
unsuitable choice due to its high latency and stream orientation. UDP,
|
||||
however, lacks many sometimes necessary features from TCP such as
|
||||
reliability, sequencing, unrestricted packet sizes, and connection
|
||||
management. So UDP by itself was not suitable as a network protocol
|
||||
either. No suitable freely available networking libraries existed at
|
||||
the time of ENet's creation to fill this niche.
|
||||
|
||||
UDP and TCP could have been used together in Cube to benefit somewhat
|
||||
from both of their features, however, the resulting combinations of
|
||||
protocols still leaves much to be desired. TCP lacks multiple streams
|
||||
of communication without resorting to opening many sockets and
|
||||
complicates delineation of packets due to its buffering behavior. UDP
|
||||
lacks sequencing, connection management, management of bandwidth
|
||||
resources, and imposes limitations on the size of packets. A
|
||||
significant investment is required to integrate these two protocols,
|
||||
and the end result is worse off in features and performance than the
|
||||
uniform protocol presented by ENet.
|
||||
|
||||
ENet thus attempts to address these issues and provide a single,
|
||||
uniform protocol layered over UDP to the developer with the best
|
||||
features of UDP and TCP as well as some useful features neither
|
||||
provide, with a much cleaner integration than any resulting from a
|
||||
mixture of UDP and TCP.
|
||||
|
||||
@section CM Connection Management
|
||||
|
||||
ENet provides a simple connection interface over which to communicate
|
||||
with a foreign host. The liveness of the connection is actively
|
||||
monitored by pinging the foreign host at frequent intervals, and also
|
||||
monitors the network conditions from the local host to the foreign
|
||||
host such as the mean round trip time and packet loss in this fashion.
|
||||
|
||||
@section Sequencing Sequencing
|
||||
|
||||
Rather than a single byte stream that complicates the delineation of
|
||||
packets, ENet presents connections as multiple, properly sequenced
|
||||
packet streams that simplify the transfer of various types of data.
|
||||
|
||||
ENet provides sequencing for all packets by assigning to each sent
|
||||
packet a sequence number that is incremented as packets are sent. ENet
|
||||
guarantees that no packet with a higher sequence number will be
|
||||
delivered before a packet with a lower sequence number, thus ensuring
|
||||
packets are delivered exactly in the order they are sent.
|
||||
|
||||
For unreliable packets, ENet will simply discard the lower sequence
|
||||
number packet if a packet with a higher sequence number has already
|
||||
been delivered. This allows the packets to be dispatched immediately
|
||||
as they arrive, and reduce latency of unreliable packets to an
|
||||
absolute minimum. For reliable packets, if a higher sequence number
|
||||
packet arrives, but the preceding packets in the sequence have not yet
|
||||
arrived, ENet will stall delivery of the higher sequence number
|
||||
packets until its predecessors have arrived.
|
||||
|
||||
@section Channels Channels
|
||||
|
||||
Since ENet will stall delivery of reliable packets to ensure proper
|
||||
sequencing, and consequently any packets of higher sequence number
|
||||
whether reliable or unreliable, in the event the reliable packet's
|
||||
predecessors have not yet arrived, this can introduce latency into the
|
||||
delivery of other packets which may not need to be as strictly ordered
|
||||
with respect to the packet that stalled their delivery.
|
||||
|
||||
To combat this latency and reduce the ordering restrictions on
|
||||
packets, ENet provides multiple channels of communication over a given
|
||||
connection. Each channel is independently sequenced, and so the
|
||||
delivery status of a packet in one channel will not stall the delivery
|
||||
of other packets in another channel.
|
||||
|
||||
@section Reliability Reliability
|
||||
|
||||
ENet provides optional reliability of packet delivery by ensuring the
|
||||
foreign host acknowledges receipt of all reliable packets. ENet will
|
||||
attempt to resend the packet up to a reasonable amount of times, if no
|
||||
acknowledgement of the packet's receipt happens within a specified
|
||||
timeout. Retry timeouts are progressive and become more lenient with
|
||||
every failed attempt to allow for temporary turbulence in network
|
||||
conditions.
|
||||
|
||||
@section FaR Fragmentation and Reassembly
|
||||
|
||||
ENet will send and deliver packets regardless of size. Large packets
|
||||
are fragmented into many smaller packets of suitable size, and
|
||||
reassembled on the foreign host to recover the original packet for
|
||||
delivery. The process is entirely transparent to the developer.
|
||||
|
||||
@section Aggregation Aggregation
|
||||
|
||||
ENet aggregates all protocol commands, including acknowledgements and
|
||||
packet transfer, into larger protocol packets to ensure the proper
|
||||
utilization of the connection and to limit the opportunities for
|
||||
packet loss that might otherwise result in further delivery latency.
|
||||
|
||||
@section Adaptability Adaptability
|
||||
|
||||
ENet provides an in-flight data window for reliable packets to ensure
|
||||
connections are not overwhelmed by volumes of packets. It also
|
||||
provides a static bandwidth allocation mechanism to ensure the total
|
||||
volume of packets sent and received to a host don't exceed the host's
|
||||
capabilities. Further, ENet also provides a dynamic throttle that
|
||||
responds to deviations from normal network connections to rectify
|
||||
various types of network congestion by further limiting the volume of
|
||||
packets sent.
|
||||
|
||||
@section Portability Portability
|
||||
|
||||
ENet works on Windows and any other Unix or Unix-like platform
|
||||
providing a BSD sockets interface. The library has a small and stable
|
||||
code base that can easily be extended to support other platforms and
|
||||
integrates easily. ENet makes no assumptions about the underlying
|
||||
platform's endianess or word size.
|
||||
|
||||
@section Freedom Freedom
|
||||
|
||||
ENet demands no royalties and doesn't carry a viral license that would
|
||||
restrict you in how you might use it in your programs. ENet is
|
||||
licensed under a short-and-sweet MIT-style license, which gives you
|
||||
the freedom to do anything you want with it (well, almost anything).
|
||||
|
||||
*/
|
||||
|
63
externals/enet/docs/install.dox
vendored
Executable file
63
externals/enet/docs/install.dox
vendored
Executable file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
@page Installation Installation
|
||||
|
||||
ENet should be trivially simple to integrate with most applications.
|
||||
First, make sure you download the latest source distribution at @ref Downloads.
|
||||
|
||||
@section Unix Unix-like Operating Systems
|
||||
|
||||
If you are using an ENet release, then you should simply be able to build it
|
||||
by doing the following:
|
||||
|
||||
./configure && make && make install
|
||||
|
||||
If you obtained the package from github, you must have automake and autoconf
|
||||
available to generate the build system first by doing the following command
|
||||
before using the above mentioned build procedure:
|
||||
|
||||
autoreconf -vfi
|
||||
|
||||
|
||||
@subsection SolarisBSD Solaris and BSD
|
||||
|
||||
When building ENet under Solaris, you must specify the -lsocket and
|
||||
-lnsl parameters to your compiler to ensure that the sockets library
|
||||
is linked in.
|
||||
|
||||
@section Windows Microsoft Windows
|
||||
|
||||
You may simply use the included "enet.lib" or "enet64.lib" static libraries.
|
||||
However, if you wish to build the library yourself, then the following
|
||||
instructions apply:
|
||||
|
||||
There is an included MSVC 6 project (enet.dsp) which you may use to
|
||||
build a suitable library file. Alternatively, you may simply drag all
|
||||
the ENet source files into your main project.
|
||||
|
||||
You will have to link to the Winsock2 libraries, so make sure to add
|
||||
ws2_32.lib and winmm.lib to your library list (Project Settings | Link |
|
||||
Object/library modules).
|
||||
|
||||
@subsection enet.dsp Building with the included enet.dsp
|
||||
|
||||
Load the included enet.dsp. MSVC may ask you to convert it if you
|
||||
are on a newer version of MSVC - just allow the conversion and save
|
||||
the resulting project as "enet" or similar. After you build this
|
||||
project, it will output an "enet.lib" file to either the "Debug/"
|
||||
or "Release/" directory, depending on which configuration you have
|
||||
selected to build. By default, it should produce "Debug/enet.lib".
|
||||
|
||||
You may then copy the resulting "enet.lib" file and the header files
|
||||
found in the "include/" directory to your other projects and add it to
|
||||
their library lists. Make sure to also link against "ws2_32.lib" and
|
||||
"winmm.lib" as described above.
|
||||
|
||||
@subsection DLL DLL
|
||||
|
||||
If you wish to build ENet as a DLL you must first define ENET_DLL
|
||||
within the project (Project Settings | C/C++ | Preprocessor |
|
||||
Preprocessor definitions) or, more invasively, simply define ENET_DLL
|
||||
at the top of enet.h.
|
||||
|
||||
*/
|
||||
|
26
externals/enet/docs/license.dox
vendored
Executable file
26
externals/enet/docs/license.dox
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
@page License License
|
||||
|
||||
Copyright (c) 2002-2016 Lee Salzman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
59
externals/enet/docs/mainpage.dox
vendored
Executable file
59
externals/enet/docs/mainpage.dox
vendored
Executable file
@@ -0,0 +1,59 @@
|
||||
/** @mainpage ENet
|
||||
|
||||
ENet's purpose is to provide a relatively thin, simple and robust
|
||||
network communication layer on top of UDP (User Datagram Protocol).
|
||||
The primary feature it provides is optional reliable, in-order
|
||||
delivery of packets.
|
||||
|
||||
ENet omits certain higher level networking features such as authentication,
|
||||
lobbying, server discovery, encryption, or other similar tasks that are
|
||||
particularly application specific so that the library remains flexible,
|
||||
portable, and easily embeddable.
|
||||
|
||||
@ref Features
|
||||
|
||||
@ref Downloads
|
||||
|
||||
@ref Installation
|
||||
|
||||
@ref Tutorial
|
||||
|
||||
@ref MailingList
|
||||
|
||||
@ref IRCChannel
|
||||
|
||||
@ref FAQ
|
||||
|
||||
@ref License
|
||||
|
||||
<a class="el" href="usergroup0.html">Documentation</a>
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page Downloads Downloads
|
||||
|
||||
You can retrieve the source to ENet by downloading it in either .tar.gz form
|
||||
or accessing the github distribution directly.
|
||||
|
||||
The most recent stable release (1.3.13) can be downloaded <a class="el" href="download/enet-1.3.13.tar.gz">here</a>.
|
||||
The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded <a class="el" href="download/enet-1.2.5.tar.gz">here</a>.
|
||||
|
||||
You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page MailingList Mailing List
|
||||
|
||||
The <a class="el" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">enet-discuss</a> list is for discussion of ENet, including bug reports or feature requests.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page IRCChannel IRC Channel
|
||||
|
||||
Join the \#enet channel on the <a class="el" href="http://freenode.net">freenode IRC network (irc.freenode.net)</a> for real-time discussion about the ENet library.
|
||||
|
||||
*/
|
||||
|
366
externals/enet/docs/tutorial.dox
vendored
Executable file
366
externals/enet/docs/tutorial.dox
vendored
Executable file
@@ -0,0 +1,366 @@
|
||||
/**
|
||||
@page Tutorial Tutorial
|
||||
|
||||
@ref Initialization
|
||||
|
||||
@ref CreateServer
|
||||
|
||||
@ref CreateClient
|
||||
|
||||
@ref ManageHost
|
||||
|
||||
@ref SendingPacket
|
||||
|
||||
@ref Disconnecting
|
||||
|
||||
@ref Connecting
|
||||
|
||||
@section Initialization Initialization
|
||||
|
||||
You should include the file <enet/enet.h> when using ENet. Do not
|
||||
include <enet.h> without the directory prefix, as this may cause
|
||||
file name conflicts on some systems.
|
||||
|
||||
Before using ENet, you must call enet_initialize() to initialize the
|
||||
library. Upon program exit, you should call enet_deinitialize() so
|
||||
that the library may clean up any used resources.
|
||||
|
||||
@code
|
||||
#include <enet/enet.h>
|
||||
|
||||
int
|
||||
main (int argc, char ** argv)
|
||||
{
|
||||
if (enet_initialize () != 0)
|
||||
{
|
||||
fprintf (stderr, "An error occurred while initializing ENet.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
atexit (enet_deinitialize);
|
||||
...
|
||||
...
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
@section CreateServer Creating an ENet server
|
||||
|
||||
Servers in ENet are constructed with enet_host_create(). You must
|
||||
specify an address on which to receive data and new connections, as
|
||||
well as the maximum allowable numbers of connected peers. You may
|
||||
optionally specify the incoming and outgoing bandwidth of the server
|
||||
in bytes per second so that ENet may try to statically manage
|
||||
bandwidth resources among connected peers in addition to its dynamic
|
||||
throttling algorithm; specifying 0 for these two options will cause
|
||||
ENet to rely entirely upon its dynamic throttling algorithm to manage
|
||||
bandwidth.
|
||||
|
||||
When done with a host, the host may be destroyed with
|
||||
enet_host_destroy(). All connected peers to the host will be reset,
|
||||
and the resources used by the host will be freed.
|
||||
|
||||
@code
|
||||
ENetAddress address;
|
||||
ENetHost * server;
|
||||
|
||||
/* Bind the server to the default localhost. */
|
||||
/* A specific host address can be specified by */
|
||||
/* enet_address_set_host (& address, "x.x.x.x"); */
|
||||
|
||||
address.host = ENET_HOST_ANY;
|
||||
/* Bind the server to port 1234. */
|
||||
address.port = 1234;
|
||||
|
||||
server = enet_host_create (& address /* the address to bind the server host to */,
|
||||
32 /* allow up to 32 clients and/or outgoing connections */,
|
||||
2 /* allow up to 2 channels to be used, 0 and 1 */,
|
||||
0 /* assume any amount of incoming bandwidth */,
|
||||
0 /* assume any amount of outgoing bandwidth */);
|
||||
if (server == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"An error occurred while trying to create an ENet server host.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
...
|
||||
...
|
||||
...
|
||||
enet_host_destroy(server);
|
||||
@endcode
|
||||
|
||||
@section CreateClient Creating an ENet client
|
||||
|
||||
Clients in ENet are similarly constructed with enet_host_create() when
|
||||
no address is specified to bind the host to. Bandwidth may be
|
||||
specified for the client host as in the above example. The peer count
|
||||
controls the maximum number of connections to other server hosts that
|
||||
may be simultaneously open.
|
||||
|
||||
@code
|
||||
ENetHost * client;
|
||||
|
||||
client = enet_host_create (NULL /* create a client host */,
|
||||
1 /* only allow 1 outgoing connection */,
|
||||
2 /* allow up 2 channels to be used, 0 and 1 */,
|
||||
57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
|
||||
14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
|
||||
|
||||
if (client == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"An error occurred while trying to create an ENet client host.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
...
|
||||
...
|
||||
...
|
||||
enet_host_destroy(client);
|
||||
@endcode
|
||||
|
||||
@section ManageHost Managing an ENet host
|
||||
|
||||
ENet uses a polled event model to notify the programmer of significant
|
||||
events. ENet hosts are polled for events with enet_host_service(),
|
||||
where an optional timeout value in milliseconds may be specified to
|
||||
control how long ENet will poll; if a timeout of 0 is specified,
|
||||
enet_host_service() will return immediately if there are no events to
|
||||
dispatch. enet_host_service() will return 1 if an event was dispatched
|
||||
within the specified timeout.
|
||||
|
||||
Beware that most processing of the network with the ENet stack is done
|
||||
inside enet_host_service(). Both hosts that make up the sides of a connection
|
||||
must regularly call this function to ensure packets are actually sent and
|
||||
received. A common symptom of not actively calling enet_host_service()
|
||||
on both ends is that one side receives events while the other does not.
|
||||
The best way to schedule this activity to ensure adequate service is, for
|
||||
example, to call enet_host_service() with a 0 timeout (meaning non-blocking)
|
||||
at the beginning of every frame in a game loop.
|
||||
|
||||
Currently there are only four types of significant events in ENet:
|
||||
|
||||
An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred
|
||||
within the specified time limit. enet_host_service() will return 0
|
||||
with this event.
|
||||
|
||||
An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client
|
||||
host has connected to the server host or when an attempt to establish a
|
||||
connection with a foreign host has succeeded. Only the "peer" field of the
|
||||
event structure is valid for this event and contains the newly connected peer.
|
||||
|
||||
An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received
|
||||
from a connected peer. The "peer" field contains the peer the packet was
|
||||
received from, "channelID" is the channel on which the packet was sent, and
|
||||
"packet" is the packet that was sent. The packet contained in the "packet"
|
||||
field must be destroyed with enet_packet_destroy() when you are done
|
||||
inspecting its contents.
|
||||
|
||||
An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer
|
||||
has either explicitly disconnected or timed out. Only the "peer" field of the
|
||||
event structure is valid for this event and contains the peer that
|
||||
disconnected. Only the "data" field of the peer is still valid on a
|
||||
disconnect event and must be explicitly reset.
|
||||
|
||||
@code
|
||||
ENetEvent event;
|
||||
|
||||
/* Wait up to 1000 milliseconds for an event. */
|
||||
while (enet_host_service (client, & event, 1000) > 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
printf ("A new client connected from %x:%u.\n",
|
||||
event.peer -> address.host,
|
||||
event.peer -> address.port);
|
||||
|
||||
/* Store any relevant client information here. */
|
||||
event.peer -> data = "Client information";
|
||||
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
|
||||
event.packet -> dataLength,
|
||||
event.packet -> data,
|
||||
event.peer -> data,
|
||||
event.channelID);
|
||||
|
||||
/* Clean up the packet now that we're done using it. */
|
||||
enet_packet_destroy (event.packet);
|
||||
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
printf ("%s disconnected.\n", event.peer -> data);
|
||||
|
||||
/* Reset the peer's client information. */
|
||||
|
||||
event.peer -> data = NULL;
|
||||
}
|
||||
}
|
||||
...
|
||||
...
|
||||
...
|
||||
@endcode
|
||||
|
||||
@section SendingPacket Sending a packet to an ENet peer
|
||||
|
||||
Packets in ENet are created with enet_packet_create(), where the size
|
||||
of the packet must be specified. Optionally, initial data may be
|
||||
specified to copy into the packet.
|
||||
|
||||
Certain flags may also be supplied to enet_packet_create() to control
|
||||
various packet features:
|
||||
|
||||
ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable
|
||||
delivery. A reliable packet is guaranteed to be delivered, and a
|
||||
number of retry attempts will be made until an acknowledgement is
|
||||
received from the foreign host the packet is sent to. If a certain
|
||||
number of retry attempts is reached without any acknowledgement, ENet
|
||||
will assume the peer has disconnected and forcefully reset the
|
||||
connection. If this flag is not specified, the packet is assumed an
|
||||
unreliable packet, and no retry attempts will be made nor
|
||||
acknowledgements generated.
|
||||
|
||||
A packet may be resized (extended or truncated) with
|
||||
enet_packet_resize().
|
||||
|
||||
A packet is sent to a foreign host with
|
||||
enet_peer_send(). enet_peer_send() accepts a channel id over which to
|
||||
send the packet to a given peer. Once the packet is handed over to
|
||||
ENet with enet_peer_send(), ENet will handle its deallocation and
|
||||
enet_packet_destroy() should not be used upon it.
|
||||
|
||||
One may also use enet_host_broadcast() to send a packet to all
|
||||
connected peers on a given host over a specified channel id, as with
|
||||
enet_peer_send().
|
||||
|
||||
Queued packets will be sent on a call to enet_host_service().
|
||||
Alternatively, enet_host_flush() will send out queued packets without
|
||||
dispatching any events.
|
||||
|
||||
@code
|
||||
/* Create a reliable packet of size 7 containing "packet\0" */
|
||||
ENetPacket * packet = enet_packet_create ("packet",
|
||||
strlen ("packet") + 1,
|
||||
ENET_PACKET_FLAG_RELIABLE);
|
||||
|
||||
/* Extend the packet so and append the string "foo", so it now */
|
||||
/* contains "packetfoo\0" */
|
||||
enet_packet_resize (packet, strlen ("packetfoo") + 1);
|
||||
strcpy (& packet -> data [strlen ("packet")], "foo");
|
||||
|
||||
/* Send the packet to the peer over channel id 0. */
|
||||
/* One could also broadcast the packet by */
|
||||
/* enet_host_broadcast (host, 0, packet); */
|
||||
enet_peer_send (peer, 0, packet);
|
||||
...
|
||||
...
|
||||
...
|
||||
/* One could just use enet_host_service() instead. */
|
||||
enet_host_flush (host);
|
||||
@endcode
|
||||
|
||||
@section Disconnecting Disconnecting an ENet peer
|
||||
|
||||
Peers may be gently disconnected with enet_peer_disconnect(). A
|
||||
disconnect request will be sent to the foreign host, and ENet will
|
||||
wait for an acknowledgement from the foreign host before finally
|
||||
disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be
|
||||
generated once the disconnection succeeds. Normally timeouts apply to
|
||||
the disconnect acknowledgement, and so if no acknowledgement is
|
||||
received after a length of time the peer will be forcefully
|
||||
disconnected.
|
||||
|
||||
enet_peer_reset() will forcefully disconnect a peer. The foreign host
|
||||
will get no notification of a disconnect and will time out on the
|
||||
foreign host. No event is generated.
|
||||
|
||||
@code
|
||||
ENetEvent event;
|
||||
|
||||
enet_peer_disconnect (peer, 0);
|
||||
|
||||
/* Allow up to 3 seconds for the disconnect to succeed
|
||||
* and drop any packets received packets.
|
||||
*/
|
||||
while (enet_host_service (client, & event, 3000) > 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
enet_packet_destroy (event.packet);
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
puts ("Disconnection succeeded.");
|
||||
return;
|
||||
...
|
||||
...
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
/* We've arrived here, so the disconnect attempt didn't */
|
||||
/* succeed yet. Force the connection down. */
|
||||
enet_peer_reset (peer);
|
||||
...
|
||||
...
|
||||
...
|
||||
@endcode
|
||||
|
||||
@section Connecting Connecting to an ENet host
|
||||
|
||||
A connection to a foreign host is initiated with enet_host_connect().
|
||||
It accepts the address of a foreign host to connect to, and the number
|
||||
of channels that should be allocated for communication. If N channels
|
||||
are allocated for use, their channel ids will be numbered 0 through
|
||||
N-1. A peer representing the connection attempt is returned, or NULL
|
||||
if there were no available peers over which to initiate the
|
||||
connection. When the connection attempt succeeds, an event of type
|
||||
ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt
|
||||
times out or otherwise fails, an event of type
|
||||
ENET_EVENT_TYPE_DISCONNECT will be generated.
|
||||
|
||||
@code
|
||||
ENetAddress address;
|
||||
ENetEvent event;
|
||||
ENetPeer *peer;
|
||||
|
||||
/* Connect to some.server.net:1234. */
|
||||
enet_address_set_host (& address, "some.server.net");
|
||||
address.port = 1234;
|
||||
|
||||
/* Initiate the connection, allocating the two channels 0 and 1. */
|
||||
peer = enet_host_connect (client, & address, 2, 0);
|
||||
|
||||
if (peer == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"No available peers for initiating an ENet connection.\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Wait up to 5 seconds for the connection attempt to succeed. */
|
||||
if (enet_host_service (client, & event, 5000) > 0 &&
|
||||
event.type == ENET_EVENT_TYPE_CONNECT)
|
||||
{
|
||||
puts ("Connection to some.server.net:1234 succeeded.");
|
||||
...
|
||||
...
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Either the 5 seconds are up or a disconnect event was */
|
||||
/* received. Reset the peer in the event the 5 seconds */
|
||||
/* had run out without any significant event. */
|
||||
enet_peer_reset (peer);
|
||||
|
||||
puts ("Connection to some.server.net:1234 failed.");
|
||||
}
|
||||
...
|
||||
...
|
||||
...
|
||||
@endcode
|
||||
*/
|
168
externals/enet/enet.dsp
vendored
Executable file
168
externals/enet/enet.dsp
vendored
Executable file
@@ -0,0 +1,168 @@
|
||||
# Microsoft Developer Studio Project File - Name="enet" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=enet - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "enet.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "enet.mak" CFG="enet - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "enet - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "enet - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "enet - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /O2 /I "include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "enet - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /I "include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "enet - Win32 Release"
|
||||
# Name "enet - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\host.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\list.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\callbacks.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\compress.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\packet.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\peer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\protocol.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\unix.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\win32.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\enet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\list.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\callbacks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\protocol.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\time.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\types.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\unix.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\utility.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\include\enet\win32.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
86
externals/enet/enet_dll.cbp
vendored
Executable file
86
externals/enet/enet_dll.cbp
vendored
Executable file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="enet_dll" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin\Debug\libenet" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Debug\" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Option createStaticLib="1" />
|
||||
<Compiler>
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="bin\Release\libenet" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj\Release\" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Option createDefFile="1" />
|
||||
<Option createStaticLib="1" />
|
||||
<Compiler>
|
||||
<Add option="-O2" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-DENET_DLL" />
|
||||
<Add directory="include" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="ws2_32" />
|
||||
<Add library="Winmm" />
|
||||
</Linker>
|
||||
<Unit filename="callbacks.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="compress.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="host.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="include\enet\callbacks.h" />
|
||||
<Unit filename="include\enet\enet.h" />
|
||||
<Unit filename="include\enet\list.h" />
|
||||
<Unit filename="include\enet\protocol.h" />
|
||||
<Unit filename="include\enet\time.h" />
|
||||
<Unit filename="include\enet\types.h" />
|
||||
<Unit filename="include\enet\unix.h" />
|
||||
<Unit filename="include\enet\utility.h" />
|
||||
<Unit filename="include\enet\win32.h" />
|
||||
<Unit filename="list.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="packet.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="peer.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="protocol.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="unix.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="win32.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
492
externals/enet/host.c
vendored
Executable file
492
externals/enet/host.c
vendored
Executable file
@@ -0,0 +1,492 @@
|
||||
/**
|
||||
@file host.c
|
||||
@brief ENet host management functions
|
||||
*/
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include <string.h>
|
||||
#include "enet/enet.h"
|
||||
|
||||
/** @defgroup host ENet host functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/** Creates a host for communicating to peers.
|
||||
|
||||
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
|
||||
@param peerCount the maximum number of peers that should be allocated for the host.
|
||||
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
|
||||
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
|
||||
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
|
||||
|
||||
@returns the host on success and NULL on failure
|
||||
|
||||
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
|
||||
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
|
||||
the window size of a connection which limits the amount of reliable packets that may be in transit
|
||||
at any given time.
|
||||
*/
|
||||
ENetHost *
|
||||
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
||||
{
|
||||
ENetHost * host;
|
||||
ENetPeer * currentPeer;
|
||||
|
||||
if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
|
||||
return NULL;
|
||||
|
||||
host = (ENetHost *) enet_malloc (sizeof (ENetHost));
|
||||
if (host == NULL)
|
||||
return NULL;
|
||||
memset (host, 0, sizeof (ENetHost));
|
||||
|
||||
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
|
||||
if (host -> peers == NULL)
|
||||
{
|
||||
enet_free (host);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
|
||||
|
||||
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
|
||||
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
|
||||
{
|
||||
if (host -> socket != ENET_SOCKET_NULL)
|
||||
enet_socket_destroy (host -> socket);
|
||||
|
||||
enet_free (host -> peers);
|
||||
enet_free (host);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
|
||||
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
|
||||
|
||||
if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
|
||||
host -> address = * address;
|
||||
|
||||
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
||||
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
||||
else
|
||||
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
||||
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
||||
|
||||
host -> randomSeed = (enet_uint32) (size_t) host;
|
||||
host -> randomSeed += enet_host_random_seed ();
|
||||
host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16);
|
||||
host -> channelLimit = channelLimit;
|
||||
host -> incomingBandwidth = incomingBandwidth;
|
||||
host -> outgoingBandwidth = outgoingBandwidth;
|
||||
host -> bandwidthThrottleEpoch = 0;
|
||||
host -> recalculateBandwidthLimits = 0;
|
||||
host -> mtu = ENET_HOST_DEFAULT_MTU;
|
||||
host -> peerCount = peerCount;
|
||||
host -> commandCount = 0;
|
||||
host -> bufferCount = 0;
|
||||
host -> checksum = NULL;
|
||||
host -> receivedAddress.host = ENET_HOST_ANY;
|
||||
host -> receivedAddress.port = 0;
|
||||
host -> receivedData = NULL;
|
||||
host -> receivedDataLength = 0;
|
||||
|
||||
host -> totalSentData = 0;
|
||||
host -> totalSentPackets = 0;
|
||||
host -> totalReceivedData = 0;
|
||||
host -> totalReceivedPackets = 0;
|
||||
|
||||
host -> connectedPeers = 0;
|
||||
host -> bandwidthLimitedPeers = 0;
|
||||
host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID;
|
||||
host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
|
||||
host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
|
||||
|
||||
host -> compressor.context = NULL;
|
||||
host -> compressor.compress = NULL;
|
||||
host -> compressor.decompress = NULL;
|
||||
host -> compressor.destroy = NULL;
|
||||
|
||||
host -> intercept = NULL;
|
||||
|
||||
enet_list_clear (& host -> dispatchQueue);
|
||||
|
||||
for (currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
currentPeer -> host = host;
|
||||
currentPeer -> incomingPeerID = currentPeer - host -> peers;
|
||||
currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF;
|
||||
currentPeer -> data = NULL;
|
||||
|
||||
enet_list_clear (& currentPeer -> acknowledgements);
|
||||
enet_list_clear (& currentPeer -> sentReliableCommands);
|
||||
enet_list_clear (& currentPeer -> sentUnreliableCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingReliableCommands);
|
||||
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
|
||||
enet_list_clear (& currentPeer -> dispatchedCommands);
|
||||
|
||||
enet_peer_reset (currentPeer);
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
/** Destroys the host and all resources associated with it.
|
||||
@param host pointer to the host to destroy
|
||||
*/
|
||||
void
|
||||
enet_host_destroy (ENetHost * host)
|
||||
{
|
||||
ENetPeer * currentPeer;
|
||||
|
||||
if (host == NULL)
|
||||
return;
|
||||
|
||||
enet_socket_destroy (host -> socket);
|
||||
|
||||
for (currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
enet_peer_reset (currentPeer);
|
||||
}
|
||||
|
||||
if (host -> compressor.context != NULL && host -> compressor.destroy)
|
||||
(* host -> compressor.destroy) (host -> compressor.context);
|
||||
|
||||
enet_free (host -> peers);
|
||||
enet_free (host);
|
||||
}
|
||||
|
||||
/** Initiates a connection to a foreign host.
|
||||
@param host host seeking the connection
|
||||
@param address destination for the connection
|
||||
@param channelCount number of channels to allocate
|
||||
@param data user data supplied to the receiving host
|
||||
@returns a peer representing the foreign host on success, NULL on failure
|
||||
@remarks The peer returned will have not completed the connection until enet_host_service()
|
||||
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
|
||||
*/
|
||||
ENetPeer *
|
||||
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data)
|
||||
{
|
||||
ENetPeer * currentPeer;
|
||||
ENetChannel * channel;
|
||||
ENetProtocol command;
|
||||
|
||||
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
||||
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
||||
else
|
||||
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
||||
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
||||
|
||||
for (currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentPeer >= & host -> peers [host -> peerCount])
|
||||
return NULL;
|
||||
|
||||
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
|
||||
if (currentPeer -> channels == NULL)
|
||||
return NULL;
|
||||
currentPeer -> channelCount = channelCount;
|
||||
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
|
||||
currentPeer -> address = * address;
|
||||
currentPeer -> connectID = ++ host -> randomSeed;
|
||||
|
||||
if (host -> outgoingBandwidth == 0)
|
||||
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
|
||||
else
|
||||
currentPeer -> windowSize = (host -> outgoingBandwidth /
|
||||
ENET_PEER_WINDOW_SIZE_SCALE) *
|
||||
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
|
||||
|
||||
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
|
||||
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
|
||||
else
|
||||
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
|
||||
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
|
||||
|
||||
for (channel = currentPeer -> channels;
|
||||
channel < & currentPeer -> channels [channelCount];
|
||||
++ channel)
|
||||
{
|
||||
channel -> outgoingReliableSequenceNumber = 0;
|
||||
channel -> outgoingUnreliableSequenceNumber = 0;
|
||||
channel -> incomingReliableSequenceNumber = 0;
|
||||
channel -> incomingUnreliableSequenceNumber = 0;
|
||||
|
||||
enet_list_clear (& channel -> incomingReliableCommands);
|
||||
enet_list_clear (& channel -> incomingUnreliableCommands);
|
||||
|
||||
channel -> usedReliableWindows = 0;
|
||||
memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
|
||||
}
|
||||
|
||||
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
|
||||
command.header.channelID = 0xFF;
|
||||
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
|
||||
command.connect.incomingSessionID = currentPeer -> incomingSessionID;
|
||||
command.connect.outgoingSessionID = currentPeer -> outgoingSessionID;
|
||||
command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
|
||||
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
|
||||
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
|
||||
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
|
||||
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
|
||||
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
|
||||
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
|
||||
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
|
||||
command.connect.connectID = currentPeer -> connectID;
|
||||
command.connect.data = ENET_HOST_TO_NET_32 (data);
|
||||
|
||||
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
|
||||
|
||||
return currentPeer;
|
||||
}
|
||||
|
||||
/** Queues a packet to be sent to all peers associated with the host.
|
||||
@param host host on which to broadcast the packet
|
||||
@param channelID channel on which to broadcast
|
||||
@param packet packet to broadcast
|
||||
*/
|
||||
void
|
||||
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
|
||||
{
|
||||
ENetPeer * currentPeer;
|
||||
|
||||
for (currentPeer = host -> peers;
|
||||
currentPeer < & host -> peers [host -> peerCount];
|
||||
++ currentPeer)
|
||||
{
|
||||
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
|
||||
continue;
|
||||
|
||||
enet_peer_send (currentPeer, channelID, packet);
|
||||
}
|
||||
|
||||
if (packet -> referenceCount == 0)
|
||||
enet_packet_destroy (packet);
|
||||
}
|
||||
|
||||
/** Sets the packet compressor the host should use to compress and decompress packets.
|
||||
@param host host to enable or disable compression for
|
||||
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
|
||||
*/
|
||||
void
|
||||
enet_host_compress (ENetHost * host, const ENetCompressor * compressor)
|
||||
{
|
||||
if (host -> compressor.context != NULL && host -> compressor.destroy)
|
||||
(* host -> compressor.destroy) (host -> compressor.context);
|
||||
|
||||
if (compressor)
|
||||
host -> compressor = * compressor;
|
||||
else
|
||||
host -> compressor.context = NULL;
|
||||
}
|
||||
|
||||
/** Limits the maximum allowed channels of future incoming connections.
|
||||
@param host host to limit
|
||||
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
|
||||
*/
|
||||
void
|
||||
enet_host_channel_limit (ENetHost * host, size_t channelLimit)
|
||||
{
|
||||
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
|
||||
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
|
||||
else
|
||||
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
|
||||
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
|
||||
|
||||
host -> channelLimit = channelLimit;
|
||||
}
|
||||
|
||||
|
||||
/** Adjusts the bandwidth limits of a host.
|
||||
@param host host to adjust
|
||||
@param incomingBandwidth new incoming bandwidth
|
||||
@param outgoingBandwidth new outgoing bandwidth
|
||||
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
|
||||
specified in enet_host_create().
|
||||
*/
|
||||
void
|
||||
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
|
||||
{
|
||||
host -> incomingBandwidth = incomingBandwidth;
|
||||
host -> outgoingBandwidth = outgoingBandwidth;
|
||||
host -> recalculateBandwidthLimits = 1;
|
||||
}
|
||||
|
||||
void
|
||||
enet_host_bandwidth_throttle (ENetHost * host)
|
||||
{
|
||||
enet_uint32 timeCurrent = enet_time_get (),
|
||||
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
|
||||
peersRemaining = (enet_uint32) host -> connectedPeers,
|
||||
dataTotal = ~0,
|
||||
bandwidth = ~0,
|
||||
throttle = 0,
|
||||
bandwidthLimit = 0;
|
||||
int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0;
|
||||
ENetPeer * peer;
|
||||
ENetProtocol command;
|
||||
|
||||
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
|
||||
return;
|
||||
|
||||
host -> bandwidthThrottleEpoch = timeCurrent;
|
||||
|
||||
if (peersRemaining == 0)
|
||||
return;
|
||||
|
||||
if (host -> outgoingBandwidth != 0)
|
||||
{
|
||||
dataTotal = 0;
|
||||
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
|
||||
|
||||
for (peer = host -> peers;
|
||||
peer < & host -> peers [host -> peerCount];
|
||||
++ peer)
|
||||
{
|
||||
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
|
||||
continue;
|
||||
|
||||
dataTotal += peer -> outgoingDataTotal;
|
||||
}
|
||||
}
|
||||
|
||||
while (peersRemaining > 0 && needsAdjustment != 0)
|
||||
{
|
||||
needsAdjustment = 0;
|
||||
|
||||
if (dataTotal <= bandwidth)
|
||||
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
|
||||
else
|
||||
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
|
||||
|
||||
for (peer = host -> peers;
|
||||
peer < & host -> peers [host -> peerCount];
|
||||
++ peer)
|
||||
{
|
||||
enet_uint32 peerBandwidth;
|
||||
|
||||
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
||||
peer -> incomingBandwidth == 0 ||
|
||||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
|
||||
continue;
|
||||
|
||||
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
|
||||
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
|
||||
continue;
|
||||
|
||||
peer -> packetThrottleLimit = (peerBandwidth *
|
||||
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
|
||||
|
||||
if (peer -> packetThrottleLimit == 0)
|
||||
peer -> packetThrottleLimit = 1;
|
||||
|
||||
if (peer -> packetThrottle > peer -> packetThrottleLimit)
|
||||
peer -> packetThrottle = peer -> packetThrottleLimit;
|
||||
|
||||
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
|
||||
|
||||
peer -> incomingDataTotal = 0;
|
||||
peer -> outgoingDataTotal = 0;
|
||||
|
||||
needsAdjustment = 1;
|
||||
-- peersRemaining;
|
||||
bandwidth -= peerBandwidth;
|
||||
dataTotal -= peerBandwidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (peersRemaining > 0)
|
||||
{
|
||||
if (dataTotal <= bandwidth)
|
||||
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
|
||||
else
|
||||
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
|
||||
|
||||
for (peer = host -> peers;
|
||||
peer < & host -> peers [host -> peerCount];
|
||||
++ peer)
|
||||
{
|
||||
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
||||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
|
||||
continue;
|
||||
|
||||
peer -> packetThrottleLimit = throttle;
|
||||
|
||||
if (peer -> packetThrottle > peer -> packetThrottleLimit)
|
||||
peer -> packetThrottle = peer -> packetThrottleLimit;
|
||||
|
||||
peer -> incomingDataTotal = 0;
|
||||
peer -> outgoingDataTotal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (host -> recalculateBandwidthLimits)
|
||||
{
|
||||
host -> recalculateBandwidthLimits = 0;
|
||||
|
||||
peersRemaining = (enet_uint32) host -> connectedPeers;
|
||||
bandwidth = host -> incomingBandwidth;
|
||||
needsAdjustment = 1;
|
||||
|
||||
if (bandwidth == 0)
|
||||
bandwidthLimit = 0;
|
||||
else
|
||||
while (peersRemaining > 0 && needsAdjustment != 0)
|
||||
{
|
||||
needsAdjustment = 0;
|
||||
bandwidthLimit = bandwidth / peersRemaining;
|
||||
|
||||
for (peer = host -> peers;
|
||||
peer < & host -> peers [host -> peerCount];
|
||||
++ peer)
|
||||
{
|
||||
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
|
||||
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
|
||||
continue;
|
||||
|
||||
if (peer -> outgoingBandwidth > 0 &&
|
||||
peer -> outgoingBandwidth >= bandwidthLimit)
|
||||
continue;
|
||||
|
||||
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
|
||||
|
||||
needsAdjustment = 1;
|
||||
-- peersRemaining;
|
||||
bandwidth -= peer -> outgoingBandwidth;
|
||||
}
|
||||
}
|
||||
|
||||
for (peer = host -> peers;
|
||||
peer < & host -> peers [host -> peerCount];
|
||||
++ peer)
|
||||
{
|
||||
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
|
||||
continue;
|
||||
|
||||
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
|
||||
command.header.channelID = 0xFF;
|
||||
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
|
||||
|
||||
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
|
||||
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
|
||||
else
|
||||
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
|
||||
|
||||
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
27
externals/enet/include/enet/callbacks.h
vendored
Executable file
27
externals/enet/include/enet/callbacks.h
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
@file callbacks.h
|
||||
@brief ENet callbacks
|
||||
*/
|
||||
#ifndef __ENET_CALLBACKS_H__
|
||||
#define __ENET_CALLBACKS_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct _ENetCallbacks
|
||||
{
|
||||
void * (ENET_CALLBACK * malloc) (size_t size);
|
||||
void (ENET_CALLBACK * free) (void * memory);
|
||||
void (ENET_CALLBACK * no_memory) (void);
|
||||
} ENetCallbacks;
|
||||
|
||||
/** @defgroup callbacks ENet internal callbacks
|
||||
@{
|
||||
@ingroup private
|
||||
*/
|
||||
extern void * enet_malloc (size_t);
|
||||
extern void enet_free (void *);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __ENET_CALLBACKS_H__ */
|
||||
|
607
externals/enet/include/enet/enet.h
vendored
Executable file
607
externals/enet/include/enet/enet.h
vendored
Executable file
@@ -0,0 +1,607 @@
|
||||
/**
|
||||
@file enet.h
|
||||
@brief ENet public header file
|
||||
*/
|
||||
#ifndef __ENET_ENET_H__
|
||||
#define __ENET_ENET_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "enet/win32.h"
|
||||
#else
|
||||
#include "enet/unix.h"
|
||||
#endif
|
||||
|
||||
#include "enet/types.h"
|
||||
#include "enet/protocol.h"
|
||||
#include "enet/list.h"
|
||||
#include "enet/callbacks.h"
|
||||
|
||||
#define ENET_VERSION_MAJOR 1
|
||||
#define ENET_VERSION_MINOR 3
|
||||
#define ENET_VERSION_PATCH 13
|
||||
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
|
||||
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
|
||||
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
|
||||
#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF)
|
||||
#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
|
||||
|
||||
typedef enet_uint32 ENetVersion;
|
||||
|
||||
struct _ENetHost;
|
||||
struct _ENetEvent;
|
||||
struct _ENetPacket;
|
||||
|
||||
typedef enum _ENetSocketType
|
||||
{
|
||||
ENET_SOCKET_TYPE_STREAM = 1,
|
||||
ENET_SOCKET_TYPE_DATAGRAM = 2
|
||||
} ENetSocketType;
|
||||
|
||||
typedef enum _ENetSocketWait
|
||||
{
|
||||
ENET_SOCKET_WAIT_NONE = 0,
|
||||
ENET_SOCKET_WAIT_SEND = (1 << 0),
|
||||
ENET_SOCKET_WAIT_RECEIVE = (1 << 1),
|
||||
ENET_SOCKET_WAIT_INTERRUPT = (1 << 2)
|
||||
} ENetSocketWait;
|
||||
|
||||
typedef enum _ENetSocketOption
|
||||
{
|
||||
ENET_SOCKOPT_NONBLOCK = 1,
|
||||
ENET_SOCKOPT_BROADCAST = 2,
|
||||
ENET_SOCKOPT_RCVBUF = 3,
|
||||
ENET_SOCKOPT_SNDBUF = 4,
|
||||
ENET_SOCKOPT_REUSEADDR = 5,
|
||||
ENET_SOCKOPT_RCVTIMEO = 6,
|
||||
ENET_SOCKOPT_SNDTIMEO = 7,
|
||||
ENET_SOCKOPT_ERROR = 8,
|
||||
ENET_SOCKOPT_NODELAY = 9
|
||||
} ENetSocketOption;
|
||||
|
||||
typedef enum _ENetSocketShutdown
|
||||
{
|
||||
ENET_SOCKET_SHUTDOWN_READ = 0,
|
||||
ENET_SOCKET_SHUTDOWN_WRITE = 1,
|
||||
ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
|
||||
} ENetSocketShutdown;
|
||||
|
||||
#define ENET_HOST_ANY 0
|
||||
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
|
||||
#define ENET_PORT_ANY 0
|
||||
|
||||
/**
|
||||
* Portable internet address structure.
|
||||
*
|
||||
* The host must be specified in network byte-order, and the port must be in host
|
||||
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
|
||||
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
|
||||
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
|
||||
* but not for enet_host_create. Once a server responds to a broadcast, the
|
||||
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
|
||||
*/
|
||||
typedef struct _ENetAddress
|
||||
{
|
||||
enet_uint32 host;
|
||||
enet_uint16 port;
|
||||
} ENetAddress;
|
||||
|
||||
/**
|
||||
* Packet flag bit constants.
|
||||
*
|
||||
* The host must be specified in network byte-order, and the port must be in
|
||||
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
|
||||
* default server host.
|
||||
|
||||
@sa ENetPacket
|
||||
*/
|
||||
typedef enum _ENetPacketFlag
|
||||
{
|
||||
/** packet must be received by the target peer and resend attempts should be
|
||||
* made until the packet is delivered */
|
||||
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
|
||||
/** packet will not be sequenced with other packets
|
||||
* not supported for reliable packets
|
||||
*/
|
||||
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
|
||||
/** packet will not allocate data, and user must supply it instead */
|
||||
ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2),
|
||||
/** packet will be fragmented using unreliable (instead of reliable) sends
|
||||
* if it exceeds the MTU */
|
||||
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3),
|
||||
|
||||
/** whether the packet has been sent from all queues it has been entered into */
|
||||
ENET_PACKET_FLAG_SENT = (1<<8)
|
||||
} ENetPacketFlag;
|
||||
|
||||
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
|
||||
|
||||
/**
|
||||
* ENet packet structure.
|
||||
*
|
||||
* An ENet data packet that may be sent to or received from a peer. The shown
|
||||
* fields should only be read and never modified. The data field contains the
|
||||
* allocated data for the packet. The dataLength fields specifies the length
|
||||
* of the allocated data. The flags field is either 0 (specifying no flags),
|
||||
* or a bitwise-or of any combination of the following flags:
|
||||
*
|
||||
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
|
||||
* and resend attempts should be made until the packet is delivered
|
||||
*
|
||||
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
|
||||
* (not supported for reliable packets)
|
||||
*
|
||||
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
|
||||
*
|
||||
* ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable
|
||||
* (instead of reliable) sends if it exceeds the MTU
|
||||
*
|
||||
* ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
|
||||
@sa ENetPacketFlag
|
||||
*/
|
||||
typedef struct _ENetPacket
|
||||
{
|
||||
size_t referenceCount; /**< internal use only */
|
||||
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
|
||||
enet_uint8 * data; /**< allocated data for packet */
|
||||
size_t dataLength; /**< length of data */
|
||||
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
|
||||
void * userData; /**< application private data, may be freely modified */
|
||||
} ENetPacket;
|
||||
|
||||
typedef struct _ENetAcknowledgement
|
||||
{
|
||||
ENetListNode acknowledgementList;
|
||||
enet_uint32 sentTime;
|
||||
ENetProtocol command;
|
||||
} ENetAcknowledgement;
|
||||
|
||||
typedef struct _ENetOutgoingCommand
|
||||
{
|
||||
ENetListNode outgoingCommandList;
|
||||
enet_uint16 reliableSequenceNumber;
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
enet_uint32 sentTime;
|
||||
enet_uint32 roundTripTimeout;
|
||||
enet_uint32 roundTripTimeoutLimit;
|
||||
enet_uint32 fragmentOffset;
|
||||
enet_uint16 fragmentLength;
|
||||
enet_uint16 sendAttempts;
|
||||
ENetProtocol command;
|
||||
ENetPacket * packet;
|
||||
} ENetOutgoingCommand;
|
||||
|
||||
typedef struct _ENetIncomingCommand
|
||||
{
|
||||
ENetListNode incomingCommandList;
|
||||
enet_uint16 reliableSequenceNumber;
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
ENetProtocol command;
|
||||
enet_uint32 fragmentCount;
|
||||
enet_uint32 fragmentsRemaining;
|
||||
enet_uint32 * fragments;
|
||||
ENetPacket * packet;
|
||||
} ENetIncomingCommand;
|
||||
|
||||
typedef enum _ENetPeerState
|
||||
{
|
||||
ENET_PEER_STATE_DISCONNECTED = 0,
|
||||
ENET_PEER_STATE_CONNECTING = 1,
|
||||
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
|
||||
ENET_PEER_STATE_CONNECTION_PENDING = 3,
|
||||
ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4,
|
||||
ENET_PEER_STATE_CONNECTED = 5,
|
||||
ENET_PEER_STATE_DISCONNECT_LATER = 6,
|
||||
ENET_PEER_STATE_DISCONNECTING = 7,
|
||||
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
|
||||
ENET_PEER_STATE_ZOMBIE = 9
|
||||
} ENetPeerState;
|
||||
|
||||
#ifndef ENET_BUFFER_MAXIMUM
|
||||
#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
|
||||
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
|
||||
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
|
||||
ENET_HOST_DEFAULT_MTU = 1400,
|
||||
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
|
||||
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
|
||||
|
||||
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
|
||||
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
|
||||
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
|
||||
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
|
||||
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
|
||||
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
|
||||
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
|
||||
ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
|
||||
ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
|
||||
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
|
||||
ENET_PEER_TIMEOUT_LIMIT = 32,
|
||||
ENET_PEER_TIMEOUT_MINIMUM = 5000,
|
||||
ENET_PEER_TIMEOUT_MAXIMUM = 30000,
|
||||
ENET_PEER_PING_INTERVAL = 500,
|
||||
ENET_PEER_UNSEQUENCED_WINDOWS = 64,
|
||||
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024,
|
||||
ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32,
|
||||
ENET_PEER_RELIABLE_WINDOWS = 16,
|
||||
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000,
|
||||
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
|
||||
};
|
||||
|
||||
typedef struct _ENetChannel
|
||||
{
|
||||
enet_uint16 outgoingReliableSequenceNumber;
|
||||
enet_uint16 outgoingUnreliableSequenceNumber;
|
||||
enet_uint16 usedReliableWindows;
|
||||
enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
|
||||
enet_uint16 incomingReliableSequenceNumber;
|
||||
enet_uint16 incomingUnreliableSequenceNumber;
|
||||
ENetList incomingReliableCommands;
|
||||
ENetList incomingUnreliableCommands;
|
||||
} ENetChannel;
|
||||
|
||||
/**
|
||||
* An ENet peer which data packets may be sent or received from.
|
||||
*
|
||||
* No fields should be modified unless otherwise specified.
|
||||
*/
|
||||
typedef struct _ENetPeer
|
||||
{
|
||||
ENetListNode dispatchList;
|
||||
struct _ENetHost * host;
|
||||
enet_uint16 outgoingPeerID;
|
||||
enet_uint16 incomingPeerID;
|
||||
enet_uint32 connectID;
|
||||
enet_uint8 outgoingSessionID;
|
||||
enet_uint8 incomingSessionID;
|
||||
ENetAddress address; /**< Internet address of the peer */
|
||||
void * data; /**< Application private data, may be freely modified */
|
||||
ENetPeerState state;
|
||||
ENetChannel * channels;
|
||||
size_t channelCount; /**< Number of channels allocated for communication with peer */
|
||||
enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
|
||||
enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
|
||||
enet_uint32 incomingBandwidthThrottleEpoch;
|
||||
enet_uint32 outgoingBandwidthThrottleEpoch;
|
||||
enet_uint32 incomingDataTotal;
|
||||
enet_uint32 outgoingDataTotal;
|
||||
enet_uint32 lastSendTime;
|
||||
enet_uint32 lastReceiveTime;
|
||||
enet_uint32 nextTimeout;
|
||||
enet_uint32 earliestTimeout;
|
||||
enet_uint32 packetLossEpoch;
|
||||
enet_uint32 packetsSent;
|
||||
enet_uint32 packetsLost;
|
||||
enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
|
||||
enet_uint32 packetLossVariance;
|
||||
enet_uint32 packetThrottle;
|
||||
enet_uint32 packetThrottleLimit;
|
||||
enet_uint32 packetThrottleCounter;
|
||||
enet_uint32 packetThrottleEpoch;
|
||||
enet_uint32 packetThrottleAcceleration;
|
||||
enet_uint32 packetThrottleDeceleration;
|
||||
enet_uint32 packetThrottleInterval;
|
||||
enet_uint32 pingInterval;
|
||||
enet_uint32 timeoutLimit;
|
||||
enet_uint32 timeoutMinimum;
|
||||
enet_uint32 timeoutMaximum;
|
||||
enet_uint32 lastRoundTripTime;
|
||||
enet_uint32 lowestRoundTripTime;
|
||||
enet_uint32 lastRoundTripTimeVariance;
|
||||
enet_uint32 highestRoundTripTimeVariance;
|
||||
enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
|
||||
enet_uint32 roundTripTimeVariance;
|
||||
enet_uint32 mtu;
|
||||
enet_uint32 windowSize;
|
||||
enet_uint32 reliableDataInTransit;
|
||||
enet_uint16 outgoingReliableSequenceNumber;
|
||||
ENetList acknowledgements;
|
||||
ENetList sentReliableCommands;
|
||||
ENetList sentUnreliableCommands;
|
||||
ENetList outgoingReliableCommands;
|
||||
ENetList outgoingUnreliableCommands;
|
||||
ENetList dispatchedCommands;
|
||||
int needsDispatch;
|
||||
enet_uint16 incomingUnsequencedGroup;
|
||||
enet_uint16 outgoingUnsequencedGroup;
|
||||
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
|
||||
enet_uint32 eventData;
|
||||
size_t totalWaitingData;
|
||||
} ENetPeer;
|
||||
|
||||
/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
|
||||
*/
|
||||
typedef struct _ENetCompressor
|
||||
{
|
||||
/** Context data for the compressor. Must be non-NULL. */
|
||||
void * context;
|
||||
/** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
|
||||
size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
|
||||
/** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
|
||||
size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
|
||||
/** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
|
||||
void (ENET_CALLBACK * destroy) (void * context);
|
||||
} ENetCompressor;
|
||||
|
||||
/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
|
||||
typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount);
|
||||
|
||||
/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
|
||||
typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event);
|
||||
|
||||
/** An ENet host for communicating with peers.
|
||||
*
|
||||
* No fields should be modified unless otherwise stated.
|
||||
|
||||
@sa enet_host_create()
|
||||
@sa enet_host_destroy()
|
||||
@sa enet_host_connect()
|
||||
@sa enet_host_service()
|
||||
@sa enet_host_flush()
|
||||
@sa enet_host_broadcast()
|
||||
@sa enet_host_compress()
|
||||
@sa enet_host_compress_with_range_coder()
|
||||
@sa enet_host_channel_limit()
|
||||
@sa enet_host_bandwidth_limit()
|
||||
@sa enet_host_bandwidth_throttle()
|
||||
*/
|
||||
typedef struct _ENetHost
|
||||
{
|
||||
ENetSocket socket;
|
||||
ENetAddress address; /**< Internet address of the host */
|
||||
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
|
||||
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
|
||||
enet_uint32 bandwidthThrottleEpoch;
|
||||
enet_uint32 mtu;
|
||||
enet_uint32 randomSeed;
|
||||
int recalculateBandwidthLimits;
|
||||
ENetPeer * peers; /**< array of peers allocated for this host */
|
||||
size_t peerCount; /**< number of peers allocated for this host */
|
||||
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
|
||||
enet_uint32 serviceTime;
|
||||
ENetList dispatchQueue;
|
||||
int continueSending;
|
||||
size_t packetSize;
|
||||
enet_uint16 headerFlags;
|
||||
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
|
||||
size_t commandCount;
|
||||
ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
|
||||
size_t bufferCount;
|
||||
ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
|
||||
ENetCompressor compressor;
|
||||
enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
|
||||
ENetAddress receivedAddress;
|
||||
enet_uint8 * receivedData;
|
||||
size_t receivedDataLength;
|
||||
enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
|
||||
enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
|
||||
enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */
|
||||
enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
|
||||
ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */
|
||||
size_t connectedPeers;
|
||||
size_t bandwidthLimitedPeers;
|
||||
size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
|
||||
size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
|
||||
size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
|
||||
} ENetHost;
|
||||
|
||||
/**
|
||||
* An ENet event type, as specified in @ref ENetEvent.
|
||||
*/
|
||||
typedef enum _ENetEventType
|
||||
{
|
||||
/** no event occurred within the specified time limit */
|
||||
ENET_EVENT_TYPE_NONE = 0,
|
||||
|
||||
/** a connection request initiated by enet_host_connect has completed.
|
||||
* The peer field contains the peer which successfully connected.
|
||||
*/
|
||||
ENET_EVENT_TYPE_CONNECT = 1,
|
||||
|
||||
/** a peer has disconnected. This event is generated on a successful
|
||||
* completion of a disconnect initiated by enet_peer_disconnect, if
|
||||
* a peer has timed out, or if a connection request intialized by
|
||||
* enet_host_connect has timed out. The peer field contains the peer
|
||||
* which disconnected. The data field contains user supplied data
|
||||
* describing the disconnection, or 0, if none is available.
|
||||
*/
|
||||
ENET_EVENT_TYPE_DISCONNECT = 2,
|
||||
|
||||
/** a packet has been received from a peer. The peer field specifies the
|
||||
* peer which sent the packet. The channelID field specifies the channel
|
||||
* number upon which the packet was received. The packet field contains
|
||||
* the packet that was received; this packet must be destroyed with
|
||||
* enet_packet_destroy after use.
|
||||
*/
|
||||
ENET_EVENT_TYPE_RECEIVE = 3
|
||||
} ENetEventType;
|
||||
|
||||
/**
|
||||
* An ENet event as returned by enet_host_service().
|
||||
|
||||
@sa enet_host_service
|
||||
*/
|
||||
typedef struct _ENetEvent
|
||||
{
|
||||
ENetEventType type; /**< type of the event */
|
||||
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
|
||||
enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
|
||||
enet_uint32 data; /**< data associated with the event, if appropriate */
|
||||
ENetPacket * packet; /**< packet associated with the event, if appropriate */
|
||||
} ENetEvent;
|
||||
|
||||
/** @defgroup global ENet global functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
Initializes ENet globally. Must be called prior to using any functions in
|
||||
ENet.
|
||||
@returns 0 on success, < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_initialize (void);
|
||||
|
||||
/**
|
||||
Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
|
||||
|
||||
@param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
|
||||
@param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
|
||||
@returns 0 on success, < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
|
||||
|
||||
/**
|
||||
Shuts down ENet globally. Should be called when a program that has
|
||||
initialized ENet exits.
|
||||
*/
|
||||
ENET_API void enet_deinitialize (void);
|
||||
|
||||
/**
|
||||
Gives the linked version of the ENet library.
|
||||
@returns the version number
|
||||
*/
|
||||
ENET_API ENetVersion enet_linked_version (void);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup private ENet private implementation functions */
|
||||
|
||||
/**
|
||||
Returns the wall-time in milliseconds. Its initial value is unspecified
|
||||
unless otherwise set.
|
||||
*/
|
||||
ENET_API enet_uint32 enet_time_get (void);
|
||||
/**
|
||||
Sets the current wall-time in milliseconds.
|
||||
*/
|
||||
ENET_API void enet_time_set (enet_uint32);
|
||||
|
||||
/** @defgroup socket ENet socket functions
|
||||
@{
|
||||
*/
|
||||
ENET_API ENetSocket enet_socket_create (ENetSocketType);
|
||||
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
|
||||
ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
|
||||
ENET_API int enet_socket_listen (ENetSocket, int);
|
||||
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
|
||||
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
|
||||
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
|
||||
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
|
||||
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
|
||||
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
|
||||
ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown);
|
||||
ENET_API void enet_socket_destroy (ENetSocket);
|
||||
ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @defgroup Address ENet address functions
|
||||
@{
|
||||
*/
|
||||
|
||||
/** Attempts to parse the printable form of the IP address in the parameter hostName
|
||||
and sets the host field in the address parameter if successful.
|
||||
@param address destination to store the parsed IP address
|
||||
@param hostName IP address to parse
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
@returns the address of the given hostName in address on success
|
||||
*/
|
||||
ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
|
||||
|
||||
/** Attempts to resolve the host named by the parameter hostName and sets
|
||||
the host field in the address parameter if successful.
|
||||
@param address destination to store resolved address
|
||||
@param hostName host name to lookup
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
@returns the address of the given hostName in address on success
|
||||
*/
|
||||
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
|
||||
|
||||
/** Gives the printable form of the IP address specified in the address parameter.
|
||||
@param address address printed
|
||||
@param hostName destination for name, must not be NULL
|
||||
@param nameLength maximum length of hostName.
|
||||
@returns the null-terminated name of the host in hostName on success
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
|
||||
|
||||
/** Attempts to do a reverse lookup of the host field in the address parameter.
|
||||
@param address address used for reverse lookup
|
||||
@param hostName destination for name, must not be NULL
|
||||
@param nameLength maximum length of hostName.
|
||||
@returns the null-terminated name of the host in hostName on success
|
||||
@retval 0 on success
|
||||
@retval < 0 on failure
|
||||
*/
|
||||
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
|
||||
|
||||
/** @} */
|
||||
|
||||
ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
|
||||
ENET_API void enet_packet_destroy (ENetPacket *);
|
||||
ENET_API int enet_packet_resize (ENetPacket *, size_t);
|
||||
ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
|
||||
|
||||
ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
|
||||
ENET_API void enet_host_destroy (ENetHost *);
|
||||
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
|
||||
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
|
||||
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
|
||||
ENET_API void enet_host_flush (ENetHost *);
|
||||
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
|
||||
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
|
||||
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
|
||||
ENET_API void enet_host_channel_limit (ENetHost *, size_t);
|
||||
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
|
||||
extern void enet_host_bandwidth_throttle (ENetHost *);
|
||||
extern enet_uint32 enet_host_random_seed (void);
|
||||
|
||||
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
|
||||
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
|
||||
ENET_API void enet_peer_ping (ENetPeer *);
|
||||
ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32);
|
||||
ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
|
||||
ENET_API void enet_peer_reset (ENetPeer *);
|
||||
ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
|
||||
ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
|
||||
ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32);
|
||||
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
|
||||
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
|
||||
extern void enet_peer_reset_queues (ENetPeer *);
|
||||
extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
|
||||
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
|
||||
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
|
||||
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
|
||||
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
|
||||
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
|
||||
extern void enet_peer_on_connect (ENetPeer *);
|
||||
extern void enet_peer_on_disconnect (ENetPeer *);
|
||||
|
||||
ENET_API void * enet_range_coder_create (void);
|
||||
ENET_API void enet_range_coder_destroy (void *);
|
||||
ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
|
||||
ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
|
||||
|
||||
extern size_t enet_protocol_command_size (enet_uint8);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ENET_ENET_H__ */
|
||||
|
43
externals/enet/include/enet/list.h
vendored
Executable file
43
externals/enet/include/enet/list.h
vendored
Executable file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
@file list.h
|
||||
@brief ENet list management
|
||||
*/
|
||||
#ifndef __ENET_LIST_H__
|
||||
#define __ENET_LIST_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct _ENetListNode
|
||||
{
|
||||
struct _ENetListNode * next;
|
||||
struct _ENetListNode * previous;
|
||||
} ENetListNode;
|
||||
|
||||
typedef ENetListNode * ENetListIterator;
|
||||
|
||||
typedef struct _ENetList
|
||||
{
|
||||
ENetListNode sentinel;
|
||||
} ENetList;
|
||||
|
||||
extern void enet_list_clear (ENetList *);
|
||||
|
||||
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
|
||||
extern void * enet_list_remove (ENetListIterator);
|
||||
extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
|
||||
|
||||
extern size_t enet_list_size (ENetList *);
|
||||
|
||||
#define enet_list_begin(list) ((list) -> sentinel.next)
|
||||
#define enet_list_end(list) (& (list) -> sentinel)
|
||||
|
||||
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
|
||||
|
||||
#define enet_list_next(iterator) ((iterator) -> next)
|
||||
#define enet_list_previous(iterator) ((iterator) -> previous)
|
||||
|
||||
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
|
||||
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
|
||||
|
||||
#endif /* __ENET_LIST_H__ */
|
||||
|
198
externals/enet/include/enet/protocol.h
vendored
Executable file
198
externals/enet/include/enet/protocol.h
vendored
Executable file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
@file protocol.h
|
||||
@brief ENet protocol
|
||||
*/
|
||||
#ifndef __ENET_PROTOCOL_H__
|
||||
#define __ENET_PROTOCOL_H__
|
||||
|
||||
#include "enet/types.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ENET_PROTOCOL_MINIMUM_MTU = 576,
|
||||
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
|
||||
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
|
||||
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
|
||||
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
|
||||
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
|
||||
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
|
||||
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
|
||||
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
|
||||
};
|
||||
|
||||
typedef enum _ENetProtocolCommand
|
||||
{
|
||||
ENET_PROTOCOL_COMMAND_NONE = 0,
|
||||
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
|
||||
ENET_PROTOCOL_COMMAND_CONNECT = 2,
|
||||
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
|
||||
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
|
||||
ENET_PROTOCOL_COMMAND_PING = 5,
|
||||
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
|
||||
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
|
||||
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
|
||||
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
|
||||
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
|
||||
ENET_PROTOCOL_COMMAND_COUNT = 13,
|
||||
|
||||
ENET_PROTOCOL_COMMAND_MASK = 0x0F
|
||||
} ENetProtocolCommand;
|
||||
|
||||
typedef enum _ENetProtocolFlag
|
||||
{
|
||||
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
|
||||
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
|
||||
|
||||
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
|
||||
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
|
||||
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
|
||||
|
||||
ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
|
||||
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
|
||||
} ENetProtocolFlag;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#define ENET_PACKED
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define ENET_PACKED __attribute__ ((packed))
|
||||
#else
|
||||
#define ENET_PACKED
|
||||
#endif
|
||||
|
||||
typedef struct _ENetProtocolHeader
|
||||
{
|
||||
enet_uint16 peerID;
|
||||
enet_uint16 sentTime;
|
||||
} ENET_PACKED ENetProtocolHeader;
|
||||
|
||||
typedef struct _ENetProtocolCommandHeader
|
||||
{
|
||||
enet_uint8 command;
|
||||
enet_uint8 channelID;
|
||||
enet_uint16 reliableSequenceNumber;
|
||||
} ENET_PACKED ENetProtocolCommandHeader;
|
||||
|
||||
typedef struct _ENetProtocolAcknowledge
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 receivedReliableSequenceNumber;
|
||||
enet_uint16 receivedSentTime;
|
||||
} ENET_PACKED ENetProtocolAcknowledge;
|
||||
|
||||
typedef struct _ENetProtocolConnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 outgoingPeerID;
|
||||
enet_uint8 incomingSessionID;
|
||||
enet_uint8 outgoingSessionID;
|
||||
enet_uint32 mtu;
|
||||
enet_uint32 windowSize;
|
||||
enet_uint32 channelCount;
|
||||
enet_uint32 incomingBandwidth;
|
||||
enet_uint32 outgoingBandwidth;
|
||||
enet_uint32 packetThrottleInterval;
|
||||
enet_uint32 packetThrottleAcceleration;
|
||||
enet_uint32 packetThrottleDeceleration;
|
||||
enet_uint32 connectID;
|
||||
enet_uint32 data;
|
||||
} ENET_PACKED ENetProtocolConnect;
|
||||
|
||||
typedef struct _ENetProtocolVerifyConnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 outgoingPeerID;
|
||||
enet_uint8 incomingSessionID;
|
||||
enet_uint8 outgoingSessionID;
|
||||
enet_uint32 mtu;
|
||||
enet_uint32 windowSize;
|
||||
enet_uint32 channelCount;
|
||||
enet_uint32 incomingBandwidth;
|
||||
enet_uint32 outgoingBandwidth;
|
||||
enet_uint32 packetThrottleInterval;
|
||||
enet_uint32 packetThrottleAcceleration;
|
||||
enet_uint32 packetThrottleDeceleration;
|
||||
enet_uint32 connectID;
|
||||
} ENET_PACKED ENetProtocolVerifyConnect;
|
||||
|
||||
typedef struct _ENetProtocolBandwidthLimit
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint32 incomingBandwidth;
|
||||
enet_uint32 outgoingBandwidth;
|
||||
} ENET_PACKED ENetProtocolBandwidthLimit;
|
||||
|
||||
typedef struct _ENetProtocolThrottleConfigure
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint32 packetThrottleInterval;
|
||||
enet_uint32 packetThrottleAcceleration;
|
||||
enet_uint32 packetThrottleDeceleration;
|
||||
} ENET_PACKED ENetProtocolThrottleConfigure;
|
||||
|
||||
typedef struct _ENetProtocolDisconnect
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint32 data;
|
||||
} ENET_PACKED ENetProtocolDisconnect;
|
||||
|
||||
typedef struct _ENetProtocolPing
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
} ENET_PACKED ENetProtocolPing;
|
||||
|
||||
typedef struct _ENetProtocolSendReliable
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 dataLength;
|
||||
} ENET_PACKED ENetProtocolSendReliable;
|
||||
|
||||
typedef struct _ENetProtocolSendUnreliable
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 unreliableSequenceNumber;
|
||||
enet_uint16 dataLength;
|
||||
} ENET_PACKED ENetProtocolSendUnreliable;
|
||||
|
||||
typedef struct _ENetProtocolSendUnsequenced
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 unsequencedGroup;
|
||||
enet_uint16 dataLength;
|
||||
} ENET_PACKED ENetProtocolSendUnsequenced;
|
||||
|
||||
typedef struct _ENetProtocolSendFragment
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
enet_uint16 startSequenceNumber;
|
||||
enet_uint16 dataLength;
|
||||
enet_uint32 fragmentCount;
|
||||
enet_uint32 fragmentNumber;
|
||||
enet_uint32 totalLength;
|
||||
enet_uint32 fragmentOffset;
|
||||
} ENET_PACKED ENetProtocolSendFragment;
|
||||
|
||||
typedef union _ENetProtocol
|
||||
{
|
||||
ENetProtocolCommandHeader header;
|
||||
ENetProtocolAcknowledge acknowledge;
|
||||
ENetProtocolConnect connect;
|
||||
ENetProtocolVerifyConnect verifyConnect;
|
||||
ENetProtocolDisconnect disconnect;
|
||||
ENetProtocolPing ping;
|
||||
ENetProtocolSendReliable sendReliable;
|
||||
ENetProtocolSendUnreliable sendUnreliable;
|
||||
ENetProtocolSendUnsequenced sendUnsequenced;
|
||||
ENetProtocolSendFragment sendFragment;
|
||||
ENetProtocolBandwidthLimit bandwidthLimit;
|
||||
ENetProtocolThrottleConfigure throttleConfigure;
|
||||
} ENET_PACKED ENetProtocol;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif /* __ENET_PROTOCOL_H__ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user