Remove O2, add cpprestsdk
This commit is contained in:
parent
7291e4c1ca
commit
8f1f90064c
947 changed files with 173652 additions and 4059 deletions
2
3rdparty/CMakeLists.txt
vendored
2
3rdparty/CMakeLists.txt
vendored
|
@ -1 +1 @@
|
|||
ADD_SUBDIRECTORY(o2)
|
||||
ADD_SUBDIRECTORY(cpprestsdk)
|
||||
|
|
204
3rdparty/cpprestsdk/CMakeLists.txt
vendored
Normal file
204
3rdparty/cpprestsdk/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,204 @@
|
|||
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(WARNINGS)
|
||||
set(ANDROID_STL_FLAGS)
|
||||
|
||||
# Platform (not compiler) specific settings
|
||||
if(IOS)
|
||||
set(IOS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Build_iOS")
|
||||
set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost")
|
||||
set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers")
|
||||
|
||||
set(OPENSSL_FOUND 1)
|
||||
set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include")
|
||||
set(OPENSSL_LIBRARIES
|
||||
"${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a"
|
||||
"${IOS_SOURCE_DIR}/openssl/lib/libssl.a"
|
||||
)
|
||||
|
||||
# The cxx_flags must be reset here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag.
|
||||
set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden")
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
set(BUILD_SAMPLES OFF)
|
||||
option(BUILD_TESTS "Build tests." ON)
|
||||
elseif(ANDROID)
|
||||
set(Boost_COMPILER "-clang")
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
if(ARM)
|
||||
set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android/build")
|
||||
set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android/build/lib")
|
||||
else()
|
||||
set(BOOST_ROOT "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build")
|
||||
set(BOOST_LIBRARYDIR "${CMAKE_BINARY_DIR}/../Boost-for-Android-x86/build/lib")
|
||||
endif()
|
||||
find_host_package(Boost 1.55 EXACT REQUIRED COMPONENTS random system thread filesystem chrono atomic)
|
||||
|
||||
set(OPENSSL_FOUND 1)
|
||||
if(ARM)
|
||||
set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/include")
|
||||
set(OPENSSL_LIBRARIES
|
||||
"${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libssl.a"
|
||||
"${CMAKE_BINARY_DIR}/../openssl/armeabi-v7a/lib/libcrypto.a"
|
||||
)
|
||||
else()
|
||||
set(OPENSSL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/../openssl/x86/include")
|
||||
set(OPENSSL_LIBRARIES
|
||||
"${CMAKE_BINARY_DIR}/../openssl/x86/lib/libssl.a"
|
||||
"${CMAKE_BINARY_DIR}/../openssl/x86/lib/libcrypto.a"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ARM)
|
||||
set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/thumb/libgnustl_static.a")
|
||||
else()
|
||||
set(LIBCXX_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/x86/libgnustl_static.a")
|
||||
endif()
|
||||
# These are used in the shared library case
|
||||
set(ANDROID_STL_FLAGS
|
||||
${LIBCXX_STL}
|
||||
atomic
|
||||
dl
|
||||
gcc
|
||||
c
|
||||
m
|
||||
-nodefaultlibs
|
||||
)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." OFF)
|
||||
set(BUILD_SAMPLES OFF)
|
||||
option(BUILD_TESTS "Build tests." ON)
|
||||
elseif(UNIX) # This includes OSX
|
||||
find_package(Boost REQUIRED COMPONENTS random chrono system thread regex filesystem)
|
||||
find_package(Threads REQUIRED)
|
||||
if(APPLE AND NOT OPENSSL_ROOT_DIR)
|
||||
# Prefer a homebrew version of OpenSSL over the one in /usr/lib
|
||||
file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*)
|
||||
# Prefer the latest (make the latest one first)
|
||||
list(REVERSE OPENSSL_ROOT_DIR)
|
||||
endif()
|
||||
# This should prevent linking against the system provided 0.9.8y
|
||||
set(_OPENSSL_VERSION "")
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." ON)
|
||||
option(BUILD_TESTS "Build tests." OFF)
|
||||
option(BUILD_SAMPLES "Build samples." OFF)
|
||||
option(CASA_INSTALL_HEADERS "Install header files." ON)
|
||||
if(CASA_INSTALL_HEADERS)
|
||||
file(GLOB CASA_HEADERS_CPPREST include/cpprest/*.hpp include/cpprest/*.h include/cpprest/*.dat)
|
||||
install(FILES ${CASA_HEADERS_CPPREST} DESTINATION include/cpprest)
|
||||
file(GLOB CASA_HEADERS_PPLX include/pplx/*.hpp include/pplx/*.h)
|
||||
install(FILES ${CASA_HEADERS_PPLX} DESTINATION include/pplx)
|
||||
file(GLOB CASA_HEADERS_DETAILS include/cpprest/details/*.hpp include/cpprest/details/*.h include/cpprest/details/*.dat)
|
||||
install(FILES ${CASA_HEADERS_DETAILS} DESTINATION include/cpprest/details)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
option(BUILD_SHARED_LIBS "Build shared Libraries." ON)
|
||||
option(BUILD_TESTS "Build tests." ON)
|
||||
option(BUILD_SAMPLES "Build samples." ON)
|
||||
option(Boost_USE_STATIC_LIBS ON)
|
||||
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
# This causes cmake to not link the test libraries separately, but instead hold onto their object files.
|
||||
set(TEST_LIBRARY_TARGET_TYPE OBJECT)
|
||||
set(Casablanca_DEFINITIONS -D_NO_ASYNCRTIMP -D_NO_PPLXIMP CACHE INTERNAL "Definitions for consume casablanca library")
|
||||
else()
|
||||
set(Casablanca_DEFINITIONS "" CACHE INTERNAL "Definitions for consume casablanca library")
|
||||
endif()
|
||||
add_definitions(${Casablanca_DEFINITIONS} -D_WINSOCK_DEPRECATED_NO_WARNINGS -DWIN32)
|
||||
|
||||
find_package(Boost 1.55 REQUIRED COMPONENTS random system thread filesystem chrono atomic)
|
||||
find_package(OpenSSL 1.0 REQUIRED)
|
||||
else()
|
||||
message(FATAL_ERROR "-- Unsupported Build Platform.")
|
||||
endif()
|
||||
|
||||
# Compiler (not platform) specific settings
|
||||
if(ANDROID)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith")
|
||||
include_directories(
|
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include"
|
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include"
|
||||
"${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.8/include/backward"
|
||||
)
|
||||
elseif((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR IOS)
|
||||
message("-- Setting clang options")
|
||||
|
||||
set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls")
|
||||
set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder")
|
||||
set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
message("-- Setting gcc options")
|
||||
|
||||
set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code")
|
||||
|
||||
set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
message("-- Setting msvc options")
|
||||
set(WARNINGS)
|
||||
else()
|
||||
message("-- Unknown compiler, success is doubtful.")
|
||||
message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}")
|
||||
endif()
|
||||
|
||||
# Reconfigure final output directory
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries)
|
||||
|
||||
# These settings can be used by the test targets
|
||||
set(Casablanca_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libs/websocketpp)
|
||||
|
||||
set(Casablanca_LIBRARY ${LIB}cpprest)
|
||||
set(Casablanca_LIBRARIES ${Casablanca_LIBRARY} ${Boost_LIBRARIES} ${Boost_FRAMEWORK})
|
||||
|
||||
# Everything in the project needs access to the casablanca include directories
|
||||
include_directories(${Casablanca_INCLUDE_DIRS})
|
||||
|
||||
# Finally, the tests all use the same style declaration to build themselves, so we use a function
|
||||
function(add_casablanca_test NAME SOURCES_VAR)
|
||||
add_library(${NAME} ${TEST_LIBRARY_TARGET_TYPE} ${${SOURCES_VAR}})
|
||||
message("-- Added test library ${NAME}")
|
||||
if (NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT")
|
||||
target_link_libraries(${NAME}
|
||||
${LIB}httptest_utilities
|
||||
${LIB}common_utilities
|
||||
${LIB}unittestpp
|
||||
${Casablanca_LIBRARIES}
|
||||
${ANDROID_STL_FLAGS}
|
||||
)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
add_test(NAME ${NAME}
|
||||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
COMMAND test_runner lib${NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(BUILD_SAMPLES)
|
||||
add_subdirectory(samples)
|
||||
endif()
|
16
3rdparty/cpprestsdk/dirs.proj
vendored
Normal file
16
3rdparty/cpprestsdk/dirs.proj
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), build.root))\Build\Common.Build.settings" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectFile Include="src\dirs.proj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(BuildTests)'!=''">
|
||||
<ProjectFile Include="tests\dirs.proj" Condition="'$(Platform)'!='ARM' or '$(WindowsSDKDesktopARMSupport)' == 'true'"/>
|
||||
<ProjectFile Include="samples\dirs.proj" Condition="'$(Platform)'!='ARM' or '$(WindowsSDKDesktopARMSupport)' == 'true'"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(TargetsPath)\Common.Build.Traversal.targets" />
|
||||
|
||||
</Project>
|
1199
3rdparty/cpprestsdk/include/cpprest/astreambuf.h
vendored
Normal file
1199
3rdparty/cpprestsdk/include/cpprest/astreambuf.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
593
3rdparty/cpprestsdk/include/cpprest/asyncrt_utils.h
vendored
Normal file
593
3rdparty/cpprestsdk/include/cpprest/asyncrt_utils.h
vendored
Normal file
|
@ -0,0 +1,593 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Various common utilities.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <system_error>
|
||||
#include <random>
|
||||
#include <locale.h>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(_WIN32) || (_MSC_VER >= 1700)
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// Various utilities for string conversions and date and time manipulation.
|
||||
namespace utility
|
||||
{
|
||||
|
||||
// Left over from VS2010 support, remains to avoid breaking.
|
||||
typedef std::chrono::seconds seconds;
|
||||
|
||||
/// Functions for converting to/from std::chrono::seconds to xml string.
|
||||
namespace timespan
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a timespan/interval in seconds to xml duration string as specified by
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl seconds_to_xml_duration(utility::seconds numSecs);
|
||||
|
||||
/// <summary>
|
||||
/// Converts an xml duration to timespan/interval in seconds
|
||||
/// http://www.w3.org/TR/xmlschema-2/#duration
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::seconds __cdecl xml_duration_to_seconds(const utility::string_t ×panString);
|
||||
}
|
||||
|
||||
/// Functions for Unicode string conversions.
|
||||
namespace conversions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a UTF-16 string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="w">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl utf16_to_utf8(const utf16string &w);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a UTF-8 string to a UTF-16
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl utf8_to_utf16(const std::string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a ASCII (us-ascii) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character us-ascii string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl usascii_to_utf16(const std::string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-16 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl latin1_to_utf16(const std::string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Latin1 (iso-8859-1) string to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP utf8string __cdecl latin1_to_utf8(const std::string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(utf16string &&s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const std::string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a platform dependent Unicode string type.
|
||||
/// </summary>
|
||||
/// <param name="s">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A platform dependent string type.</returns>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const utf16string &s);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl to_utf16string(const std::string &value);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-16 from string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A two byte character UTF-16 string.</returns>
|
||||
_ASYNCRTIMP utf16string __cdecl to_utf16string(utf16string value);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A single byte character UTF-8 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl to_utf8string(std::string value);
|
||||
|
||||
/// <summary>
|
||||
/// Converts to a UTF-8 string.
|
||||
/// </summary>
|
||||
/// <param name="value">A two byte character UTF-16 string.</param>
|
||||
/// <returns>A single byte character UTF-8 string.</returns>
|
||||
_ASYNCRTIMP std::string __cdecl to_utf8string(const utf16string &value);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the given byte array into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(const std::vector<unsigned char>& data);
|
||||
|
||||
/// <summary>
|
||||
/// Encode the given 8-byte integer into a base64 string
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_base64(uint64_t data);
|
||||
|
||||
/// <summary>
|
||||
/// Decode the given base64 string to a byte array
|
||||
/// </summary>
|
||||
_ASYNCRTIMP std::vector<unsigned char> __cdecl from_base64(const utility::string_t& str);
|
||||
|
||||
template <typename Source>
|
||||
utility::string_t print_string(const Source &val, const std::locale &loc)
|
||||
{
|
||||
utility::ostringstream_t oss;
|
||||
oss.imbue(loc);
|
||||
oss << val;
|
||||
if (oss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
template <typename Source>
|
||||
utility::string_t print_string(const Source &val)
|
||||
{
|
||||
return print_string(val, std::locale());
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
Target scan_string(const utility::string_t &str, const std::locale &loc)
|
||||
{
|
||||
Target t;
|
||||
utility::istringstream_t iss(str);
|
||||
iss.imbue(loc);
|
||||
iss >> t;
|
||||
if (iss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
template <typename Target>
|
||||
Target scan_string(const utility::string_t &str)
|
||||
{
|
||||
return scan_string<Target>(str, std::locale());
|
||||
}
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Cross platform RAII container for setting thread local locale.
|
||||
/// </summary>
|
||||
class scoped_c_thread_locale
|
||||
{
|
||||
public:
|
||||
_ASYNCRTIMP scoped_c_thread_locale();
|
||||
_ASYNCRTIMP ~scoped_c_thread_locale();
|
||||
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269
|
||||
#ifdef _WIN32
|
||||
typedef _locale_t xplat_locale;
|
||||
#else
|
||||
typedef locale_t xplat_locale;
|
||||
#endif
|
||||
|
||||
static _ASYNCRTIMP xplat_locale __cdecl c_locale();
|
||||
#endif
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
std::string m_prevLocale;
|
||||
int m_prevThreadSetting;
|
||||
#elif !(defined(ANDROID) || defined(__ANDROID__))
|
||||
locale_t m_prevLocale;
|
||||
#endif
|
||||
scoped_c_thread_locale(const scoped_c_thread_locale &);
|
||||
scoped_c_thread_locale & operator=(const scoped_c_thread_locale &);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
inline bool __cdecl is_alnum(char ch)
|
||||
{
|
||||
return (ch >= '0' && ch <= '9')
|
||||
|| (ch >= 'A' && ch <= 'Z')
|
||||
|| (ch >= 'a' && ch <= 'z');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simplistic implementation of make_unique. A better implementation would be based on variadic templates
|
||||
/// and therefore not be compatible with Dev10.
|
||||
/// </summary>
|
||||
template <typename _Type>
|
||||
std::unique_ptr<_Type> make_unique() {
|
||||
return std::unique_ptr<_Type>(new _Type());
|
||||
}
|
||||
|
||||
template <typename _Type, typename _Arg1>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1) {
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1)));
|
||||
}
|
||||
|
||||
template <typename _Type, typename _Arg1, typename _Arg2>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2) {
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2)));
|
||||
}
|
||||
|
||||
template <typename _Type, typename _Arg1, typename _Arg2, typename _Arg3>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3) {
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string comparision.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if the strings are equivalent, false otherwise</returns>
|
||||
inline bool str_icmp(const utility::string_t &left, const utility::string_t &right)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wcsicmp(left.c_str(), right.c_str()) == 0;
|
||||
#else
|
||||
return boost::iequals(left, right);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/// <summary>
|
||||
/// Category error type for Windows OS errors.
|
||||
/// </summary>
|
||||
class windows_category_impl : public std::error_category
|
||||
{
|
||||
public:
|
||||
virtual const char *name() const CPPREST_NOEXCEPT { return "windows"; }
|
||||
|
||||
_ASYNCRTIMP virtual std::string message(int errorCode) const CPPREST_NOEXCEPT;
|
||||
|
||||
_ASYNCRTIMP virtual std::error_condition default_error_condition(int errorCode) const CPPREST_NOEXCEPT;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the windows error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl windows_category();
|
||||
|
||||
#else
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the linux error category.
|
||||
/// </summary>
|
||||
/// </returns>An error category instance.</returns>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl linux_category();
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the one global instance of the current platform's error category.
|
||||
/// <summary>
|
||||
_ASYNCRTIMP const std::error_category & __cdecl platform_category();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of std::system_error from a OS error code.
|
||||
/// </summary>
|
||||
inline std::system_error __cdecl create_system_error(unsigned long errorCode)
|
||||
{
|
||||
std::error_code code((int)errorCode, platform_category());
|
||||
return std::system_error(code, code.message());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a std::error_code from a OS error code.
|
||||
/// </summary>
|
||||
inline std::error_code __cdecl create_error_code(unsigned long errorCode)
|
||||
{
|
||||
return std::error_code((int)errorCode, platform_category());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the corresponding error message from a OS error code.
|
||||
/// </summary>
|
||||
inline utility::string_t __cdecl create_error_message(unsigned long errorCode)
|
||||
{
|
||||
return utility::conversions::to_string_t(create_error_code(errorCode).message());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class datetime
|
||||
{
|
||||
public:
|
||||
typedef uint64_t interval_type;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the supported date and time string formats.
|
||||
/// </summary>
|
||||
enum date_format { RFC_1123, ISO_8601 };
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current UTC time.
|
||||
/// </summary>
|
||||
static _ASYNCRTIMP datetime __cdecl utc_now();
|
||||
|
||||
/// <summary>
|
||||
/// An invalid UTC timestamp value.
|
||||
/// </summary>
|
||||
enum:interval_type { utc_timestamp_invalid = static_cast<interval_type>(-1) };
|
||||
|
||||
/// <summary>
|
||||
/// Returns seconds since Unix/POSIX time epoch at 01-01-1970 00:00:00.
|
||||
/// If time is before epoch, utc_timestamp_invalid is returned.
|
||||
/// </summary>
|
||||
static interval_type utc_timestamp()
|
||||
{
|
||||
const auto seconds = utc_now().to_interval() / _secondTicks;
|
||||
if (seconds >= 11644473600LL)
|
||||
{
|
||||
return seconds - 11644473600LL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return utc_timestamp_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
datetime() : m_interval(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the <c>datetime</c>.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP utility::string_t to_string(date_format format = RFC_1123) const;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the integral time value.
|
||||
/// </summary>
|
||||
interval_type to_interval() const
|
||||
{
|
||||
return m_interval;
|
||||
}
|
||||
|
||||
datetime operator- (interval_type value) const
|
||||
{
|
||||
return datetime(m_interval - value);
|
||||
}
|
||||
|
||||
datetime operator+ (interval_type value) const
|
||||
{
|
||||
return datetime(m_interval + value);
|
||||
}
|
||||
|
||||
bool operator== (datetime dt) const
|
||||
{
|
||||
return m_interval == dt.m_interval;
|
||||
}
|
||||
|
||||
bool operator!= (const datetime& dt) const
|
||||
{
|
||||
return !(*this == dt);
|
||||
}
|
||||
|
||||
static interval_type from_milliseconds(unsigned int milliseconds)
|
||||
{
|
||||
return milliseconds*_msTicks;
|
||||
}
|
||||
|
||||
static interval_type from_seconds(unsigned int seconds)
|
||||
{
|
||||
return seconds*_secondTicks;
|
||||
}
|
||||
|
||||
static interval_type from_minutes(unsigned int minutes)
|
||||
{
|
||||
return minutes*_minuteTicks;
|
||||
}
|
||||
|
||||
static interval_type from_hours(unsigned int hours)
|
||||
{
|
||||
return hours*_hourTicks;
|
||||
}
|
||||
|
||||
static interval_type from_days(unsigned int days)
|
||||
{
|
||||
return days*_dayTicks;
|
||||
}
|
||||
|
||||
bool is_initialized() const
|
||||
{
|
||||
return m_interval != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
friend int operator- (datetime t1, datetime t2);
|
||||
|
||||
static const interval_type _msTicks = static_cast<interval_type>(10000);
|
||||
static const interval_type _secondTicks = 1000*_msTicks;
|
||||
static const interval_type _minuteTicks = 60*_secondTicks;
|
||||
static const interval_type _hourTicks = 60*60*_secondTicks;
|
||||
static const interval_type _dayTicks = 24*60*60*_secondTicks;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// void* to avoid pulling in windows.h
|
||||
static _ASYNCRTIMP bool __cdecl datetime::system_type_to_datetime(/*SYSTEMTIME*/ void* psysTime, uint64_t seconds, datetime * pdt);
|
||||
#else
|
||||
static datetime timeval_to_datetime(const timeval &time);
|
||||
#endif
|
||||
|
||||
// Private constructor. Use static methods to create an instance.
|
||||
datetime(interval_type interval) : m_interval(interval)
|
||||
{
|
||||
}
|
||||
|
||||
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
|
||||
interval_type m_interval;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
// temporary workaround for the fact that
|
||||
// utf16char is not fully supported in GCC
|
||||
class cmp
|
||||
{
|
||||
public:
|
||||
|
||||
static int icmp(std::string left, std::string right)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < left.size(); ++i)
|
||||
{
|
||||
if (i == right.size()) return 1;
|
||||
|
||||
auto l = cmp::tolower(left[i]);
|
||||
auto r = cmp::tolower(right[i]);
|
||||
if (l > r) return 1;
|
||||
if (l < r) return -1;
|
||||
}
|
||||
if (i < right.size()) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
static char tolower(char c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return static_cast<char>(c - 'A' + 'a');
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
inline int operator- (datetime t1, datetime t2)
|
||||
{
|
||||
auto diff = (t1.m_interval - t2.m_interval);
|
||||
|
||||
// Round it down to seconds
|
||||
diff /= 10 * 1000 * 1000;
|
||||
|
||||
return static_cast<int>(diff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nonce string generator class.
|
||||
/// </summary>
|
||||
class nonce_generator
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Define default nonce length.
|
||||
/// </summary>
|
||||
enum { default_length = 32 };
|
||||
|
||||
/// <summary>
|
||||
/// Nonce generator constructor.
|
||||
/// </summary>
|
||||
/// <param name="length">Length of the generated nonce string.</param>
|
||||
nonce_generator(int length=default_length) :
|
||||
m_random(static_cast<unsigned int>(utility::datetime::utc_timestamp())),
|
||||
m_length(length)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a nonce string containing random alphanumeric characters (A-Za-z0-9).
|
||||
/// Length of the generated string is set by length().
|
||||
/// </summary>
|
||||
/// <returns>The generated nonce string.</returns>
|
||||
_ASYNCRTIMP utility::string_t generate();
|
||||
|
||||
/// <summary>
|
||||
/// Get length of generated nonce string.
|
||||
/// </summary>
|
||||
/// <returns>Nonce string length.</returns>
|
||||
int length() const { return m_length; }
|
||||
|
||||
/// <summary>
|
||||
/// Set length of the generated nonce string.
|
||||
/// </summary>
|
||||
/// <param name="length">Lenght of nonce string.</param>
|
||||
void set_length(int length) { m_length = length; }
|
||||
|
||||
private:
|
||||
static const utility::string_t c_allowed_chars;
|
||||
std::mt19937 m_random;
|
||||
int m_length;
|
||||
};
|
||||
|
||||
} // namespace utility;
|
450
3rdparty/cpprestsdk/include/cpprest/base_uri.h
vendored
Normal file
450
3rdparty/cpprestsdk/include/cpprest/base_uri.h
vendored
Normal file
|
@ -0,0 +1,450 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
namespace web {
|
||||
namespace details
|
||||
{
|
||||
struct uri_components
|
||||
{
|
||||
uri_components() : m_path(_XPLATSTR("/")), m_port(-1)
|
||||
{}
|
||||
|
||||
uri_components(const uri_components &other) :
|
||||
m_scheme(other.m_scheme),
|
||||
m_host(other.m_host),
|
||||
m_user_info(other.m_user_info),
|
||||
m_path(other.m_path),
|
||||
m_query(other.m_query),
|
||||
m_fragment(other.m_fragment),
|
||||
m_port(other.m_port)
|
||||
{}
|
||||
|
||||
uri_components & operator=(const uri_components &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_scheme = other.m_scheme;
|
||||
m_host = other.m_host;
|
||||
m_user_info = other.m_user_info;
|
||||
m_path = other.m_path;
|
||||
m_query = other.m_query;
|
||||
m_fragment = other.m_fragment;
|
||||
m_port = other.m_port;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
uri_components(uri_components &&other) CPPREST_NOEXCEPT :
|
||||
m_scheme(std::move(other.m_scheme)),
|
||||
m_host(std::move(other.m_host)),
|
||||
m_user_info(std::move(other.m_user_info)),
|
||||
m_path(std::move(other.m_path)),
|
||||
m_query(std::move(other.m_query)),
|
||||
m_fragment(std::move(other.m_fragment)),
|
||||
m_port(other.m_port)
|
||||
{}
|
||||
|
||||
uri_components & operator=(uri_components &&other) CPPREST_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_scheme = std::move(other.m_scheme);
|
||||
m_host = std::move(other.m_host);
|
||||
m_user_info = std::move(other.m_user_info);
|
||||
m_path = std::move(other.m_path);
|
||||
m_query = std::move(other.m_query);
|
||||
m_fragment = std::move(other.m_fragment);
|
||||
m_port = other.m_port;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ASYNCRTIMP utility::string_t join();
|
||||
|
||||
utility::string_t m_scheme;
|
||||
utility::string_t m_host;
|
||||
utility::string_t m_user_info;
|
||||
utility::string_t m_path;
|
||||
utility::string_t m_query;
|
||||
utility::string_t m_fragment;
|
||||
int m_port;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A single exception type to represent errors in parsing, encoding, and decoding URIs.
|
||||
/// </summary>
|
||||
class uri_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
uri_exception(std::string msg) : m_msg(std::move(msg)) {}
|
||||
|
||||
~uri_exception() CPPREST_NOEXCEPT {}
|
||||
|
||||
const char* what() const CPPREST_NOEXCEPT
|
||||
{
|
||||
return m_msg.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A flexible, protocol independent URI implementation.
|
||||
///
|
||||
/// URI instances are immutable. Querying the various fields on an emtpy URI will return empty strings. Querying
|
||||
/// various diagnostic members on an empty URI will return false.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This implementation accepts both URIs ('http://msn.com/path') and URI relative-references
|
||||
/// ('/path?query#frag').
|
||||
///
|
||||
/// This implementation does not provide any scheme-specific handling -- an example of this
|
||||
/// would be the following: 'http://path1/path'. This is a valid URI, but it's not a valid
|
||||
/// http-uri -- that is, it's syntactically correct but does not conform to the requirements
|
||||
/// of the http scheme (http requires a host).
|
||||
/// We could provide this by allowing a pluggable 'scheme' policy-class, which would provide
|
||||
/// extra capability for validating and canonicalizing a URI according to scheme, and would
|
||||
/// introduce a layer of type-safety for URIs of differing schemes, and thus differing semantics.
|
||||
///
|
||||
/// One issue with implementing a scheme-independent URI facility is that of comparing for equality.
|
||||
/// For instance, these URIs are considered equal 'http://msn.com', 'http://msn.com:80'. That is --
|
||||
/// the 'default' port can be either omitted or explicit. Since we don't have a way to map a scheme
|
||||
/// to it's default port, we don't have a way to know these are equal. This is just one of a class of
|
||||
/// issues with regard to scheme-specific behavior.
|
||||
/// </remarks>
|
||||
class uri
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// The various components of a URI. This enum is used to indicate which
|
||||
/// URI component is being encoded to the encode_uri_component. This allows
|
||||
/// specific encoding to be performed.
|
||||
///
|
||||
/// Scheme and port don't allow '%' so they don't need to be encoded.
|
||||
/// </summary>
|
||||
class components
|
||||
{
|
||||
public:
|
||||
enum component
|
||||
{
|
||||
user_info,
|
||||
host,
|
||||
path,
|
||||
query,
|
||||
fragment,
|
||||
full_uri
|
||||
};
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a URI component according to RFC 3986.
|
||||
/// Note if a full URI is specified instead of an individual URI component all
|
||||
/// characters not in the unreserved set are escaped.
|
||||
/// </summary>
|
||||
/// <param name="raw">The URI as a string.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_uri(const utility::string_t &raw, uri::components::component = components::full_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a string by converting all characters except for RFC 3986 unreserved characters to their
|
||||
/// hexadecimal representation.
|
||||
/// </summary>
|
||||
/// <param name="utf8data">The UTF-8 string data.</param>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t &utf8data);
|
||||
|
||||
/// <summary>
|
||||
/// Decodes an encoded string.
|
||||
/// </summary>
|
||||
/// <param name="encoded">The URI as a string.</param>
|
||||
/// <returns>The decoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl decode(const utility::string_t &encoded);
|
||||
|
||||
/// <summary>
|
||||
/// Splits a path into its hierarchical components.
|
||||
/// </summary>
|
||||
/// <param name="path">The path as a string</param>
|
||||
/// <returns>A <c>std::vector<utility::string_t></c> containing the segments in the path.</returns>
|
||||
_ASYNCRTIMP static std::vector<utility::string_t> __cdecl split_path(const utility::string_t &path);
|
||||
|
||||
/// <summary>
|
||||
/// Splits a query into its key-value components.
|
||||
/// </summary>
|
||||
/// <param name="query">The query string</param>
|
||||
/// <returns>A <c>std::map<utility::string_t, utility::string_t></c> containing the key-value components of the query.</returns>
|
||||
_ASYNCRTIMP static std::map<utility::string_t, utility::string_t> __cdecl split_query(const utility::string_t &query);
|
||||
|
||||
/// <summary>
|
||||
/// Validates a string as a URI.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">The URI string to be validated.</param>
|
||||
/// <returns><c>true</c> if the given string represents a valid URI, <c>false</c> otherwise.</returns>
|
||||
_ASYNCRTIMP static bool __cdecl validate(const utility::string_t &uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an empty uri
|
||||
/// </summary>
|
||||
uri() { m_uri = _XPLATSTR("/");};
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">A pointer to an encoded string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::char_t *uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given encoded string. This will throw an exception if the string
|
||||
/// does not contain a valid URI. Use uri::validate if processing user-input.
|
||||
/// </summary>
|
||||
/// <param name="uri_string">An encoded URI string to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const utility::string_t &uri_string);
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
uri(const uri &other) :
|
||||
m_uri(other.m_uri),
|
||||
m_components(other.m_components)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Copy assignment operator.
|
||||
/// </summary>
|
||||
uri & operator=(const uri &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_uri = other.m_uri;
|
||||
m_components = other.m_components;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
uri(uri &&other) CPPREST_NOEXCEPT :
|
||||
m_uri(std::move(other.m_uri)),
|
||||
m_components(std::move(other.m_components))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator
|
||||
/// </summary>
|
||||
uri & operator=(uri &&other) CPPREST_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
m_uri = std::move(other.m_uri);
|
||||
m_components = std::move(other.m_components);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scheme component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI scheme as a string.</returns>
|
||||
const utility::string_t &scheme() const { return m_components.m_scheme; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the user information component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI user information as a string.</returns>
|
||||
const utility::string_t &user_info() const { return m_components.m_user_info; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the host component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI host as a string.</returns>
|
||||
const utility::string_t &host() const { return m_components.m_host; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||||
/// </summary>
|
||||
/// <returns>The URI port as an integer.</returns>
|
||||
int port() const { return m_components.m_port; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the path component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI path as a string.</returns>
|
||||
const utility::string_t &path() const { return m_components.m_path; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the query component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI query as a string.</returns>
|
||||
const utility::string_t &query() const { return m_components.m_query; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the fragment component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI fragment as a string.</returns>
|
||||
const utility::string_t &fragment() const { return m_components.m_fragment; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new uri object with the same authority portion as this one, omitting the resource and query portions.
|
||||
/// </summary>
|
||||
/// <returns>The new uri object with the same authority.</returns>
|
||||
_ASYNCRTIMP uri authority() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path, query, and fragment portion of this uri, which may be empty.
|
||||
/// </summary>
|
||||
/// <returns>The new URI object with the path, query and fragment portion of this URI.</returns>
|
||||
_ASYNCRTIMP uri resource() const;
|
||||
|
||||
/// <summary>
|
||||
/// An empty URI specifies no components, and serves as a default value
|
||||
/// </summary>
|
||||
bool is_empty() const
|
||||
{
|
||||
return this->m_uri.empty() || this->m_uri == _XPLATSTR("/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examples include "locahost", or ip addresses in the loopback range (127.0.0.0/24).
|
||||
/// </remarks>
|
||||
/// <returns><c>true</c> if this URI references the local host, <c>false</c> otherwise.</returns>
|
||||
bool is_host_loopback() const
|
||||
{
|
||||
return !is_empty() && ((host() == _XPLATSTR("localhost")) || (host().size() > 4 && host().substr(0,4) == _XPLATSTR("127.")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wildcard URI is one which refers to all hostnames that resolve to the local machine (using the * or +)
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// http://*:80
|
||||
/// </example>
|
||||
bool is_host_wildcard() const
|
||||
{
|
||||
return !is_empty() && (this->host() == _XPLATSTR("*") || this->host() == _XPLATSTR("+"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A portable URI is one with a hostname that can be resolved globally (used from another machine).
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI can be resolved globally (used from another machine), <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// The hostname "localhost" is a reserved name that is guaranteed to resolve to the local machine,
|
||||
/// and cannot be used for inter-machine communication. Likewise the hostnames "*" and "+" on Windows
|
||||
/// represent wildcards, and do not map to a resolvable address.
|
||||
/// </remarks>
|
||||
bool is_host_portable() const
|
||||
{
|
||||
return !(is_empty() || is_host_loopback() || is_host_wildcard());
|
||||
}
|
||||
|
||||
// <summary>
|
||||
/// A default port is one where the port is unspecified, and will be determined by the operating system.
|
||||
/// The choice of default port may be dictated by the scheme (http -> 80) or not.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this URI instance has a default port, <c>false</c> otherwise.</returns>
|
||||
bool is_port_default() const
|
||||
{
|
||||
return !is_empty() && this->port() == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An "authority" URI is one with only a scheme, optional userinfo, hostname, and (optional) port.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if this is an "authority" URI, <c>false</c> otherwise.</returns>
|
||||
bool is_authority() const
|
||||
{
|
||||
return !is_empty() && is_path_empty() && query().empty() && fragment().empty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the other URI has the same authority as this one
|
||||
/// </summary>
|
||||
/// <param name="other">The URI to compare the authority with.</param>
|
||||
/// <returns><c>true</c> if both the URI's have the same authority, <c>false</c> otherwise.</returns>
|
||||
bool has_same_authority(const uri &other) const
|
||||
{
|
||||
return !is_empty() && this->authority() == other.authority();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the path portion of this URI is empty
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if the path portion of this URI is empty, <c>false</c> otherwise.</returns>
|
||||
bool is_path_empty() const
|
||||
{
|
||||
return path().empty() || path() == _XPLATSTR("/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full (encoded) URI as a string.
|
||||
/// </summary>
|
||||
/// <returns>The full encoded URI string.</returns>
|
||||
utility::string_t to_string() const
|
||||
{
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
_ASYNCRTIMP bool operator == (const uri &other) const;
|
||||
|
||||
bool operator < (const uri &other) const
|
||||
{
|
||||
return m_uri < other.m_uri;
|
||||
}
|
||||
|
||||
bool operator != (const uri &other) const
|
||||
{
|
||||
return !(this->operator == (other));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class uri_builder;
|
||||
|
||||
// Encodes all characters not in given set determined by given function.
|
||||
static utility::string_t encode_impl(const utility::string_t &raw, const std::function<bool(int)>& should_encode);
|
||||
|
||||
utility::string_t m_uri;
|
||||
details::uri_components m_components;
|
||||
};
|
||||
|
||||
} // namespace web
|
632
3rdparty/cpprestsdk/include/cpprest/containerstream.h
vendored
Normal file
632
3rdparty/cpprestsdk/include/cpprest/containerstream.h
vendored
Normal file
|
@ -0,0 +1,632 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a basic STL-container-based stream buffer. Reading from the buffer will not remove any data
|
||||
* from it and seeking is thus supported.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
|
||||
namespace Concurrency { namespace streams {
|
||||
|
||||
// Forward declarations
|
||||
|
||||
template<typename _CollectionType> class container_buffer;
|
||||
|
||||
namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// The basic_container_buffer class serves as a memory-based steam buffer that supports writing or reading
|
||||
/// sequences of characters.
|
||||
/// The class itself should not be used in application code, it is used by the stream definitions farther down in the header file.
|
||||
/// </summary>
|
||||
/// <remarks> When closed, neither writing nor reading is supported any longer. <c>basic_container_buffer</c> does not support simultaneous use of the buffer
|
||||
/// for reading and writing.</remarks>
|
||||
template<typename _CollectionType>
|
||||
class basic_container_buffer : public streams::details::streambuf_state_manager<typename _CollectionType::value_type>
|
||||
{
|
||||
public:
|
||||
typedef typename _CollectionType::value_type _CharType;
|
||||
typedef typename basic_streambuf<_CharType>::traits traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying data container
|
||||
/// </summary>
|
||||
_CollectionType& collection()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_container_buffer()
|
||||
{
|
||||
// Invoke the synchronous versions since we need to
|
||||
// purge the request queue before deleting the buffer
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/// <summary>
|
||||
/// can_seek is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the stream, if known. Calls to <c>has_size</c> will determine whether
|
||||
/// the result of <c>size</c> can be relied on.
|
||||
/// </summary>
|
||||
virtual utility::size64_t size() const
|
||||
{
|
||||
return utility::size64_t(m_data.size());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it will not have any effect on what is returned by subsequent calls to <see cref="::buffer_size method" />.</remarks>
|
||||
virtual void set_buffer_size(size_t , std::ios_base::openmode = std::ios_base::in)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, <c>in_avail</c> returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> to read data without
|
||||
/// incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const
|
||||
{
|
||||
// See the comment in seek around the restriction that we do not allow read head to
|
||||
// seek beyond the current write_end.
|
||||
_ASSERTE(m_current_position <= m_data.size());
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_data.size());
|
||||
return (size_t)(writeend - readhead);
|
||||
}
|
||||
|
||||
virtual pplx::task<bool> _sync()
|
||||
{
|
||||
return pplx::task_from_result(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
int_type retVal = (this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof();
|
||||
return pplx::task_from_result<int_type>(retVal);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count)
|
||||
{
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support alloc/commit.</returns>
|
||||
_CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write()) return nullptr;
|
||||
|
||||
// Allocate space
|
||||
resize_for_write(m_current_position+count);
|
||||
|
||||
// Let the caller copy the data
|
||||
return (_CharType*)&m_data[m_current_position];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
void _commit(size_t actual )
|
||||
{
|
||||
// Update the write position and satisfy any pending reads
|
||||
update_current_position(m_current_position+actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr.'</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
ptr = nullptr;
|
||||
count = 0;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
count = in_avail();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
ptr = (_CharType*)&m_data[m_current_position];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can only be open for read OR write, not both. If there is no data then
|
||||
// we have reached the end of the stream so indicate such with true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to de-allocate the
|
||||
/// memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr != nullptr)
|
||||
update_current_position(m_current_position + count);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return pplx::task_from_result(this->read(ptr, count));
|
||||
}
|
||||
|
||||
size_t _sgetn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count);
|
||||
}
|
||||
|
||||
virtual size_t _scopy(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count, false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc()
|
||||
{
|
||||
return pplx::task_from_result(this->read_byte(true));
|
||||
}
|
||||
|
||||
virtual int_type _sbumpc()
|
||||
{
|
||||
return this->read_byte(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _getc()
|
||||
{
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
int_type _sgetc()
|
||||
{
|
||||
return this->read_byte(false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
this->read_byte(true);
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc()
|
||||
{
|
||||
auto pos = seekoff(-1, std::ios_base::cur, std::ios_base::in);
|
||||
if ( pos == (pos_type)traits::eof())
|
||||
return pplx::task_from_result(traits::eof());
|
||||
return this->getc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if ( ((mode & std::ios_base::in) && !this->can_read()) ||
|
||||
((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given position.
|
||||
/// </summary>
|
||||
/// <param name="pos">The offset from the beginning of the stream.</param>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks).</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors. For such streams, the direction parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekpos(pos_type position, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg(0);
|
||||
|
||||
// In order to support relative seeking from the end position we need to fix an end position.
|
||||
// Technically, there is no end for the stream buffer as new writes would just expand the buffer.
|
||||
// For now, we assume that the current write_end is the end of the buffer. We use this artificial
|
||||
// end to restrict the read head from seeking beyond what is available.
|
||||
|
||||
pos_type end(m_data.size());
|
||||
|
||||
if (position >= beg)
|
||||
{
|
||||
auto pos = static_cast<size_t>(position);
|
||||
|
||||
// Read head
|
||||
if ((mode & std::ios_base::in) && this->can_read())
|
||||
{
|
||||
if (position <= end)
|
||||
{
|
||||
// We do not allow reads to seek beyond the end or before the start position.
|
||||
update_current_position(pos);
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
// Write head
|
||||
if ((mode & std::ios_base::out) && this->can_write())
|
||||
{
|
||||
// Allocate space
|
||||
resize_for_write(pos);
|
||||
|
||||
// Nothing to really copy
|
||||
|
||||
// Update write head and satisfy read requests if any
|
||||
update_current_position(pos);
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a position given by a relative offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The relative position to seek to</param>
|
||||
/// <param name="way">The starting point (beginning, end, current) for the seek.</param>
|
||||
/// <param name="mode">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the mode parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg = 0;
|
||||
pos_type cur = static_cast<pos_type>(m_current_position);
|
||||
pos_type end = static_cast<pos_type>(m_data.size());
|
||||
|
||||
switch ( way )
|
||||
{
|
||||
case std::ios_base::beg:
|
||||
return seekpos(beg + offset, mode);
|
||||
|
||||
case std::ios_base::cur:
|
||||
return seekpos(cur + offset, mode);
|
||||
|
||||
case std::ios_base::end:
|
||||
return seekpos(end + offset, mode);
|
||||
|
||||
default:
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename _CollectionType1> friend class streams::container_buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_container_buffer(std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<typename _CollectionType::value_type>(mode),
|
||||
m_current_position(0)
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_container_buffer(_CollectionType data, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<typename _CollectionType::value_type>(mode),
|
||||
m_data(std::move(data)),
|
||||
m_current_position((mode & std::ios_base::in) ? 0 : m_data.size())
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
static void validate_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
// Disallow simultaneous use of the stream buffer for writing and reading.
|
||||
if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
|
||||
throw std::invalid_argument("this combination of modes on container stream not supported");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t)
|
||||
{
|
||||
// We can always satisfy a read, at least partially, unless the
|
||||
// read position is at the very end of the buffer.
|
||||
return (in_avail() > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
size_t read(_Out_writes_ (count) _CharType *ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
if (!can_satisfy(count))
|
||||
return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> request_size(count);
|
||||
msl::safeint3::SafeInt<size_t> read_size = request_size.Min(in_avail());
|
||||
|
||||
size_t newPos = m_current_position + read_size;
|
||||
|
||||
auto readBegin = begin(m_data) + m_current_position;
|
||||
auto readEnd = begin(m_data) + newPos;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType *>(ptr, count));
|
||||
#else
|
||||
std::copy(readBegin, readEnd, ptr);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_current_position(newPos);
|
||||
}
|
||||
|
||||
return (size_t) read_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write count characters from the ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType *ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
auto newSize = m_current_position + count;
|
||||
|
||||
// Allocate space
|
||||
resize_for_write(newSize);
|
||||
|
||||
// Copy the data
|
||||
std::copy(ptr, ptr + count, begin(m_data) + m_current_position);
|
||||
|
||||
// Update write head and satisfy pending reads if any
|
||||
update_current_position(newSize);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resize the underlying container to match the new write head
|
||||
/// </summary>
|
||||
void resize_for_write(size_t newPos)
|
||||
{
|
||||
// Resize the container if required
|
||||
if (newPos > m_data.size())
|
||||
{
|
||||
m_data.resize(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the write head to the new position
|
||||
/// </summary>
|
||||
void update_current_position(size_t newPos)
|
||||
{
|
||||
// The new write head
|
||||
m_current_position = newPos;
|
||||
_ASSERTE(m_current_position <= m_data.size());
|
||||
}
|
||||
|
||||
// The actual data store
|
||||
_CollectionType m_data;
|
||||
|
||||
// Read/write head
|
||||
size_t m_current_position;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The basic_container_buffer class serves as a memory-based steam buffer that supports writing or reading
|
||||
/// sequences of characters. Note that it cannot be used as a consumer producer buffer.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">
|
||||
/// The type of the container.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// This is a reference-counted version of <c>basic_container_buffer</c>.
|
||||
/// </remarks>
|
||||
template<typename _CollectionType>
|
||||
class container_buffer : public streambuf<typename _CollectionType::value_type>
|
||||
{
|
||||
public:
|
||||
typedef typename _CollectionType::value_type char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a container_buffer given a collection, copying its data into the buffer.
|
||||
/// </summary>
|
||||
/// <param name="data">The collection that is the starting point for the buffer</param>
|
||||
/// <param name="mode">The I/O mode that the buffer should use (in / out)</param>
|
||||
container_buffer(_CollectionType data, std::ios_base::openmode mode = std::ios_base::in)
|
||||
: streambuf<typename _CollectionType::value_type>(
|
||||
std::shared_ptr<details::basic_container_buffer<_CollectionType>>(new streams::details::basic_container_buffer<_CollectionType>(std::move(data), mode)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a container_buffer starting from an empty collection.
|
||||
/// </summary>
|
||||
/// <param name="mode">The I/O mode that the buffer should use (in / out)</param>
|
||||
container_buffer(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: streambuf<typename _CollectionType::value_type>(
|
||||
std::shared_ptr<details::basic_container_buffer<_CollectionType>>(new details::basic_container_buffer<_CollectionType>(mode)))
|
||||
{
|
||||
}
|
||||
|
||||
_CollectionType& collection() const
|
||||
{
|
||||
auto listBuf = static_cast<details::basic_container_buffer<_CollectionType> *>(this->get_base().get());
|
||||
return listBuf->collection();
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A static class to allow users to create input and out streams based off STL
|
||||
/// collections. The sole purpose of this class to avoid users from having to know
|
||||
/// anything about stream buffers.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
template<typename _CollectionType>
|
||||
class container_stream
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename _CollectionType::value_type char_type;
|
||||
typedef container_buffer<_CollectionType> buffer_type;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an input stream given an STL container.
|
||||
/// </summary>
|
||||
/// </param name="data">STL container to back the input stream.</param>
|
||||
/// <returns>An input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(_CollectionType data)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(std::move(data), std::ios_base::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an output stream using an STL container as the storage.
|
||||
/// </summary>
|
||||
/// <returns>An output stream.</returns>
|
||||
static concurrency::streams::basic_ostream<char_type> open_ostream()
|
||||
{
|
||||
return concurrency::streams::basic_ostream<char_type>(buffer_type(std::ios_base::out));
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The stringstream allows an input stream to be constructed from std::string or std::wstring
|
||||
/// For output streams the underlying string container could be retrieved using <c>buf->collection().</c>
|
||||
/// </summary>
|
||||
typedef container_stream<std::basic_string<char>> stringstream;
|
||||
typedef stringstream::buffer_type stringstreambuf;
|
||||
|
||||
typedef container_stream<utility::string_t> wstringstream;
|
||||
typedef wstringstream::buffer_type wstringstreambuf;
|
||||
|
||||
/// <summary>
|
||||
/// The <c>bytestream</c> is a static class that allows an input stream to be constructed from any STL container.
|
||||
/// </summary>
|
||||
class bytestream
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Creates a single byte character input stream given an STL container.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
/// <param name="data">STL container to back the input stream.</param>
|
||||
/// <returns>An single byte character input stream.</returns>
|
||||
template<typename _CollectionType>
|
||||
static concurrency::streams::istream open_istream(_CollectionType data)
|
||||
{
|
||||
return concurrency::streams::istream(streams::container_buffer<_CollectionType>(std::move(data), std::ios_base::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a single byte character output stream using an STL container as storage.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CollectionType">The type of the STL collection.</typeparam>
|
||||
/// <returns>A single byte character output stream.</returns>
|
||||
template<typename _CollectionType>
|
||||
static concurrency::streams::ostream open_ostream()
|
||||
{
|
||||
return concurrency::streams::ostream(streams::container_buffer<_CollectionType>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}} // namespaces
|
7047
3rdparty/cpprestsdk/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
7047
3rdparty/cpprestsdk/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
141
3rdparty/cpprestsdk/include/cpprest/details/basic_types.h
vendored
Normal file
141
3rdparty/cpprestsdk/include/cpprest/details/basic_types.h
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Platform-dependent type definitions
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
# define __STDC_LIMIT_MACROS
|
||||
# include <stdint.h>
|
||||
#else
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/SafeInt3.hpp"
|
||||
|
||||
namespace utility
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _UTF16_STRINGS
|
||||
#endif
|
||||
|
||||
// We should be using a 64-bit size type for most situations that do
|
||||
// not involve specifying the size of a memory allocation or buffer.
|
||||
typedef uint64_t size64_t;
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef uint32_t HRESULT; // Needed for PPLX
|
||||
#endif
|
||||
|
||||
#ifdef _UTF16_STRINGS
|
||||
//
|
||||
// On Windows, all strings are wide
|
||||
//
|
||||
typedef wchar_t char_t ;
|
||||
typedef std::wstring string_t;
|
||||
#define _XPLATSTR(x) L ## x
|
||||
typedef std::wostringstream ostringstream_t;
|
||||
typedef std::wofstream ofstream_t;
|
||||
typedef std::wostream ostream_t;
|
||||
typedef std::wistream istream_t;
|
||||
typedef std::wifstream ifstream_t;
|
||||
typedef std::wistringstream istringstream_t;
|
||||
typedef std::wstringstream stringstream_t;
|
||||
#define ucout std::wcout
|
||||
#define ucin std::wcin
|
||||
#define ucerr std::wcerr
|
||||
#else
|
||||
//
|
||||
// On POSIX platforms, all strings are narrow
|
||||
//
|
||||
typedef char char_t;
|
||||
typedef std::string string_t;
|
||||
#define _XPLATSTR(x) x
|
||||
typedef std::ostringstream ostringstream_t;
|
||||
typedef std::ofstream ofstream_t;
|
||||
typedef std::ostream ostream_t;
|
||||
typedef std::istream istream_t;
|
||||
typedef std::ifstream ifstream_t;
|
||||
typedef std::istringstream istringstream_t;
|
||||
typedef std::stringstream stringstream_t;
|
||||
#define ucout std::cout
|
||||
#define ucin std::cin
|
||||
#define ucerr std::cerr
|
||||
#endif // endif _UTF16_STRINGS
|
||||
|
||||
#ifndef _TURN_OFF_PLATFORM_STRING
|
||||
#define U(x) _XPLATSTR(x)
|
||||
#endif // !_TURN_OFF_PLATFORM_STRING
|
||||
|
||||
}// namespace utility
|
||||
|
||||
typedef char utf8char;
|
||||
typedef std::string utf8string;
|
||||
typedef std::stringstream utf8stringstream;
|
||||
typedef std::ostringstream utf8ostringstream;
|
||||
typedef std::ostream utf8ostream;
|
||||
typedef std::istream utf8istream;
|
||||
typedef std::istringstream utf8istringstream;
|
||||
|
||||
#ifdef _UTF16_STRINGS
|
||||
typedef wchar_t utf16char;
|
||||
typedef std::wstring utf16string;
|
||||
typedef std::wstringstream utf16stringstream;
|
||||
typedef std::wostringstream utf16ostringstream;
|
||||
typedef std::wostream utf16ostream;
|
||||
typedef std::wistream utf16istream;
|
||||
typedef std::wistringstream utf16istringstream;
|
||||
#else
|
||||
typedef char16_t utf16char;
|
||||
typedef std::u16string utf16string;
|
||||
typedef std::basic_stringstream<utf16char> utf16stringstream;
|
||||
typedef std::basic_ostringstream<utf16char> utf16ostringstream;
|
||||
typedef std::basic_ostream<utf16char> utf16ostream;
|
||||
typedef std::basic_istream<utf16char> utf16istream;
|
||||
typedef std::basic_istringstream<utf16char> utf16istringstream;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Include on everything except Windows Desktop ARM, unless explicitly excluded.
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
#if defined(WINAPI_FAMILY)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && defined(_M_ARM)
|
||||
#define CPPREST_EXCLUDE_WEBSOCKETS
|
||||
#endif
|
||||
#else
|
||||
#if defined(_M_ARM)
|
||||
#define CPPREST_EXCLUDE_WEBSOCKETS
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
103
3rdparty/cpprestsdk/include/cpprest/details/cpprest_compat.h
vendored
Normal file
103
3rdparty/cpprestsdk/include/cpprest/details/cpprest_compat.h
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Standard macros and definitions.
|
||||
* This header has minimal dependency on windows headers and is safe for use in the public API
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32) // Settings specific to Windows
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
#else
|
||||
#define CPPREST_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (x)
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#else // End settings specific to Windows
|
||||
|
||||
// Settings common to all but Windows
|
||||
|
||||
#define __declspec(x) __attribute__ ((x))
|
||||
#define dllimport
|
||||
#define novtable /* no novtable equivalent */
|
||||
#define __assume(x) do { if (!(x)) __builtin_unreachable(); } while (false)
|
||||
#define CASABLANCA_UNREFERENCED_PARAMETER(x) (void)x
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
|
||||
#include <assert.h>
|
||||
#define _ASSERTE(x) assert(x)
|
||||
|
||||
// No SAL on non Windows platforms
|
||||
#include "cpprest/details/nosal.h"
|
||||
|
||||
#if defined(__APPLE__) // Settings specific to Apple
|
||||
#define __cdecl
|
||||
#else
|
||||
|
||||
// Settings specific to Linux and Android
|
||||
|
||||
// Ignore cdecl on ANDROID ARM and 64bit
|
||||
#if defined(__ANDROID__) && defined(__arm__) || defined(__LP64__)
|
||||
#define __cdecl
|
||||
#else
|
||||
#define __cdecl __attribute__ ((cdecl))
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// This is needed to disable the use of __thread inside the boost library.
|
||||
// Android does not support thread local storage -- if boost is included
|
||||
// without this macro defined, it will create references to __tls_get_addr
|
||||
// which (while able to link) will not be available at runtime and prevent
|
||||
// the .so from loading.
|
||||
#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
#endif // defined(__APPLE__)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _NO_ASYNCRTIMP
|
||||
#define _ASYNCRTIMP
|
||||
#else
|
||||
#ifdef _ASYNCRT_EXPORT
|
||||
#define _ASYNCRTIMP __declspec(dllexport)
|
||||
#else
|
||||
#define _ASYNCRTIMP __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CASABLANCA_DEPRECATION_NO_WARNINGS
|
||||
#define CASABLANCA_DEPRECATED(x)
|
||||
#else
|
||||
#define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x))
|
||||
#endif
|
206
3rdparty/cpprestsdk/include/cpprest/details/fileio.h
vendored
Normal file
206
3rdparty/cpprestsdk/include/cpprest/details/fileio.h
vendored
Normal file
|
@ -0,0 +1,206 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* fileio.h
|
||||
*
|
||||
* Asynchronous I/O: stream buffer implementation details
|
||||
*
|
||||
* We're going to some lengths to avoid exporting C++ class member functions and implementation details across
|
||||
* module boundaries, and the factoring requires that we keep the implementation details away from the main header
|
||||
* files. The supporting functions, which are in this file, use C-like signatures to avoid as many issues as
|
||||
* possible.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
namespace Concurrency { namespace streams
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// A record containing the essential private data members of a file stream,
|
||||
/// in particular the parts that need to be shared between the public header
|
||||
/// file and the implementation in the implementation file.
|
||||
/// </summary>
|
||||
struct _file_info
|
||||
{
|
||||
_ASYNCRTIMP _file_info(std::ios_base::openmode mode, size_t buffer_size) :
|
||||
m_rdpos(0),
|
||||
m_wrpos(0),
|
||||
m_atend(false),
|
||||
m_buffer_size(buffer_size),
|
||||
m_buffer(nullptr),
|
||||
m_bufoff(0),
|
||||
m_bufsize(0),
|
||||
m_buffill(0),
|
||||
m_mode(mode)
|
||||
{
|
||||
}
|
||||
|
||||
// Positional data
|
||||
|
||||
size_t m_rdpos;
|
||||
size_t m_wrpos;
|
||||
bool m_atend;
|
||||
|
||||
// Input buffer
|
||||
|
||||
size_t m_buffer_size; // The intended size of the buffer to read into.
|
||||
char *m_buffer;
|
||||
|
||||
size_t m_bufoff; // File position that the start of the buffer represents.
|
||||
msl::safeint3::SafeInt<size_t> m_bufsize; // Buffer allocated size, as actually allocated.
|
||||
size_t m_buffill; // Amount of file data actually in the buffer
|
||||
|
||||
std::ios_base::openmode m_mode;
|
||||
|
||||
pplx::extensibility::recursive_lock_t m_lock;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This interface provides the necessary callbacks for completion events.
|
||||
/// </summary>
|
||||
class _filestream_callback
|
||||
{
|
||||
public:
|
||||
virtual void on_opened(_In_ details::_file_info *) { }
|
||||
virtual void on_closed() { }
|
||||
virtual void on_error(const std::exception_ptr &) { }
|
||||
virtual void on_completed(size_t) { }
|
||||
protected:
|
||||
virtual ~_filestream_callback() {}
|
||||
};
|
||||
|
||||
}
|
||||
}}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
/// <summary>
|
||||
/// Open a file and create a streambuf instance to represent it.
|
||||
/// </summary>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <param name="filename">The name of the file to open</param>
|
||||
/// <param name="mode">A creation mode for the stream buffer</param>
|
||||
/// <param name="prot">A file protection mode to use for the file stream (not supported on Linux)</param>
|
||||
/// <returns><c>true</c> if the opening operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully opened, just that the process was started.
|
||||
/// </remarks>
|
||||
#if !defined(__cplusplus_winrt)
|
||||
_ASYNCRTIMP bool __cdecl _open_fsb_str(_In_ concurrency::streams::details::_filestream_callback *callback, const utility::char_t *filename, std::ios_base::openmode mode, int prot);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Create a streambuf instance to represent a WinRT file.
|
||||
/// </summary>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <param name="file">The file object</param>
|
||||
/// <param name="mode">A creation mode for the stream buffer</param>
|
||||
/// <returns><c>true</c> if the opening operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully opened, just that the process was started.
|
||||
/// This is only available for WinRT.
|
||||
/// </remarks>
|
||||
#if defined(__cplusplus_winrt)
|
||||
_ASYNCRTIMP bool __cdecl _open_fsb_stf_str(_In_ concurrency::streams::details::_filestream_callback *callback, ::Windows::Storage::StorageFile^ file, std::ios_base::openmode mode, int prot);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Close a file stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the file has been opened.</param>
|
||||
/// <returns><c>true</c> if the closing operation could be initiated, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// True does not signal that the file will eventually be successfully closed, just that the process was started.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP bool __cdecl _close_fsb_nolock(_In_ concurrency::streams::details::_file_info **info, _In_ concurrency::streams::details::_filestream_callback *callback);
|
||||
_ASYNCRTIMP bool __cdecl _close_fsb(_In_ concurrency::streams::details::_file_info **info, _In_ concurrency::streams::details::_filestream_callback *callback);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Write data from a buffer into the file stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is completed.</param>
|
||||
/// <param name="ptr">A pointer to a buffer where the data should be placed</param>
|
||||
/// <param name="count">The size (in characters) of the buffer</param>
|
||||
/// <returns>0 if the read request is still outstanding, -1 if the request failed, otherwise the size of the data read into the buffer</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _putn_fsb(_In_ concurrency::streams::details::_file_info *info, _In_ concurrency::streams::details::_filestream_callback *callback, const void *ptr, size_t count, size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Read data from a file stream into a buffer
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is completed.</param>
|
||||
/// <param name="ptr">A pointer to a buffer where the data should be placed</param>
|
||||
/// <param name="count">The size (in characters) of the buffer</param>
|
||||
/// <returns>0 if the read request is still outstanding, -1 if the request failed, otherwise the size of the data read into the buffer</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _getn_fsb(_In_ concurrency::streams::details::_file_info *info, _In_ concurrency::streams::details::_filestream_callback *callback, _Out_writes_ (count) void *ptr, _In_ size_t count, size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Flush all buffered data to the underlying file.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="callback">A pointer to the callback interface to invoke when the write request is completed.</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP bool __cdecl _sync_fsb(_In_ concurrency::streams::details::_file_info *info, _In_ concurrency::streams::details::_filestream_callback *callback);
|
||||
|
||||
/// <summary>
|
||||
/// Get the size of the underlying file.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <returns>The file size</returns>
|
||||
_ASYNCRTIMP utility::size64_t __cdecl _get_size(_In_ concurrency::streams::details::_file_info *info, size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new read location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekrdpos_fsb(_In_ concurrency::streams::details::_file_info *info, size_t pos, size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new read location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekrdtoend_fsb(_In_ concurrency::streams::details::_file_info *info, int64_t offset, size_t char_size);
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the internal buffers and pointers when the application seeks to a new write location in the stream.
|
||||
/// </summary>
|
||||
/// <param name="info">The file info record of the file</param>
|
||||
/// <param name="pos">The new position (offset from the start) in the file stream</param>
|
||||
/// <returns><c>true</c> if the request was initiated</returns>
|
||||
_ASYNCRTIMP size_t __cdecl _seekwrpos_fsb(_In_ concurrency::streams::details::_file_info *info, size_t pos, size_t char_size);
|
||||
}
|
466
3rdparty/cpprestsdk/include/cpprest/details/http_client_impl.h
vendored
Normal file
466
3rdparty/cpprestsdk/include/cpprest/details/http_client_impl.h
vendored
Normal file
|
@ -0,0 +1,466 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Client-side APIs, non-public declarations used in the implementation.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/details/http_helpers.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# define CRLF _XPLATSTR("\r\n")
|
||||
#else
|
||||
# define CRLF std::string("\r\n")
|
||||
#endif
|
||||
|
||||
namespace web { namespace http { namespace client { namespace details
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
static const utility::char_t * get_with_body = _XPLATSTR("A GET or HEAD request should not have an entity body.");
|
||||
|
||||
// Helper function to trim leading and trailing null characters from a string.
|
||||
static void trim_nulls(utility::string_t &str)
|
||||
{
|
||||
size_t index;
|
||||
for(index = 0; index < str.size() && str[index] == 0; ++index);
|
||||
str.erase(0, index);
|
||||
for(index = str.size(); index > 0 && str[index - 1] == 0; --index);
|
||||
str.erase(index);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Flatten the http_headers into a name:value pairs separated by a carriage return and line feed.
|
||||
static utility::string_t flatten_http_headers(const http_headers &headers)
|
||||
{
|
||||
utility::string_t flattened_headers;
|
||||
for(auto iter = headers.begin(); iter != headers.end(); ++iter)
|
||||
{
|
||||
flattened_headers.append(iter->first);
|
||||
flattened_headers.push_back(':');
|
||||
flattened_headers.append(iter->second);
|
||||
flattened_headers.append(CRLF);
|
||||
}
|
||||
return flattened_headers;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/// <summary>
|
||||
/// Parses a string containing Http headers.
|
||||
/// </summary>
|
||||
static void parse_headers_string(_Inout_z_ utf16char *headersStr, http_headers &headers)
|
||||
{
|
||||
utf16char *context = nullptr;
|
||||
utf16char *line = wcstok_s(headersStr, CRLF, &context);
|
||||
while(line != nullptr)
|
||||
{
|
||||
const utility::string_t header_line(line);
|
||||
const size_t colonIndex = header_line.find_first_of(_XPLATSTR(":"));
|
||||
if(colonIndex != utility::string_t::npos)
|
||||
{
|
||||
utility::string_t key = header_line.substr(0, colonIndex);
|
||||
utility::string_t value = header_line.substr(colonIndex + 1, header_line.length() - colonIndex - 1);
|
||||
http::details::trim_whitespace(key);
|
||||
http::details::trim_whitespace(value);
|
||||
headers.add(key, value);
|
||||
}
|
||||
line = wcstok_s(nullptr, CRLF, &context);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class _http_client_communicator;
|
||||
|
||||
// Request context encapsulating everything necessary for creating and responding to a request.
|
||||
class request_context
|
||||
{
|
||||
public:
|
||||
|
||||
// Destructor to clean up any held resources.
|
||||
virtual ~request_context()
|
||||
{
|
||||
}
|
||||
|
||||
void complete_headers()
|
||||
{
|
||||
// We have already read (and transmitted) the request body. Should we explicitly close the stream?
|
||||
// Well, there are test cases that assumes that the istream is valid when t receives the response!
|
||||
// For now, we will drop our reference which will close the stream if the user doesn't have one.
|
||||
m_request.set_body(Concurrency::streams::istream());
|
||||
m_request_completion.set(m_response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completes this request, setting the underlying task completion event, and cleaning up the handles
|
||||
/// </summary>
|
||||
void complete_request(utility::size64_t body_size)
|
||||
{
|
||||
m_response._get_impl()->_complete(body_size);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
void report_error(unsigned long error_code, const std::string &errorMessage)
|
||||
{
|
||||
report_exception(http_exception(static_cast<int>(error_code), errorMessage));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void report_error(unsigned long error_code, const std::wstring &errorMessage)
|
||||
{
|
||||
report_exception(http_exception(static_cast<int>(error_code), errorMessage));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename _ExceptionType>
|
||||
void report_exception(const _ExceptionType &e)
|
||||
{
|
||||
report_exception(std::make_exception_ptr(e));
|
||||
}
|
||||
|
||||
virtual void report_exception(std::exception_ptr exceptionPtr)
|
||||
{
|
||||
auto response_impl = m_response._get_impl();
|
||||
|
||||
// If cancellation has been triggered then ignore any errors.
|
||||
if(m_request._cancellation_token().is_canceled())
|
||||
{
|
||||
exceptionPtr = std::make_exception_ptr(http_exception((int)std::errc::operation_canceled, std::generic_category()));
|
||||
}
|
||||
|
||||
// First try to complete the headers with an exception.
|
||||
if(m_request_completion.set_exception(exceptionPtr))
|
||||
{
|
||||
// Complete the request with no msg body. The exception
|
||||
// should only be propagated to one of the tce.
|
||||
response_impl->_complete(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Complete the request with an exception
|
||||
response_impl->_complete(0, exceptionPtr);
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
virtual concurrency::streams::streambuf<uint8_t> _get_readbuffer()
|
||||
{
|
||||
auto instream = m_request.body();
|
||||
|
||||
_ASSERTE((bool)instream);
|
||||
return instream.streambuf();
|
||||
}
|
||||
|
||||
concurrency::streams::streambuf<uint8_t> _get_writebuffer()
|
||||
{
|
||||
auto outstream = m_response._get_impl()->outstream();
|
||||
|
||||
_ASSERTE((bool)outstream);
|
||||
return outstream.streambuf();
|
||||
}
|
||||
|
||||
// Reference to the http_client implementation.
|
||||
std::shared_ptr<_http_client_communicator> m_http_client;
|
||||
|
||||
// request/response pair.
|
||||
http_request m_request;
|
||||
http_response m_response;
|
||||
|
||||
utility::size64_t m_uploaded;
|
||||
utility::size64_t m_downloaded;
|
||||
|
||||
// task completion event to signal request is completed.
|
||||
pplx::task_completion_event<http_response> m_request_completion;
|
||||
|
||||
// Registration for cancellation notification if enabled.
|
||||
pplx::cancellation_token_registration m_cancellationRegistration;
|
||||
|
||||
protected:
|
||||
|
||||
request_context(const std::shared_ptr<_http_client_communicator> &client, const http_request &request)
|
||||
: m_http_client(client),
|
||||
m_request(request),
|
||||
m_uploaded(0),
|
||||
m_downloaded(0)
|
||||
{
|
||||
auto responseImpl = m_response._get_impl();
|
||||
|
||||
// Copy the user specified output stream over to the response
|
||||
responseImpl->set_outstream(request._get_impl()->_response_stream(), false);
|
||||
|
||||
// Prepare for receiving data from the network. Ideally, this should be done after
|
||||
// we receive the headers and determine that there is a response body. We will do it here
|
||||
// since it is not immediately apparent where that would be in the callback handler
|
||||
responseImpl->_prepare_to_receive_data();
|
||||
}
|
||||
|
||||
virtual void finish();
|
||||
};
|
||||
|
||||
//
|
||||
// Interface used by client implementations. Concrete implementations are responsible for
|
||||
// sending HTTP requests and receiving the responses.
|
||||
//
|
||||
class _http_client_communicator
|
||||
{
|
||||
public:
|
||||
|
||||
// Destructor to clean up any held resources.
|
||||
virtual ~_http_client_communicator() {}
|
||||
|
||||
// Asynchronously send a HTTP request and process the response.
|
||||
void async_send_request(const std::shared_ptr<request_context> &request)
|
||||
{
|
||||
if(m_client_config.guarantee_order())
|
||||
{
|
||||
// Send to call block to be processed.
|
||||
push_request(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Schedule a task to start sending.
|
||||
pplx::create_task([this, request]
|
||||
{
|
||||
open_and_send_request(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void finish_request()
|
||||
{
|
||||
// If guarantee order is specified we don't need to do anything.
|
||||
if(m_client_config.guarantee_order())
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_open_lock);
|
||||
|
||||
--m_scheduled;
|
||||
|
||||
if( !m_requests_queue.empty())
|
||||
{
|
||||
auto request = m_requests_queue.front();
|
||||
m_requests_queue.pop();
|
||||
|
||||
// Schedule a task to start sending.
|
||||
pplx::create_task([this, request]
|
||||
{
|
||||
open_and_send_request(request);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const http_client_config& client_config() const
|
||||
{
|
||||
return m_client_config;
|
||||
}
|
||||
|
||||
const uri & base_uri() const
|
||||
{
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
protected:
|
||||
_http_client_communicator(http::uri address, http_client_config client_config)
|
||||
: m_uri(std::move(address)), m_client_config(std::move(client_config)), m_opened(false), m_scheduled(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Method to open client.
|
||||
virtual unsigned long open() = 0;
|
||||
|
||||
// HTTP client implementations must implement send_request.
|
||||
virtual void send_request(_In_ const std::shared_ptr<request_context> &request) = 0;
|
||||
|
||||
// URI to connect to.
|
||||
const http::uri m_uri;
|
||||
|
||||
private:
|
||||
|
||||
http_client_config m_client_config;
|
||||
|
||||
bool m_opened;
|
||||
|
||||
pplx::extensibility::critical_section_t m_open_lock;
|
||||
|
||||
// Wraps opening the client around sending a request.
|
||||
void open_and_send_request(const std::shared_ptr<request_context> &request)
|
||||
{
|
||||
// First see if client needs to be opened.
|
||||
auto error = open_if_required();
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
// Failed to open
|
||||
request->report_error(error, _XPLATSTR("Open failed"));
|
||||
|
||||
// DO NOT TOUCH the this pointer after completing the request
|
||||
// This object could be freed along with the request as it could
|
||||
// be the last reference to this object
|
||||
return;
|
||||
}
|
||||
|
||||
send_request(request);
|
||||
}
|
||||
|
||||
unsigned long open_if_required()
|
||||
{
|
||||
unsigned long error = 0;
|
||||
|
||||
if(!m_opened)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_open_lock);
|
||||
|
||||
// Check again with the lock held
|
||||
if (!m_opened)
|
||||
{
|
||||
error = open();
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
m_opened = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void push_request(const std::shared_ptr<request_context> &request)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_open_lock);
|
||||
|
||||
if(++m_scheduled == 1)
|
||||
{
|
||||
// Schedule a task to start sending.
|
||||
pplx::create_task([this, request]()
|
||||
{
|
||||
open_and_send_request(request);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
m_requests_queue.push(request);
|
||||
}
|
||||
}
|
||||
|
||||
// Queue used to guarantee ordering of requests, when applicable.
|
||||
std::queue<std::shared_ptr<request_context>> m_requests_queue;
|
||||
int m_scheduled;
|
||||
};
|
||||
|
||||
inline void request_context::finish()
|
||||
{
|
||||
// If cancellation is enabled and registration was performed, unregister.
|
||||
if(m_cancellationRegistration != pplx::cancellation_token_registration())
|
||||
{
|
||||
_ASSERTE(m_request._cancellation_token() != pplx::cancellation_token::none());
|
||||
m_request._cancellation_token().deregister_callback(m_cancellationRegistration);
|
||||
}
|
||||
|
||||
m_http_client->finish_request();
|
||||
}
|
||||
|
||||
class http_network_handler : public http_pipeline_stage
|
||||
{
|
||||
public:
|
||||
http_network_handler(const uri &base_uri, const http_client_config &client_config);
|
||||
|
||||
virtual pplx::task<http_response> propagate(http_request request);
|
||||
|
||||
const std::shared_ptr<details::_http_client_communicator>& http_client_impl() const
|
||||
{
|
||||
return m_http_client_impl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<_http_client_communicator> m_http_client_impl;
|
||||
};
|
||||
|
||||
// Helper function to check to make sure the uri is valid.
|
||||
void verify_uri(const uri &uri)
|
||||
{
|
||||
// Some things like proper URI schema are verified by the URI class.
|
||||
// We only need to check certain things specific to HTTP.
|
||||
if (uri.scheme() != _XPLATSTR("http") && uri.scheme() != _XPLATSTR("https"))
|
||||
{
|
||||
throw std::invalid_argument("URI scheme must be 'http' or 'https'");
|
||||
}
|
||||
|
||||
if(uri.host().empty())
|
||||
{
|
||||
throw std::invalid_argument("URI must contain a hostname.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
http_client::http_client(const uri &base_uri)
|
||||
{
|
||||
build_pipeline(base_uri, http_client_config());
|
||||
}
|
||||
|
||||
http_client::http_client(const uri &base_uri, const http_client_config &client_config)
|
||||
{
|
||||
build_pipeline(base_uri, client_config);
|
||||
}
|
||||
|
||||
void http_client::build_pipeline(const uri &base_uri, const http_client_config &client_config)
|
||||
{
|
||||
if (base_uri.scheme().empty())
|
||||
{
|
||||
auto uribuilder = uri_builder(base_uri);
|
||||
uribuilder.set_scheme(_XPLATSTR("http"));
|
||||
uri uriWithScheme = uribuilder.to_uri();
|
||||
details::verify_uri(uriWithScheme);
|
||||
m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared<details::http_network_handler>(uriWithScheme, client_config));
|
||||
}
|
||||
else
|
||||
{
|
||||
details::verify_uri(base_uri);
|
||||
m_pipeline = ::web::http::http_pipeline::create_pipeline(std::make_shared<details::http_network_handler>(base_uri, client_config));
|
||||
}
|
||||
|
||||
#if !defined(CPPREST_TARGET_XP) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP || _MSC_VER > 1700)
|
||||
add_handler(std::static_pointer_cast<http::http_pipeline_stage>(
|
||||
std::make_shared<oauth1::details::oauth1_handler>(client_config.oauth1())));
|
||||
#endif
|
||||
|
||||
add_handler(std::static_pointer_cast<http::http_pipeline_stage>(
|
||||
std::make_shared<oauth2::details::oauth2_handler>(client_config.oauth2())));
|
||||
}
|
||||
|
||||
const http_client_config & http_client::client_config() const
|
||||
{
|
||||
auto ph = std::static_pointer_cast<details::http_network_handler>(m_pipeline->last_stage());
|
||||
return ph->http_client_impl()->client_config();
|
||||
}
|
||||
|
||||
const uri & http_client::base_uri() const
|
||||
{
|
||||
auto ph = std::static_pointer_cast<details::http_network_handler>(m_pipeline->last_stage());
|
||||
return ph->http_client_impl()->base_uri();
|
||||
}
|
||||
|
||||
}}} // namespaces
|
179
3rdparty/cpprestsdk/include/cpprest/details/http_constants.dat
vendored
Normal file
179
3rdparty/cpprestsdk/include/cpprest/details/http_constants.dat
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
#ifdef _METHODS
|
||||
DAT(GET, _XPLATSTR("GET"))
|
||||
DAT(POST, _XPLATSTR("POST"))
|
||||
DAT(PUT, _XPLATSTR("PUT"))
|
||||
DAT(DEL, _XPLATSTR("DELETE"))
|
||||
DAT(HEAD, _XPLATSTR("HEAD"))
|
||||
DAT(OPTIONS, _XPLATSTR("OPTIONS"))
|
||||
DAT(TRCE, _XPLATSTR("TRACE"))
|
||||
DAT(CONNECT, _XPLATSTR("CONNECT"))
|
||||
DAT(MERGE, _XPLATSTR("MERGE"))
|
||||
DAT(PATCH, _XPLATSTR("PATCH"))
|
||||
#endif
|
||||
|
||||
#ifdef _PHRASES
|
||||
DAT(Continue, 100, _XPLATSTR("Continue"))
|
||||
DAT(SwitchingProtocols, 101, _XPLATSTR("Switching Protocols"))
|
||||
DAT(OK, 200, _XPLATSTR("OK"))
|
||||
DAT(Created, 201, _XPLATSTR("Created"))
|
||||
DAT(Accepted, 202, _XPLATSTR("Accepted"))
|
||||
DAT(NonAuthInfo, 203, _XPLATSTR("Non-Authoritative Information"))
|
||||
DAT(NoContent, 204, _XPLATSTR("No Content"))
|
||||
DAT(ResetContent, 205, _XPLATSTR("Reset Content"))
|
||||
DAT(PartialContent, 206, _XPLATSTR("Partial Content"))
|
||||
DAT(MultipleChoices, 300, _XPLATSTR("Multiple Choices"))
|
||||
DAT(MovedPermanently, 301, _XPLATSTR("Moved Permanently"))
|
||||
DAT(Found, 302, _XPLATSTR("Found"))
|
||||
DAT(SeeOther, 303, _XPLATSTR("See Other"))
|
||||
DAT(NotModified, 304, _XPLATSTR("Not Modified"))
|
||||
DAT(UseProxy, 305, _XPLATSTR("Use Proxy"))
|
||||
DAT(TemporaryRedirect, 307, _XPLATSTR("Temporary Redirect"))
|
||||
DAT(BadRequest, 400, _XPLATSTR("Bad Request"))
|
||||
DAT(Unauthorized, 401, _XPLATSTR("Unauthorized"))
|
||||
DAT(PaymentRequired, 402, _XPLATSTR("Payment Required"))
|
||||
DAT(Forbidden, 403, _XPLATSTR("Forbidden"))
|
||||
DAT(NotFound, 404, _XPLATSTR("Not Found"))
|
||||
DAT(MethodNotAllowed, 405, _XPLATSTR("Method Not Allowed"))
|
||||
DAT(NotAcceptable, 406, _XPLATSTR("Not Acceptable"))
|
||||
DAT(ProxyAuthRequired, 407, _XPLATSTR("Proxy Authentication Required"))
|
||||
DAT(RequestTimeout, 408, _XPLATSTR("Request Time-out"))
|
||||
DAT(Conflict, 409, _XPLATSTR("Conflict"))
|
||||
DAT(Gone, 410, _XPLATSTR("Gone"))
|
||||
DAT(LengthRequired, 411, _XPLATSTR("Length Required"))
|
||||
DAT(PreconditionFailed, 412, _XPLATSTR("Precondition Failed"))
|
||||
DAT(RequestEntityTooLarge, 413, _XPLATSTR("Request Entity Too Large"))
|
||||
DAT(RequestUriTooLarge, 414, _XPLATSTR("Request Uri Too Large"))
|
||||
DAT(UnsupportedMediaType, 415, _XPLATSTR("Unsupported Media Type"))
|
||||
DAT(RangeNotSatisfiable, 416, _XPLATSTR("Requested range not satisfiable"))
|
||||
DAT(ExpectationFailed, 417, _XPLATSTR("Expectation Failed"))
|
||||
DAT(InternalError, 500, _XPLATSTR("Internal Error"))
|
||||
DAT(NotImplemented, 501, _XPLATSTR("Not Implemented"))
|
||||
DAT(BadGateway, 502, _XPLATSTR("Bad Gateway"))
|
||||
DAT(ServiceUnavailable, 503, _XPLATSTR("Service Unavailable"))
|
||||
DAT(GatewayTimeout, 504, _XPLATSTR("Gateway Time-out"))
|
||||
DAT(HttpVersionNotSupported, 505, _XPLATSTR("HTTP Version not supported"))
|
||||
#endif // _PHRASES
|
||||
|
||||
#ifdef _HEADER_NAMES
|
||||
DAT(accept, "Accept")
|
||||
DAT(accept_charset, "Accept-Charset")
|
||||
DAT(accept_encoding, "Accept-Encoding")
|
||||
DAT(accept_language, "Accept-Language")
|
||||
DAT(accept_ranges, "Accept-Ranges")
|
||||
DAT(age, "Age")
|
||||
DAT(allow, "Allow")
|
||||
DAT(authorization, "Authorization")
|
||||
DAT(cache_control, "Cache-Control")
|
||||
DAT(connection, "Connection")
|
||||
DAT(content_encoding, "Content-Encoding")
|
||||
DAT(content_language, "Content-Language")
|
||||
DAT(content_length, "Content-Length")
|
||||
DAT(content_location, "Content-Location")
|
||||
DAT(content_md5, "Content-MD5")
|
||||
DAT(content_range, "Content-Range")
|
||||
DAT(content_type, "Content-Type")
|
||||
DAT(content_disposition, "Content-Disposition")
|
||||
DAT(date, "Date")
|
||||
DAT(etag, "ETag")
|
||||
DAT(expect, "Expect")
|
||||
DAT(expires, "Expires")
|
||||
DAT(from, "From")
|
||||
DAT(host, "Host")
|
||||
DAT(if_match, "If-Match")
|
||||
DAT(if_modified_since, "If-Modified-Since")
|
||||
DAT(if_none_match, "If-None-Match")
|
||||
DAT(if_range, "If-Range")
|
||||
DAT(if_unmodified_since, "If-Unmodified-Since")
|
||||
DAT(last_modified, "Last-Modified")
|
||||
DAT(location, "Location")
|
||||
DAT(max_forwards, "Max-Forwards")
|
||||
DAT(pragma, "Pragma")
|
||||
DAT(proxy_authenticate, "Proxy-Authenticate")
|
||||
DAT(proxy_authorization, "Proxy-Authorization")
|
||||
DAT(range, "Range")
|
||||
DAT(referer, "Referer")
|
||||
DAT(retry_after, "Retry-After")
|
||||
DAT(server, "Server")
|
||||
DAT(te, "TE")
|
||||
DAT(trailer, "Trailer")
|
||||
DAT(transfer_encoding, "Transfer-Encoding")
|
||||
DAT(upgrade, "Upgrade")
|
||||
DAT(user_agent, "User-Agent")
|
||||
DAT(vary, "Vary")
|
||||
DAT(via, "Via")
|
||||
DAT(warning, "Warning")
|
||||
DAT(www_authenticate, "WWW-Authenticate")
|
||||
#endif // _HEADER_NAMES
|
||||
|
||||
#ifdef _MIME_TYPES
|
||||
DAT(application_atom_xml, "application/atom+xml")
|
||||
DAT(application_http, "application/http")
|
||||
DAT(application_javascript, "application/javascript")
|
||||
DAT(application_json, "application/json")
|
||||
DAT(application_xjson, "application/x-json")
|
||||
DAT(application_octetstream, "application/octet-stream")
|
||||
DAT(application_x_www_form_urlencoded, "application/x-www-form-urlencoded")
|
||||
DAT(multipart_form_data, "multipart/form-data")
|
||||
DAT(boundary, "boundary")
|
||||
DAT(form_data, "form-data")
|
||||
DAT(application_xjavascript, "application/x-javascript")
|
||||
DAT(application_xml, "application/xml")
|
||||
DAT(message_http, "message/http")
|
||||
DAT(text, "text")
|
||||
DAT(text_javascript, "text/javascript")
|
||||
DAT(text_json, "text/json")
|
||||
DAT(text_plain, "text/plain")
|
||||
DAT(text_plain_utf16, "text/plain; charset=utf-16")
|
||||
DAT(text_plain_utf16le, "text/plain; charset=utf-16le")
|
||||
DAT(text_plain_utf8, "text/plain; charset=utf-8")
|
||||
DAT(text_xjavascript, "text/x-javascript")
|
||||
DAT(text_xjson, "text/x-json")
|
||||
#endif // _MIME_TYPES
|
||||
|
||||
#ifdef _CHARSET_TYPES
|
||||
DAT(ascii, "ascii")
|
||||
DAT(usascii, "us-ascii")
|
||||
DAT(latin1, "iso-8859-1")
|
||||
DAT(utf8, "utf-8")
|
||||
DAT(utf16, "utf-16")
|
||||
DAT(utf16le, "utf-16le")
|
||||
DAT(utf16be, "utf-16be")
|
||||
#endif // _CHARSET_TYPES
|
||||
|
||||
#ifdef _OAUTH1_METHODS
|
||||
DAT(hmac_sha1, _XPLATSTR("HMAC-SHA1"))
|
||||
DAT(plaintext, _XPLATSTR("PLAINTEXT"))
|
||||
#endif // _OAUTH1_METHODS
|
||||
|
||||
#ifdef _OAUTH1_STRINGS
|
||||
DAT(callback, "oauth_callback")
|
||||
DAT(callback_confirmed, "oauth_callback_confirmed")
|
||||
DAT(consumer_key, "oauth_consumer_key")
|
||||
DAT(nonce, "oauth_nonce")
|
||||
DAT(realm, "realm") // NOTE: No "oauth_" prefix.
|
||||
DAT(signature, "oauth_signature")
|
||||
DAT(signature_method, "oauth_signature_method")
|
||||
DAT(timestamp, "oauth_timestamp")
|
||||
DAT(token, "oauth_token")
|
||||
DAT(token_secret, "oauth_token_secret")
|
||||
DAT(verifier, "oauth_verifier")
|
||||
DAT(version, "oauth_version")
|
||||
#endif // _OAUTH1_STRINGS
|
||||
|
||||
#ifdef _OAUTH2_STRINGS
|
||||
DAT(access_token, "access_token")
|
||||
DAT(authorization_code, "authorization_code")
|
||||
DAT(bearer, "bearer")
|
||||
DAT(client_id, "client_id")
|
||||
DAT(client_secret, "client_secret")
|
||||
DAT(code, "code")
|
||||
DAT(expires_in, "expires_in")
|
||||
DAT(grant_type, "grant_type")
|
||||
DAT(redirect_uri, "redirect_uri")
|
||||
DAT(refresh_token, "refresh_token")
|
||||
DAT(response_type, "response_type")
|
||||
DAT(scope, "scope")
|
||||
DAT(state, "state")
|
||||
DAT(token, "token")
|
||||
DAT(token_type, "token_type")
|
||||
#endif // _OAUTH2_STRINGS
|
122
3rdparty/cpprestsdk/include/cpprest/details/http_helpers.h
vendored
Normal file
122
3rdparty/cpprestsdk/include/cpprest/details/http_helpers.h
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Implementation Details of the http.h layer of messaging
|
||||
*
|
||||
* Functions and types for interoperating with http.h from modern C++
|
||||
* This file includes windows definitions and should not be included in a public header
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web { namespace http
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constants for MIME types.
|
||||
/// </summary>
|
||||
class mime_types
|
||||
{
|
||||
public:
|
||||
#define _MIME_TYPES
|
||||
#define DAT(a,b) _ASYNCRTIMP const static utility::string_t a;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _MIME_TYPES
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constants for charset types.
|
||||
/// </summary>
|
||||
class charset_types
|
||||
{
|
||||
public:
|
||||
#define _CHARSET_TYPES
|
||||
#define DAT(a,b) _ASYNCRTIMP const static utility::string_t a;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _CHARSET_TYPES
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not the given content type is 'textual' according the feature specifications.
|
||||
/// </summary>
|
||||
bool is_content_type_textual(const utility::string_t &content_type);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not the given content type is JSON according the feature specifications.
|
||||
/// </summary>
|
||||
bool is_content_type_json(const utility::string_t &content_type);
|
||||
|
||||
/// <summary>
|
||||
/// Parses the given Content-Type header value to get out actual content type and charset.
|
||||
/// If the charset isn't specified the default charset for the content type will be set.
|
||||
/// </summary>
|
||||
void parse_content_type_and_charset(const utility::string_t &content_type, utility::string_t &content, utility::string_t &charset);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default charset for given content type. If the MIME type is not textual or recognized Latin1 will be returned.
|
||||
/// </summary>
|
||||
utility::string_t get_default_charset(const utility::string_t &content_type);
|
||||
|
||||
/// <summary>
|
||||
/// Helper functions to convert a series of bytes from a charset to utf-8 or utf-16.
|
||||
/// These APIs deal with checking for and handling byte order marker (BOM).
|
||||
/// </summary>
|
||||
utility::string_t convert_utf16_to_string_t(utf16string src);
|
||||
utf16string convert_utf16_to_utf16(utf16string src);
|
||||
std::string convert_utf16_to_utf8(utf16string src);
|
||||
utility::string_t convert_utf16le_to_string_t(utf16string src, bool erase_bom);
|
||||
std::string convert_utf16le_to_utf8(utf16string src, bool erase_bom);
|
||||
utility::string_t convert_utf16be_to_string_t(utf16string src, bool erase_bom);
|
||||
std::string convert_utf16be_to_utf8(utf16string src, bool erase_bom);
|
||||
utf16string convert_utf16be_to_utf16le(utf16string src, bool erase_bom);
|
||||
|
||||
// simple helper functions to trim whitespace.
|
||||
_ASYNCRTIMP void __cdecl ltrim_whitespace(utility::string_t &str);
|
||||
_ASYNCRTIMP void __cdecl rtrim_whitespace(utility::string_t &str);
|
||||
_ASYNCRTIMP void __cdecl trim_whitespace(utility::string_t &str);
|
||||
|
||||
bool validate_method(const utility::string_t& method);
|
||||
|
||||
|
||||
namespace chunked_encoding
|
||||
{
|
||||
// Transfer-Encoding: chunked support
|
||||
static const size_t additional_encoding_space = 12;
|
||||
static const size_t data_offset = additional_encoding_space-2;
|
||||
|
||||
// Add the data necessary for properly sending data with transfer-encoding: chunked.
|
||||
//
|
||||
// There are up to 12 additional bytes needed for each chunk:
|
||||
//
|
||||
// The last chunk requires 5 bytes, and is fixed.
|
||||
// All other chunks require up to 8 bytes for the length, and four for the two CRLF
|
||||
// delimiters.
|
||||
//
|
||||
_ASYNCRTIMP size_t __cdecl add_chunked_delimiters(_Out_writes_(buffer_size) uint8_t *data, _In_ size_t buffer_size, size_t bytes_read);
|
||||
}
|
||||
|
||||
}}}
|
81
3rdparty/cpprestsdk/include/cpprest/details/http_server.h
vendored
Normal file
81
3rdparty/cpprestsdk/include/cpprest/details/http_server.h
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: interface to implement HTTP server to service http_listeners.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
#error "Error: http server APIs are not supported in XP"
|
||||
#endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
|
||||
#include "cpprest/http_listener.h"
|
||||
|
||||
namespace web { namespace http
|
||||
{
|
||||
namespace experimental {
|
||||
namespace details
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Interface http listeners interact with for receiving and responding to http requests.
|
||||
/// </summary>
|
||||
class http_server
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Release any held resources.
|
||||
/// </summary>
|
||||
virtual ~http_server() { };
|
||||
|
||||
/// <summary>
|
||||
/// Start listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> start() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Registers an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> register_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> unregister_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Stop processing and listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> stop() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends the specified http response.
|
||||
/// </summary>
|
||||
/// <param name="response">The http_response to send.</param>
|
||||
/// <returns>A operation which is completed once the response has been sent.</returns>
|
||||
virtual pplx::task<void> respond(http::http_response response) = 0;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace experimental
|
||||
}} // namespace web::http
|
101
3rdparty/cpprestsdk/include/cpprest/details/http_server_api.h
vendored
Normal file
101
3rdparty/cpprestsdk/include/cpprest/details/http_server_api.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: exposes the entry points to the http server transport apis.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
#error "Error: http server APIs are not supported in XP"
|
||||
#endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "cpprest/http_listener.h"
|
||||
|
||||
namespace web { namespace http
|
||||
{
|
||||
namespace experimental {
|
||||
namespace details
|
||||
{
|
||||
|
||||
class http_server;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton class used to register for http requests and send responses.
|
||||
///
|
||||
/// The lifetime is tied to http listener registration. When the first listener registers an instance is created
|
||||
/// and when the last one unregisters the receiver stops and is destroyed. It can be started back up again if
|
||||
/// listeners are again registered.
|
||||
/// </summary>
|
||||
class http_server_api
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether or not any listeners are registered.
|
||||
/// </summary>
|
||||
static bool __cdecl has_listener();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a HTTP server API.
|
||||
/// </summary>
|
||||
static void __cdecl register_server_api(std::unique_ptr<http_server> server_api);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the http server API.
|
||||
/// </summary>
|
||||
static void __cdecl unregister_server_api();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a listener for HTTP requests and starts receiving.
|
||||
/// </summary>
|
||||
static pplx::task<void> __cdecl register_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the given listener and stops listening for HTTP requests.
|
||||
/// </summary>
|
||||
static pplx::task<void> __cdecl unregister_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Gets static HTTP server API. Could be null if no registered listeners.
|
||||
/// </summary>
|
||||
static http_server * __cdecl server_api();
|
||||
|
||||
private:
|
||||
|
||||
/// Used to lock access to the server api registration
|
||||
static pplx::extensibility::critical_section_t s_lock;
|
||||
|
||||
/// Registers a server API set -- this assumes the lock has already been taken
|
||||
static void unsafe_register_server_api(std::unique_ptr<http_server> server_api);
|
||||
|
||||
// Static instance of the HTTP server API.
|
||||
static std::unique_ptr<http_server> s_server_api;
|
||||
|
||||
/// Number of registered listeners;
|
||||
static pplx::details::atomic_long s_registrations;
|
||||
|
||||
// Static only class. No creation.
|
||||
http_server_api();
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
202
3rdparty/cpprestsdk/include/cpprest/details/http_server_asio.h
vendored
Normal file
202
3rdparty/cpprestsdk/include/cpprest/details/http_server_asio.h
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include <boost/asio.hpp>
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#include <boost/bind.hpp>
|
||||
#include <set>
|
||||
#include "pplx/threadpool.h"
|
||||
#include "cpprest/details/http_server.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace listener
|
||||
{
|
||||
|
||||
class http_linux_server;
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
struct linux_request_context : web::http::details::_http_server_context
|
||||
{
|
||||
linux_request_context(){}
|
||||
|
||||
pplx::task_completion_event<void> m_response_completed;
|
||||
|
||||
private:
|
||||
linux_request_context(const linux_request_context&);
|
||||
linux_request_context& operator=(const linux_request_context&);
|
||||
};
|
||||
|
||||
class hostport_listener;
|
||||
|
||||
class connection
|
||||
{
|
||||
private:
|
||||
std::unique_ptr<boost::asio::ip::tcp::socket> m_socket;
|
||||
boost::asio::streambuf m_request_buf;
|
||||
boost::asio::streambuf m_response_buf;
|
||||
http_linux_server* m_p_server;
|
||||
hostport_listener* m_p_parent;
|
||||
http_request m_request;
|
||||
size_t m_read, m_write;
|
||||
size_t m_read_size, m_write_size;
|
||||
bool m_close;
|
||||
bool m_chunked;
|
||||
std::atomic<int> m_refs; // track how many threads are still referring to this
|
||||
|
||||
public:
|
||||
connection(std::unique_ptr<boost::asio::ip::tcp::socket> socket, http_linux_server* server, hostport_listener* parent)
|
||||
: m_socket(std::move(socket))
|
||||
, m_request_buf()
|
||||
, m_response_buf()
|
||||
, m_p_server(server)
|
||||
, m_p_parent(parent)
|
||||
, m_refs(1)
|
||||
{
|
||||
start_request_response();
|
||||
}
|
||||
|
||||
connection(const connection&) = delete;
|
||||
connection& operator=(const connection&) = delete;
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
void start_request_response();
|
||||
void handle_http_line(const boost::system::error_code& ec);
|
||||
void handle_headers();
|
||||
void handle_body(const boost::system::error_code& ec);
|
||||
void handle_chunked_header(const boost::system::error_code& ec);
|
||||
void handle_chunked_body(const boost::system::error_code& ec, int toWrite);
|
||||
void dispatch_request_to_listener();
|
||||
void do_response(bool bad_request);
|
||||
template <typename ReadHandler>
|
||||
void async_read_until_buffersize(size_t size, const ReadHandler &handler);
|
||||
void async_process_response(http_response response);
|
||||
void cancel_sending_response_with_error(const http_response &response, const std::exception_ptr &);
|
||||
void handle_headers_written(const http_response &response, const boost::system::error_code& ec);
|
||||
void handle_write_large_response(const http_response &response, const boost::system::error_code& ec);
|
||||
void handle_write_chunked_response(const http_response &response, const boost::system::error_code& ec);
|
||||
void handle_response_written(const http_response &response, const boost::system::error_code& ec);
|
||||
void finish_request_response();
|
||||
};
|
||||
|
||||
class hostport_listener
|
||||
{
|
||||
private:
|
||||
friend class connection;
|
||||
|
||||
std::unique_ptr<boost::asio::ip::tcp::acceptor> m_acceptor;
|
||||
std::map<std::string, web::http::experimental::listener::details::http_listener_impl* > m_listeners;
|
||||
pplx::extensibility::reader_writer_lock_t m_listeners_lock;
|
||||
|
||||
pplx::extensibility::recursive_lock_t m_connections_lock;
|
||||
pplx::extensibility::event_t m_all_connections_complete;
|
||||
std::set<connection*> m_connections;
|
||||
|
||||
http_linux_server* m_p_server;
|
||||
|
||||
std::string m_host;
|
||||
std::string m_port;
|
||||
|
||||
public:
|
||||
hostport_listener(http_linux_server* server, const std::string& hostport)
|
||||
: m_acceptor()
|
||||
, m_listeners()
|
||||
, m_listeners_lock()
|
||||
, m_connections_lock()
|
||||
, m_connections()
|
||||
, m_p_server(server)
|
||||
{
|
||||
m_all_connections_complete.set();
|
||||
|
||||
std::istringstream hostport_in(hostport);
|
||||
hostport_in.imbue(std::locale::classic());
|
||||
|
||||
std::getline(hostport_in, m_host, ':');
|
||||
std::getline(hostport_in, m_port);
|
||||
}
|
||||
|
||||
~hostport_listener()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void add_listener(const std::string& path, web::http::experimental::listener::details::http_listener_impl* listener);
|
||||
void remove_listener(const std::string& path, web::http::experimental::listener::details::http_listener_impl* listener);
|
||||
|
||||
private:
|
||||
void on_accept(boost::asio::ip::tcp::socket* socket, const boost::system::error_code& ec);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct iequal_to
|
||||
{
|
||||
bool operator()(const std::string& left, const std::string& right) const
|
||||
{
|
||||
return boost::ilexicographical_compare(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
class http_linux_server : public web::http::experimental::details::http_server
|
||||
{
|
||||
private:
|
||||
friend class http::experimental::listener::details::connection;
|
||||
|
||||
pplx::extensibility::reader_writer_lock_t m_listeners_lock;
|
||||
std::map<std::string, std::unique_ptr<details::hostport_listener>, iequal_to> m_listeners;
|
||||
std::unordered_map<details::http_listener_impl *, std::unique_ptr<pplx::extensibility::reader_writer_lock_t>> m_registered_listeners;
|
||||
bool m_started;
|
||||
|
||||
public:
|
||||
http_linux_server()
|
||||
: m_listeners_lock()
|
||||
, m_listeners()
|
||||
, m_started(false)
|
||||
{}
|
||||
|
||||
~http_linux_server()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
virtual pplx::task<void> start();
|
||||
virtual pplx::task<void> stop();
|
||||
|
||||
virtual pplx::task<void> register_listener(web::http::experimental::listener::details::http_listener_impl* listener);
|
||||
virtual pplx::task<void> unregister_listener(web::http::experimental::listener::details::http_listener_impl* listener);
|
||||
|
||||
pplx::task<void> respond(http::http_response response);
|
||||
};
|
||||
|
||||
}}}}
|
250
3rdparty/cpprestsdk/include/cpprest/details/http_server_httpsys.h
vendored
Normal file
250
3rdparty/cpprestsdk/include/cpprest/details/http_server_httpsys.h
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: implementation of HTTP server API built on Windows HTTP Server APIs.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
#error "Error: http server APIs are not supported in XP"
|
||||
#endif //_WIN32_WINNT < _WIN32_WINNT_VISTA
|
||||
|
||||
// Windows Sockets are not code analysis clean.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 6386)
|
||||
#include <http.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#include "cpprest/details/http_server.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
|
||||
class http_windows_server;
|
||||
struct windows_request_context;
|
||||
|
||||
/// <summary>
|
||||
/// Class used to wrap OVERLAPPED I/O with any HTTP I/O.
|
||||
/// </summary>
|
||||
class http_overlapped : public OVERLAPPED
|
||||
{
|
||||
public:
|
||||
void set_http_io_completion(std::function<void(DWORD, DWORD)> http_io_completion)
|
||||
{
|
||||
ZeroMemory(this, sizeof(OVERLAPPED));
|
||||
m_http_io_completion = http_io_completion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback for all I/O completions.
|
||||
/// </summary>
|
||||
static void CALLBACK io_completion_callback(
|
||||
PTP_CALLBACK_INSTANCE instance,
|
||||
PVOID context,
|
||||
PVOID pOverlapped,
|
||||
ULONG result,
|
||||
ULONG_PTR numberOfBytesTransferred,
|
||||
PTP_IO io)
|
||||
{
|
||||
CASABLANCA_UNREFERENCED_PARAMETER(io);
|
||||
CASABLANCA_UNREFERENCED_PARAMETER(context);
|
||||
CASABLANCA_UNREFERENCED_PARAMETER(instance);
|
||||
|
||||
http_overlapped *p_http_overlapped = (http_overlapped *)pOverlapped;
|
||||
p_http_overlapped->m_http_io_completion(result, (DWORD) numberOfBytesTransferred);
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(DWORD, DWORD)> m_http_io_completion;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Context for http request through Windows HTTP Server API.
|
||||
/// </summary>
|
||||
struct windows_request_context : http::details::_http_server_context
|
||||
{
|
||||
windows_request_context();
|
||||
virtual ~windows_request_context();
|
||||
|
||||
// Asynchronously starts processing the current request.
|
||||
void async_process_request(HTTP_REQUEST_ID request_id, http::http_request msg, const unsigned long headers_size);
|
||||
|
||||
// Dispatch request to the provided http_listener.
|
||||
void dispatch_request_to_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
|
||||
|
||||
// Read in a portion of the request body.
|
||||
void read_request_body_chunk();
|
||||
|
||||
// Start processing the response.
|
||||
void async_process_response();
|
||||
|
||||
void transmit_body();
|
||||
|
||||
// Read request headers io completion callback function .
|
||||
void read_headers_io_completion(DWORD error_code, DWORD bytes_read);
|
||||
|
||||
// Read request body io completion callback function.
|
||||
void read_body_io_completion(DWORD error_code, DWORD bytes_read);
|
||||
|
||||
// Send response io completion callback function .
|
||||
void send_response_io_completion(DWORD error_code, DWORD bytes_read);
|
||||
|
||||
// Send response body io completion callback function.
|
||||
void send_response_body_io_completion(DWORD error_code, DWORD bytes_read);
|
||||
|
||||
// Cancel request io completion callback function.
|
||||
void cancel_request_io_completion(DWORD error_code, DWORD bytes_read);
|
||||
|
||||
// TCE that indicates the completion of response
|
||||
// Workaround for ppl task_completion_event bug.
|
||||
std::mutex m_responseCompletedLock;
|
||||
pplx::task_completion_event<void> m_response_completed;
|
||||
|
||||
// Id of the currently processed request on this connection.
|
||||
HTTP_REQUEST_ID m_request_id;
|
||||
|
||||
bool m_sending_in_chunks;
|
||||
bool m_transfer_encoding;
|
||||
|
||||
size_t m_remaining_to_write;
|
||||
|
||||
HTTP_REQUEST *m_request;
|
||||
std::unique_ptr<unsigned char[]> m_request_buffer;
|
||||
|
||||
std::unique_ptr<HTTP_UNKNOWN_HEADER []> m_headers;
|
||||
std::vector<std::string> m_headers_buffer;
|
||||
|
||||
http_overlapped m_overlapped;
|
||||
|
||||
http_request m_msg;
|
||||
http_response m_response;
|
||||
|
||||
std::exception_ptr m_except_ptr;
|
||||
private:
|
||||
windows_request_context(const windows_request_context &);
|
||||
windows_request_context& operator=(const windows_request_context &);
|
||||
|
||||
// Sends entity body chunk.
|
||||
void send_entity_body(_In_reads_(data_length) unsigned char * data, _In_ size_t data_length);
|
||||
|
||||
// Cancels this request.
|
||||
void cancel_request(std::exception_ptr except_ptr);
|
||||
|
||||
std::vector<unsigned char> m_body_data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Class to implement HTTP server API on Windows.
|
||||
/// </summary>
|
||||
class http_windows_server : public http_server
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a http_windows_server.
|
||||
/// </summary>
|
||||
http_windows_server();
|
||||
|
||||
/// <summary>
|
||||
/// Releases resources held.
|
||||
/// </summary>
|
||||
~http_windows_server();
|
||||
|
||||
/// <summary>
|
||||
/// Start listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> start();
|
||||
|
||||
/// <summary>
|
||||
/// Registers an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> register_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters an http listener.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> unregister_listener(_In_ web::http::experimental::listener::details::http_listener_impl *pListener);
|
||||
|
||||
/// <summary>
|
||||
/// Stop processing and listening for incoming requests.
|
||||
/// </summary>
|
||||
virtual pplx::task<void> stop();
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends the specified http response.
|
||||
/// </summary>
|
||||
/// <param name="response">The http_response to send.</param>
|
||||
/// <returns>A operation which is completed once the response has been sent.</returns>
|
||||
virtual pplx::task<void> respond(http::http_response response);
|
||||
|
||||
private:
|
||||
friend struct details::windows_request_context;
|
||||
|
||||
// Structure to hold each registered listener.
|
||||
class listener_registration
|
||||
{
|
||||
public:
|
||||
listener_registration(HTTP_URL_GROUP_ID urlGroupId)
|
||||
: m_urlGroupId(urlGroupId)
|
||||
{}
|
||||
|
||||
// URL group id for this listener. Each listener needs it own URL group
|
||||
// because configuration like timeouts, authentication, etc...
|
||||
HTTP_URL_GROUP_ID m_urlGroupId;
|
||||
|
||||
// Request handler lock to guard against removing a listener while in user code.
|
||||
pplx::extensibility::reader_writer_lock_t m_requestHandlerLock;
|
||||
};
|
||||
|
||||
// Registered listeners
|
||||
pplx::extensibility::reader_writer_lock_t _M_listenersLock;
|
||||
std::unordered_map<web::http::experimental::listener::details::http_listener_impl *, std::unique_ptr<listener_registration>> _M_registeredListeners;
|
||||
|
||||
// HTTP Server API server session id.
|
||||
HTTP_SERVER_SESSION_ID m_serverSessionId;
|
||||
|
||||
// Tracks the number of outstanding requests being processed.
|
||||
std::atomic<int> m_numOutstandingRequests;
|
||||
pplx::extensibility::event_t m_zeroOutstandingRequests;
|
||||
|
||||
// Handle to HTTP Server API request queue.
|
||||
HANDLE m_hRequestQueue;
|
||||
|
||||
// Threadpool I/O structure for overlapped I/O.
|
||||
TP_IO * m_threadpool_io;
|
||||
|
||||
// Task which actually handles receiving requests from HTTP Server API request queue.
|
||||
pplx::task<void> m_receivingTask;
|
||||
void receive_requests();
|
||||
};
|
||||
|
||||
} // namespace details;
|
||||
} // namespace experimental
|
||||
}} // namespace web::http
|
89
3rdparty/cpprestsdk/include/cpprest/details/nosal.h
vendored
Normal file
89
3rdparty/cpprestsdk/include/cpprest/details/nosal.h
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
***/
|
||||
|
||||
#pragma once
|
||||
// selected MS SAL annotations
|
||||
|
||||
#ifdef _In_
|
||||
#undef _In_
|
||||
#endif
|
||||
#define _In_
|
||||
|
||||
#ifdef _Inout_
|
||||
#undef _Inout_
|
||||
#endif
|
||||
#define _Inout_
|
||||
|
||||
#ifdef _Out_
|
||||
#undef _Out_
|
||||
#endif
|
||||
#define _Out_
|
||||
|
||||
#ifdef _In_z_
|
||||
#undef _In_z_
|
||||
#endif
|
||||
#define _In_z_
|
||||
|
||||
#ifdef _Out_z_
|
||||
#undef _Out_z_
|
||||
#endif
|
||||
#define _Out_z_
|
||||
|
||||
#ifdef _Inout_z_
|
||||
#undef _Inout_z_
|
||||
#endif
|
||||
#define _Inout_z_
|
||||
|
||||
#ifdef _In_opt_
|
||||
#undef _In_opt_
|
||||
#endif
|
||||
#define _In_opt_
|
||||
|
||||
#ifdef _Out_opt_
|
||||
#undef _Out_opt_
|
||||
#endif
|
||||
#define _Out_opt_
|
||||
|
||||
#ifdef _Inout_opt_
|
||||
#undef _Inout_opt_
|
||||
#endif
|
||||
#define _Inout_opt_
|
||||
|
||||
#ifdef _Out_writes_
|
||||
#undef _Out_writes_
|
||||
#endif
|
||||
#define _Out_writes_(x)
|
||||
|
||||
#ifdef _Out_writes_opt_
|
||||
#undef _Out_writes_opt_
|
||||
#endif
|
||||
#define _Out_writes_opt_(x)
|
||||
|
||||
#ifdef _In_reads_
|
||||
#undef _In_reads_
|
||||
#endif
|
||||
#define _In_reads_(x)
|
||||
|
||||
#ifdef _Inout_updates_bytes_
|
||||
#undef _Inout_updates_bytes_
|
||||
#endif
|
||||
#define _Inout_updates_bytes_(x)
|
14
3rdparty/cpprestsdk/include/cpprest/details/resource.h
vendored
Normal file
14
3rdparty/cpprestsdk/include/cpprest/details/resource.h
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Resource.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
215
3rdparty/cpprestsdk/include/cpprest/details/uri_parser.h
vendored
Normal file
215
3rdparty/cpprestsdk/include/cpprest/details/uri_parser.h
vendored
Normal file
|
@ -0,0 +1,215 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* URI parsing implementation
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace web { namespace details
|
||||
{
|
||||
namespace uri_parser
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Parses the uri, attempting to determine its validity.
|
||||
///
|
||||
/// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query')
|
||||
/// </summary>
|
||||
bool validate(const utility::string_t &encoded_string);
|
||||
|
||||
/// <summary>
|
||||
/// Parses the uri, setting each provided string to the value of that component. Components
|
||||
/// that are not part of the provided text are set to the empty string. Component strings
|
||||
/// DO NOT contain their beginning or ending delimiters.
|
||||
///
|
||||
/// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query')
|
||||
/// </summary>
|
||||
bool parse(const utility::string_t &encoded_string, uri_components &components);
|
||||
|
||||
/// <summary>
|
||||
/// Unreserved characters are those that are allowed in a URI but do not have a reserved purpose. They include:
|
||||
/// - A-Z
|
||||
/// - a-z
|
||||
/// - 0-9
|
||||
/// - '-' (hyphen)
|
||||
/// - '.' (period)
|
||||
/// - '_' (underscore)
|
||||
/// - '~' (tilde)
|
||||
/// </summary>
|
||||
inline bool is_unreserved(int c)
|
||||
{
|
||||
return ::utility::details::is_alnum((char)c) || c == '-' || c == '.' || c == '_' || c == '~';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// General delimiters serve as the delimiters between different uri components.
|
||||
/// General delimiters include:
|
||||
/// - All of these :/?#[]@
|
||||
/// </summary>
|
||||
inline bool is_gen_delim(int c)
|
||||
{
|
||||
return c == ':' || c == '/' || c == '?' || c == '#' || c == '[' || c == ']' || c == '@';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subdelimiters are those characters that may have a defined meaning within component
|
||||
/// of a uri for a particular scheme. They do not serve as delimiters in any case between
|
||||
/// uri segments. sub_delimiters include:
|
||||
/// - All of these !$&'()*+,;=
|
||||
/// </summary>
|
||||
inline bool is_sub_delim(int c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '!':
|
||||
case '$':
|
||||
case '&':
|
||||
case '\'':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
case ';':
|
||||
case '=':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reserved characters includes the general delimiters and sub delimiters. Some characters
|
||||
/// are neither reserved nor unreserved, and must be percent-encoded.
|
||||
/// </summary>
|
||||
inline bool is_reserved(int c)
|
||||
{
|
||||
return is_gen_delim(c) || is_sub_delim(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the scheme portion include:
|
||||
/// - Any alphanumeric character
|
||||
/// - '+' (plus)
|
||||
/// - '-' (hyphen)
|
||||
/// - '.' (period)
|
||||
///
|
||||
/// Note that the scheme must BEGIN with an alpha character.
|
||||
/// </summary>
|
||||
inline bool is_scheme_character(int c)
|
||||
{
|
||||
return ::utility::details::is_alnum((char)c) || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the user information portion include:
|
||||
/// - Any unreserved character
|
||||
/// - The percent character ('%'), and thus any percent-endcoded octet
|
||||
/// - The sub-delimiters
|
||||
/// - ':' (colon)
|
||||
/// </summary>
|
||||
inline bool is_user_info_character(int c)
|
||||
{
|
||||
return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the host portion include:
|
||||
/// - Any unreserved character
|
||||
/// - The percent character ('%'), and thus any percent-endcoded octet
|
||||
/// - The sub-delimiters
|
||||
/// - ':' (colon)
|
||||
/// - '[' (open bracket)
|
||||
/// - ']' (close bracket)
|
||||
/// </summary>
|
||||
inline bool is_host_character(int c)
|
||||
{
|
||||
return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == ':' || c == '[' || c == ']';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the authority portion include:
|
||||
/// - Any unreserved character
|
||||
/// - The percent character ('%'), and thus any percent-endcoded octet
|
||||
/// - The sub-delimiters
|
||||
/// - ':' (colon)
|
||||
///
|
||||
/// Note that we don't currently support:
|
||||
/// - IPv6 addresses (requires '[]')
|
||||
/// </summary>
|
||||
inline bool is_authority_character(int c)
|
||||
{
|
||||
return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '@' || c == ':';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the path portion include:
|
||||
/// - Any unreserved character
|
||||
/// - The percent character ('%'), and thus any percent-endcoded octet
|
||||
/// - The sub-delimiters
|
||||
/// - ':' (colon)
|
||||
/// - '@' (ampersand)
|
||||
/// </summary>
|
||||
inline bool is_path_character(int c)
|
||||
{
|
||||
return is_unreserved(c) || is_sub_delim(c) || c == '%' || c == '/' || c == ':' || c == '@';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the query portion include:
|
||||
/// - Any path character
|
||||
/// - '?' (question mark)
|
||||
/// </summary>
|
||||
inline bool is_query_character(int c)
|
||||
{
|
||||
return is_path_character(c) || c == '?';
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legal characters in the fragment portion include:
|
||||
/// - Any path character
|
||||
/// - '?' (question mark)
|
||||
/// </summary>
|
||||
inline bool is_fragment_character(int c)
|
||||
{
|
||||
// this is intentional, they have the same set of legal characters
|
||||
return is_query_character(c);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the uri, setting the given pointers to locations inside the given buffer.
|
||||
/// 'encoded' is expected to point to an encoded zero-terminated string containing a uri
|
||||
/// </summary>
|
||||
bool inner_parse(
|
||||
const utility::char_t *encoded,
|
||||
const utility::char_t **scheme_begin, const utility::char_t **scheme_end,
|
||||
const utility::char_t **uinfo_begin, const utility::char_t **uinfo_end,
|
||||
const utility::char_t **host_begin, const utility::char_t **host_end,
|
||||
_Out_ int *port,
|
||||
const utility::char_t **path_begin, const utility::char_t **path_end,
|
||||
const utility::char_t **query_begin, const utility::char_t **query_end,
|
||||
const utility::char_t **fragment_begin, const utility::char_t **fragment_end);
|
||||
}
|
||||
}}
|
248
3rdparty/cpprestsdk/include/cpprest/details/web_utilities.h
vendored
Normal file
248
3rdparty/cpprestsdk/include/cpprest/details/web_utilities.h
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* utility classes used by the different web:: clients
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
|
||||
namespace http { namespace client { namespace details {
|
||||
class winhttp_client;
|
||||
class winrt_client;
|
||||
}}}
|
||||
namespace websockets { namespace client { namespace details {
|
||||
class winrt_callback_client;
|
||||
class wspp_callback_client;
|
||||
}}}
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
class zero_memory_deleter
|
||||
{
|
||||
public:
|
||||
_ASYNCRTIMP void operator()(::utility::string_t *data) const;
|
||||
};
|
||||
typedef std::unique_ptr<::utility::string_t, zero_memory_deleter> plaintext_string;
|
||||
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(__cplusplus_winrt)
|
||||
#if !(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP && _MSC_VER < 1800)
|
||||
class winrt_encryption
|
||||
{
|
||||
public:
|
||||
winrt_encryption() {}
|
||||
_ASYNCRTIMP winrt_encryption(const std::wstring &data);
|
||||
_ASYNCRTIMP plaintext_string decrypt() const;
|
||||
private:
|
||||
::pplx::task<Windows::Storage::Streams::IBuffer ^> m_buffer;
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
class win32_encryption
|
||||
{
|
||||
public:
|
||||
win32_encryption() {}
|
||||
_ASYNCRTIMP win32_encryption(const std::wstring &data);
|
||||
_ASYNCRTIMP ~win32_encryption();
|
||||
_ASYNCRTIMP plaintext_string decrypt() const;
|
||||
private:
|
||||
std::vector<char> m_buffer;
|
||||
size_t m_numCharacters;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a set of user credentials (user name and password) to be used
|
||||
/// for authentication.
|
||||
/// </summary>
|
||||
class credentials
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructs an empty set of credentials without a user name or password.
|
||||
/// </summary>
|
||||
credentials() {}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs credentials from given user name and password.
|
||||
/// </summary>
|
||||
/// <param name="username">User name as a string.</param>
|
||||
/// <param name="password">Password as a string.</param>
|
||||
credentials(utility::string_t username, const utility::string_t & password) :
|
||||
m_username(std::move(username)),
|
||||
m_password(password)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// The user name associated with the credentials.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the user name.</returns>
|
||||
const utility::string_t &username() const { return m_username; }
|
||||
|
||||
/// <summary>
|
||||
/// The password for the user name associated with the credentials.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the password.</returns>
|
||||
CASABLANCA_DEPRECATED("This API is deprecated for security reasons to avoid unnecessary password copies stored in plaintext.")
|
||||
utility::string_t password() const
|
||||
{
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP && _MSC_VER < 1800
|
||||
return m_password;
|
||||
#else
|
||||
return utility::string_t(*m_password.decrypt());
|
||||
#endif
|
||||
#else
|
||||
return m_password;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if credentials have been set
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if user name and password is set, <c>false</c> otherwise.</returns>
|
||||
bool is_set() const { return !m_username.empty(); }
|
||||
|
||||
private:
|
||||
friend class http::client::details::winhttp_client;
|
||||
friend class http::client::details::winrt_client;
|
||||
friend class websockets::client::details::winrt_callback_client;
|
||||
friend class websockets::client::details::wspp_callback_client;
|
||||
|
||||
details::plaintext_string decrypt() const
|
||||
{
|
||||
// Encryption APIs not supported on Windows Phone 8.0 or XP
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP && _MSC_VER < 1800
|
||||
return details::plaintext_string(new ::utility::string_t(m_password));
|
||||
#else
|
||||
return m_password.decrypt();
|
||||
#endif
|
||||
#else
|
||||
return details::plaintext_string(new ::utility::string_t(m_password));
|
||||
#endif
|
||||
}
|
||||
|
||||
::utility::string_t m_username;
|
||||
|
||||
#if defined(_WIN32) && !defined(CPPREST_TARGET_XP)
|
||||
#if defined(__cplusplus_winrt)
|
||||
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP && _MSC_VER < 1800
|
||||
::utility::string_t m_password;
|
||||
#else
|
||||
details::winrt_encryption m_password;
|
||||
#endif
|
||||
#else
|
||||
details::win32_encryption m_password;
|
||||
#endif
|
||||
#else
|
||||
::utility::string_t m_password;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// web_proxy represents the concept of the web proxy, which can be auto-discovered,
|
||||
/// disabled, or specified explicitly by the user.
|
||||
/// </summary>
|
||||
class web_proxy
|
||||
{
|
||||
enum web_proxy_mode_internal{ use_default_, use_auto_discovery_, disabled_, user_provided_ };
|
||||
public:
|
||||
enum web_proxy_mode{ use_default = use_default_, use_auto_discovery = use_auto_discovery_, disabled = disabled_};
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a proxy with the default settings.
|
||||
/// </summary>
|
||||
web_proxy() : m_address(_XPLATSTR("")), m_mode(use_default_) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a proxy with specified mode.
|
||||
/// </summary>
|
||||
/// <param name="mode">Mode to use.</param>
|
||||
web_proxy( web_proxy_mode mode ) : m_address(_XPLATSTR("")), m_mode(static_cast<web_proxy_mode_internal>(mode)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a proxy explicitly with provided address.
|
||||
/// </summary>
|
||||
/// <param name="address">Proxy URI to use.</param>
|
||||
web_proxy( uri address ) : m_address(address), m_mode(user_provided_) {}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this proxy's URI address. Returns an empty URI if not explicitly set by user.
|
||||
/// </summary>
|
||||
/// <returns>A reference to this proxy's URI.</returns>
|
||||
const uri& address() const { return m_address; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the credentials used for authentication with this proxy.
|
||||
/// </summary>
|
||||
/// <returns>Credentials to for this proxy.</returns>
|
||||
const web::credentials& credentials() const { return m_credentials; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the credentials to use for authentication with this proxy.
|
||||
/// </summary>
|
||||
/// <param name="cred">Credentials to use for this proxy.</param>
|
||||
void set_credentials(web::credentials cred) {
|
||||
if( m_mode == disabled_ )
|
||||
{
|
||||
throw std::invalid_argument("Cannot attach credentials to a disabled proxy");
|
||||
}
|
||||
m_credentials = std::move(cred);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this proxy was constructed with default settings.
|
||||
/// </summary>
|
||||
/// <returns>True if default, false otherwise.</param>
|
||||
bool is_default() const { return m_mode == use_default_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if using a proxy is disabled.
|
||||
/// </summary>
|
||||
/// <returns>True if disabled, false otherwise.</returns>
|
||||
bool is_disabled() const { return m_mode == disabled_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the auto discovery protocol, WPAD, is to be used.
|
||||
/// </summary>
|
||||
/// <returns>True if auto discovery enabled, false otherwise.</returns>
|
||||
bool is_auto_discovery() const { return m_mode == use_auto_discovery_; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a proxy address is explicitly specified by the user.
|
||||
/// </summary>
|
||||
/// <returns>True if a proxy address was explicitly specified, false otherwise.</returns>
|
||||
bool is_specified() const { return m_mode == user_provided_; }
|
||||
|
||||
private:
|
||||
web::uri m_address;
|
||||
web_proxy_mode_internal m_mode;
|
||||
web::credentials m_credentials;
|
||||
};
|
||||
|
||||
}
|
57
3rdparty/cpprestsdk/include/cpprest/details/x509_cert_utilities.h
vendored
Normal file
57
3rdparty/cpprestsdk/include/cpprest/details/x509_cert_utilities.h
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Contains utility functions for helping to verify server certificates in OS X/iOS and Android.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#if defined(__APPLE__) || (defined(ANDROID) || defined(__ANDROID__)) || (defined(_WIN32) && !defined(__cplusplus_winrt) && !defined(_M_ARM) && !defined(CPPREST_EXCLUDE_WEBSOCKETS))
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#endif
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace web { namespace http { namespace client { namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// Using platform specific APIs verifies server certificate.
|
||||
/// Currently implemented to work on iOS, Android, and OS X.
|
||||
/// </summary>
|
||||
/// <param name="verifyCtx">Boost.ASIO context get certificate chain from.</param>
|
||||
/// <param name="hostName">Host name from the URI.</param>
|
||||
/// <returns>True if verification passed and server can be trusted, false otherwise.</returns>
|
||||
bool verify_cert_chain_platform_specific(boost::asio::ssl::verify_context &verifyCtx, const std::string &hostName);
|
||||
|
||||
bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std::string &hostName);
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
1132
3rdparty/cpprestsdk/include/cpprest/filestream.h
vendored
Normal file
1132
3rdparty/cpprestsdk/include/cpprest/filestream.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
670
3rdparty/cpprestsdk/include/cpprest/http_client.h
vendored
Normal file
670
3rdparty/cpprestsdk/include/cpprest/http_client.h
vendored
Normal file
|
@ -0,0 +1,670 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Client-side APIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_HTTP_CLIENT_H
|
||||
#define _CASA_HTTP_CLIENT_H
|
||||
|
||||
#if defined (__cplusplus_winrt)
|
||||
#if !defined(__WRL_NO_DEFAULT_LIB__)
|
||||
#define __WRL_NO_DEFAULT_LIB__
|
||||
#endif
|
||||
#include <wrl.h>
|
||||
#include <msxml6.h>
|
||||
namespace web { namespace http{namespace client{
|
||||
typedef IXMLHTTPRequest2* native_handle;}}}
|
||||
#else
|
||||
namespace web { namespace http{namespace client{
|
||||
typedef void* native_handle;}}}
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
#if !defined(CPPREST_TARGET_XP) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP || _MSC_VER > 1700)
|
||||
#include "cpprest/oauth1.h"
|
||||
#endif
|
||||
|
||||
#include "cpprest/oauth2.h"
|
||||
|
||||
/// The web namespace contains functionality common to multiple protocols like HTTP and WebSockets.
|
||||
namespace web
|
||||
{
|
||||
/// Declarations and functionality for the HTTP protocol.
|
||||
namespace http
|
||||
{
|
||||
/// HTTP client side library.
|
||||
namespace client
|
||||
{
|
||||
|
||||
// credentials and web_proxy class has been moved from web::http::client namespace to web namespace.
|
||||
// The below using declarations ensure we don't break existing code.
|
||||
// Please use the web::credentials and web::web_proxy class going forward.
|
||||
using web::credentials;
|
||||
using web::web_proxy;
|
||||
|
||||
/// <summary>
|
||||
/// HTTP client configuration class, used to set the possible configuration options
|
||||
/// used to create an http_client instance.
|
||||
/// </summary>
|
||||
class http_client_config
|
||||
{
|
||||
public:
|
||||
http_client_config() :
|
||||
m_guarantee_order(false),
|
||||
m_timeout(utility::seconds(30)),
|
||||
m_chunksize(0)
|
||||
#if !defined(__cplusplus_winrt)
|
||||
, m_validate_certificates(true)
|
||||
#endif
|
||||
, m_set_user_nativehandle_options([](native_handle)->void{})
|
||||
#if defined(_WIN32) && !defined(__cplusplus_winrt)
|
||||
, m_buffer_request(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(CPPREST_TARGET_XP) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP || _MSC_VER > 1700)
|
||||
/// <summary>
|
||||
/// Get OAuth 1.0 configuration.
|
||||
/// </summary>
|
||||
/// <returns>Shared pointer to OAuth 1.0 configuration.</returns>
|
||||
const std::shared_ptr<oauth1::experimental::oauth1_config> oauth1() const
|
||||
{
|
||||
return m_oauth1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set OAuth 1.0 configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">OAuth 1.0 configuration to set.</param>
|
||||
void set_oauth1(oauth1::experimental::oauth1_config config)
|
||||
{
|
||||
m_oauth1 = std::make_shared<oauth1::experimental::oauth1_config>(std::move(config));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Get OAuth 2.0 configuration.
|
||||
/// </summary>
|
||||
/// <returns>Shared pointer to OAuth 2.0 configuration.</returns>
|
||||
const std::shared_ptr<oauth2::experimental::oauth2_config> oauth2() const
|
||||
{
|
||||
return m_oauth2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set OAuth 2.0 configuration.
|
||||
/// </summary>
|
||||
/// <param name="config">OAuth 2.0 configuration to set.</param>
|
||||
void set_oauth2(oauth2::experimental::oauth2_config config)
|
||||
{
|
||||
m_oauth2 = std::make_shared<oauth2::experimental::oauth2_config>(std::move(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const
|
||||
{
|
||||
return m_proxy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(web_proxy proxy)
|
||||
{
|
||||
m_proxy = std::move(proxy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the client credentials
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client credentials.</returns>
|
||||
const http::client::credentials& credentials() const
|
||||
{
|
||||
return m_credentials;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the client credentials
|
||||
/// </summary>
|
||||
/// <param name="cred">A reference to the client credentials.</param>
|
||||
void set_credentials(const http::client::credentials& cred)
|
||||
{
|
||||
m_credentials = cred;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the 'guarantee order' property
|
||||
/// </summary>
|
||||
/// <returns>The value of the property.</returns>
|
||||
bool guarantee_order() const
|
||||
{
|
||||
return m_guarantee_order;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the 'guarantee order' property
|
||||
/// </summary>
|
||||
/// <param name="guarantee_order">The value of the property.</param>
|
||||
CASABLANCA_DEPRECATED("Confusing API will be removed in future releases. If you need to order HTTP requests use task continuations.")
|
||||
void set_guarantee_order(bool guarantee_order)
|
||||
{
|
||||
m_guarantee_order = guarantee_order;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in seconds) used for each send and receive operation on the client.</returns>
|
||||
utility::seconds timeout() const
|
||||
{
|
||||
return m_timeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout (in seconds) used for each send and receive operation on the client.</param>
|
||||
void set_timeout(const utility::seconds &timeout)
|
||||
{
|
||||
m_timeout = timeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the client chunk size.
|
||||
/// </summary>
|
||||
/// <returns>The internal buffer size used by the http client when sending and receiving data from the network.</returns>
|
||||
size_t chunksize() const
|
||||
{
|
||||
return m_chunksize == 0 ? 64 * 1024 : m_chunksize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the client chunk size.
|
||||
/// </summary>
|
||||
/// <param name="size">The internal buffer size used by the http client when sending and receiving data from the network.</param>
|
||||
/// <remarks>This is a hint -- an implementation may disregard the setting and use some other chunk size.</remarks>
|
||||
void set_chunksize(size_t size)
|
||||
{
|
||||
m_chunksize = size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the default chunk size is in use.
|
||||
/// <remarks>If true, implementations are allowed to choose whatever size is best.</remarks>
|
||||
/// </summary>
|
||||
/// <returns>True if default, false if set by user.</returns>
|
||||
bool is_default_chunksize() const
|
||||
{
|
||||
return m_chunksize == 0;
|
||||
}
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Gets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <returns>True if certificates are to be verified, false otherwise.</returns>
|
||||
bool validate_certificates() const
|
||||
{
|
||||
return m_validate_certificates;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the server certificate validation property.
|
||||
/// </summary>
|
||||
/// <param name="validate_certs">False to turn ignore all server certificate validation errors, true otherwise.</param>
|
||||
/// <remarks>Note ignoring certificate errors can be dangerous and should be done with caution.</remarks>
|
||||
void set_validate_certificates(bool validate_certs)
|
||||
{
|
||||
m_validate_certificates = validate_certs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Checks if request data buffering is turned on, the default is off.
|
||||
/// </summary>
|
||||
/// <returns>True if buffering is enabled, false otherwise</returns>
|
||||
bool buffer_request() const
|
||||
{
|
||||
return m_buffer_request;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the request buffering property.
|
||||
/// If true, in cases where the request body/stream doesn't support seeking the request data will be buffered.
|
||||
/// This can help in situations where an authentication challenge might be expected.
|
||||
/// </summary>
|
||||
/// <param name="buffer_request">True to turn on buffer, false otherwise.</param>
|
||||
/// <remarks>Please note there is a performance cost due to copying the request data.</remarks>
|
||||
void set_buffer_request(bool buffer_request)
|
||||
{
|
||||
m_buffer_request = buffer_request;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of platform specific options.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The native_handle is the following type depending on the underlying platform:
|
||||
/// Windows Desktop, WinHTTP - HINTERNET
|
||||
/// Windows Runtime, WinRT - IXMLHTTPRequest2 *
|
||||
/// All other platforms, Boost.Asio:
|
||||
/// https - boost::asio::ssl::stream<boost::asio::ip::tcp::socket &> *
|
||||
/// http - boost::asio::ip::tcp::socket *
|
||||
/// </remarks>
|
||||
/// <param name="callback">A user callback allowing for customization of the request</param>
|
||||
void set_nativehandle_options(const std::function<void(native_handle)> &callback)
|
||||
{
|
||||
m_set_user_nativehandle_options = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a user's callback to allow for customization of the request.
|
||||
/// </summary>
|
||||
/// <param name="handle">A internal implementation handle.</param>
|
||||
void invoke_nativehandle_options(native_handle handle) const
|
||||
{
|
||||
m_set_user_nativehandle_options(handle);
|
||||
}
|
||||
|
||||
private:
|
||||
#if !defined(CPPREST_TARGET_XP) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP || _MSC_VER > 1700)
|
||||
std::shared_ptr<oauth1::experimental::oauth1_config> m_oauth1;
|
||||
#endif
|
||||
|
||||
std::shared_ptr<oauth2::experimental::oauth2_config> m_oauth2;
|
||||
web_proxy m_proxy;
|
||||
http::client::credentials m_credentials;
|
||||
// Whether or not to guarantee ordering, i.e. only using one underlying TCP connection.
|
||||
bool m_guarantee_order;
|
||||
|
||||
utility::seconds m_timeout;
|
||||
size_t m_chunksize;
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
// IXmlHttpRequest2 doesn't allow configuration of certificate verification.
|
||||
bool m_validate_certificates;
|
||||
#endif
|
||||
|
||||
std::function<void(native_handle)> m_set_user_nativehandle_options;
|
||||
|
||||
#if defined(_WIN32) && !defined(__cplusplus_winrt)
|
||||
bool m_buffer_request;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// HTTP client class, used to maintain a connection to an HTTP service for an extended session.
|
||||
/// </summary>
|
||||
class http_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new http_client connected to specified uri.
|
||||
/// </summary>
|
||||
/// <param name="base_uri">A string representation of the base uri to be used for all requests. Must start with either "http://" or "https://"</param>
|
||||
_ASYNCRTIMP http_client(const uri &base_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new http_client connected to specified uri.
|
||||
/// </summary>
|
||||
/// <param name="base_uri">A string representation of the base uri to be used for all requests. Must start with either "http://" or "https://"</param>
|
||||
/// <param name="client_config">The http client configuration object containing the possible configuration options to initialize the <c>http_client</c>. </param>
|
||||
_ASYNCRTIMP http_client(const uri &base_uri, const http_client_config &client_config);
|
||||
|
||||
/// <summary>
|
||||
/// Note the destructor doesn't necessarily close the connection and release resources.
|
||||
/// The connection is reference counted with the http_responses.
|
||||
/// </summary>
|
||||
~http_client() CPPREST_NOEXCEPT {}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base URI.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A base URI initialized in constructor
|
||||
/// </returns>
|
||||
_ASYNCRTIMP const uri& base_uri() const;
|
||||
|
||||
/// <summary>
|
||||
/// Get client configuration object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
_ASYNCRTIMP const http_client_config& client_config() const;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an HTTP pipeline stage to the client.
|
||||
/// </summary>
|
||||
/// <param name="handler">A function object representing the pipeline stage.</param>
|
||||
void add_handler(const std::function<pplx::task<http_response>(http_request, std::shared_ptr<http::http_pipeline_stage>)> &handler)
|
||||
{
|
||||
m_pipeline->append(std::make_shared<::web::http::details::function_pipeline_wrapper>(handler));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an HTTP pipeline stage to the client.
|
||||
/// </summary>
|
||||
/// <param name="stage">A shared pointer to a pipeline stage.</param>
|
||||
void add_handler(const std::shared_ptr<http::http_pipeline_stage> &stage)
|
||||
{
|
||||
m_pipeline->append(stage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="request">Request to send.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
_ASYNCRTIMP pplx::task<http_response> request(http_request request, const pplx::cancellation_token &token = pplx::cancellation_token::none());
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(const method &mtd, const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body_data">The data to be used as the message body, represented using the json object library.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const json::value &body_data,
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body_data);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="content_type">A string holding the MIME type of the message body.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf8string &path_query_fragment,
|
||||
const utf8string &body_data,
|
||||
const utf8string &content_type = "text/plain; charset=utf-8",
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(body_data, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="content_type">A string holding the MIME type of the message body.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf8string &path_query_fragment,
|
||||
utf8string &&body_data,
|
||||
const utf8string &content_type = "text/plain; charset=utf-8",
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(std::move(body_data), content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-16 will perform conversion to UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="content_type">A string holding the MIME type of the message body.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf16string &path_query_fragment,
|
||||
const utf16string &body_data,
|
||||
const utf16string &content_type = ::utility::conversions::to_utf16string("text/plain"),
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(body_data, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf8string &path_query_fragment,
|
||||
const utf8string &body_data,
|
||||
const pplx::cancellation_token &token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body_data, "text/plain; charset=utf-8", token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes the
|
||||
/// character encoding of the string is UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf8string &path_query_fragment,
|
||||
utf8string &&body_data,
|
||||
const pplx::cancellation_token &token)
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(::utility::conversions::to_string_t(path_query_fragment));
|
||||
msg.set_body(std::move(body_data), "text/plain; charset=utf-8");
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request with a string body. Assumes
|
||||
/// the character encoding of the string is UTF-16 will perform conversion to UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body_data">String containing the text to use in the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>An asynchronous operation that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utf16string &path_query_fragment,
|
||||
const utf16string &body_data,
|
||||
const pplx::cancellation_token &token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body_data, ::utility::conversions::to_utf16string("text/plain"), token);
|
||||
}
|
||||
|
||||
#if !defined (__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body">An asynchronous stream representing the body data.</param>
|
||||
/// <param name="content_type">A string holding the MIME type of the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>A task that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const concurrency::streams::istream &body,
|
||||
const utility::string_t &content_type = _XPLATSTR("application/octet-stream"),
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body">An asynchronous stream representing the body data.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>A task that is completed once a response from the request is received.</returns>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const concurrency::streams::istream &body,
|
||||
const pplx::cancellation_token &token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body, _XPLATSTR("application/octet-stream"), token);
|
||||
}
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body">An asynchronous stream representing the body data.</param>
|
||||
/// <param name="content_length">Size of the message body.</param>
|
||||
/// <param name="content_type">A string holding the MIME type of the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>A task that is completed once a response from the request is received.</returns>
|
||||
/// <remarks>Winrt requires to provide content_length.</remarks>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const concurrency::streams::istream &body,
|
||||
size_t content_length,
|
||||
const utility::string_t &content_type = _XPLATSTR("application/octet-stream"),
|
||||
const pplx::cancellation_token &token = pplx::cancellation_token::none())
|
||||
{
|
||||
http_request msg(mtd);
|
||||
msg.set_request_uri(path_query_fragment);
|
||||
msg.set_body(body, content_length, content_type);
|
||||
return request(msg, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously sends an HTTP request.
|
||||
/// </summary>
|
||||
/// <param name="mtd">HTTP request method.</param>
|
||||
/// <param name="path_query_fragment">String containing the path, query, and fragment, relative to the http_client's base URI.</param>
|
||||
/// <param name="body">An asynchronous stream representing the body data.</param>
|
||||
/// <param name="content_length">Size of the message body.</param>
|
||||
/// <param name="token">Cancellation token for cancellation of this request operation.</param>
|
||||
/// <returns>A task that is completed once a response from the request is received.</returns>
|
||||
/// <remarks>Winrt requires to provide content_length.</remarks>
|
||||
pplx::task<http_response> request(
|
||||
const method &mtd,
|
||||
const utility::string_t &path_query_fragment,
|
||||
const concurrency::streams::istream &body,
|
||||
size_t content_length,
|
||||
const pplx::cancellation_token &token)
|
||||
{
|
||||
return request(mtd, path_query_fragment, body, content_length, _XPLATSTR("application/octet-stream"), token);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void build_pipeline(const uri &base_uri, const http_client_config &client_config);
|
||||
|
||||
std::shared_ptr<::web::http::http_pipeline> m_pipeline;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
331
3rdparty/cpprestsdk/include/cpprest/http_headers.h
vendored
Normal file
331
3rdparty/cpprestsdk/include/cpprest/http_headers.h
vendored
Normal file
|
@ -0,0 +1,331 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
namespace web { namespace http {
|
||||
|
||||
/// <summary>
|
||||
/// Binds an individual reference to a string value.
|
||||
/// </summary>
|
||||
/// <typeparam name="key_type">The type of string value.</typeparam>
|
||||
/// <typeparam name="_t">The type of the value to bind to.</typeparam>
|
||||
/// <param name="text">The string value.</param>
|
||||
/// <param name="ref">The value to bind to.</param>
|
||||
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
||||
template<typename key_type, typename _t>
|
||||
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, std::istringstream instead.")
|
||||
bool bind(const key_type &text, _t &ref) // const
|
||||
{
|
||||
utility::istringstream_t iss(text);
|
||||
iss >> ref;
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds an individual reference to a string value.
|
||||
/// This specialization is need because <c>istringstream::>></c> delimits on whitespace.
|
||||
/// </summary>
|
||||
/// <typeparam name="key_type">The type of the string value.</typeparam>
|
||||
/// <param name="text">The string value.</param>
|
||||
/// <param name="ref">The value to bind to.</param>
|
||||
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
||||
template <typename key_type>
|
||||
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release.")
|
||||
bool bind(const key_type &text, utility::string_t &ref) //const
|
||||
{
|
||||
ref = text;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents HTTP headers, acts like a map.
|
||||
/// </summary>
|
||||
class http_headers
|
||||
{
|
||||
public:
|
||||
/// Function object to perform case insensitive comparison of wstrings.
|
||||
struct _case_insensitive_cmp
|
||||
{
|
||||
bool operator()(const utility::string_t &str1, const utility::string_t &str2) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return _wcsicmp(str1.c_str(), str2.c_str()) < 0;
|
||||
#else
|
||||
return utility::cmp::icmp(str1, str2) < 0;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// STL-style typedefs
|
||||
/// </summary>
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::key_type key_type;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::key_compare key_compare;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::allocator_type allocator_type;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::size_type size_type;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::difference_type difference_type;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::pointer pointer;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::const_pointer const_pointer;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::reference reference;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::const_reference const_reference;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::iterator iterator;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::const_iterator const_iterator;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::reverse_iterator reverse_iterator;
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp>::const_reverse_iterator const_reverse_iterator;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an empty set of HTTP headers.
|
||||
/// </summary>
|
||||
http_headers() {}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
||||
http_headers(const http_headers &other) : m_headers(other.m_headers) {}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
||||
http_headers &operator=(const http_headers &other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
m_headers = other.m_headers;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
||||
http_headers(http_headers &&other) : m_headers(std::move(other.m_headers)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
||||
http_headers &operator=(http_headers &&other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
m_headers = std::move(other.m_headers);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a header field using the '<<' operator.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <param name="value">The value of the header field.</param>
|
||||
/// <remarks>If the header field exists, the value will be combined as comma separated string.</remarks>
|
||||
template<typename _t1>
|
||||
void add(const key_type& name, const _t1& value)
|
||||
{
|
||||
if (has(name))
|
||||
{
|
||||
m_headers[name] = m_headers[name].append(_XPLATSTR(", ") + utility::conversions::print_string(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_headers[name] = utility::conversions::print_string(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a header field.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
void remove(const key_type& name)
|
||||
{
|
||||
m_headers.erase(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all elements from the headers.
|
||||
/// </summary>
|
||||
void clear() { m_headers.clear(); }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there is a header with the given key.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <returns><c>true</c> if there is a header with the given name, <c>false</c> otherwise.</returns>
|
||||
bool has(const key_type& name) const { return m_headers.find(name) != m_headers.end(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of header fields.
|
||||
/// </summary>
|
||||
/// <returns>Number of header fields.</returns>
|
||||
size_type size() const { return m_headers.size(); }
|
||||
|
||||
/// <summary>
|
||||
/// Tests to see if there are any header fields.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c> if there are no headers, <c>false</c> otherwise.</returns>
|
||||
bool empty() const { return m_headers.empty(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a reference to header field with given name, if there is no header field one is inserted.
|
||||
/// </summary>
|
||||
utility::string_t & operator[](const key_type &name) { return m_headers[name]; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a header field exists with given name and returns an iterator if found. Otherwise
|
||||
/// and iterator to end is returned.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <returns>An iterator to where the HTTP header is found.</returns>
|
||||
iterator find(const key_type &name) { return m_headers.find(name); }
|
||||
const_iterator find(const key_type &name) const { return m_headers.find(name); }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to match a header field with the given name using the '>>' operator.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the header field.</param>
|
||||
/// <param name="value">The value of the header field.</param>
|
||||
/// <returns><c>true</c> if header field was found and successfully stored in value parameter.</returns>
|
||||
template<typename _t1>
|
||||
bool match(const key_type &name, _t1 &value) const
|
||||
{
|
||||
auto iter = m_headers.find(name);
|
||||
if (iter != m_headers.end())
|
||||
{
|
||||
// Check to see if doesn't have a value.
|
||||
if(iter->second.empty())
|
||||
{
|
||||
bind_impl(iter->second, value);
|
||||
return true;
|
||||
}
|
||||
return bind_impl(iter->second, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an iterator referring to the first header field.
|
||||
/// </summary>
|
||||
/// <returns>An iterator to the beginning of the HTTP headers</returns>
|
||||
iterator begin() { return m_headers.begin(); }
|
||||
const_iterator begin() const { return m_headers.begin(); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an iterator referring to the past-the-end header field.
|
||||
/// </summary>
|
||||
/// <returns>An iterator to the element past the end of the HTTP headers.</returns>
|
||||
iterator end() { return m_headers.end(); }
|
||||
const_iterator end() const { return m_headers.end(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content length of the message.
|
||||
/// </summary>
|
||||
/// <returns>The length of the content.</returns>
|
||||
_ASYNCRTIMP utility::size64_t content_length() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content length of the message.
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the content.</param>
|
||||
_ASYNCRTIMP void set_content_length(utility::size64_t length);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of the message.
|
||||
/// </summary>
|
||||
/// <returns>The content type of the body.</returns>
|
||||
_ASYNCRTIMP utility::string_t content_type() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the content type of the message.
|
||||
/// </summary>
|
||||
/// <param name="type">The content type of the body.</param>
|
||||
_ASYNCRTIMP void set_content_type(utility::string_t type);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache control header of the message.
|
||||
/// </summary>
|
||||
/// <returns>The cache control header value.</returns>
|
||||
_ASYNCRTIMP utility::string_t cache_control() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the cache control header of the message.
|
||||
/// </summary>
|
||||
/// <param name="control">The cache control header value.</param>
|
||||
_ASYNCRTIMP void set_cache_control(utility::string_t control);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date header of the message.
|
||||
/// </summary>
|
||||
/// <returns>The date header value.</returns>
|
||||
_ASYNCRTIMP utility::string_t date() const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the date header of the message.
|
||||
/// </summary>
|
||||
/// <param name="date">The date header value.</param>
|
||||
_ASYNCRTIMP void set_date(const utility::datetime& date);
|
||||
|
||||
private:
|
||||
|
||||
template<typename _t>
|
||||
bool bind_impl(const key_type &text, _t &ref) const
|
||||
{
|
||||
utility::istringstream_t iss(text);
|
||||
iss.imbue(std::locale::classic());
|
||||
iss >> ref;
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bind_impl(const key_type &text, ::utility::string_t &ref) const
|
||||
{
|
||||
ref = text;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Headers are stored in a map with case insensitive key.
|
||||
std::map<utility::string_t, utility::string_t, _case_insensitive_cmp> m_headers;
|
||||
};
|
||||
|
||||
}}
|
314
3rdparty/cpprestsdk/include/cpprest/http_listener.h
vendored
Normal file
314
3rdparty/cpprestsdk/include/cpprest/http_listener.h
vendored
Normal file
|
@ -0,0 +1,314 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: HTTP listener (server-side) APIs
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_HTTP_LISTENER_H
|
||||
#define _CASA_HTTP_LISTENER_H
|
||||
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt))
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
/// HTTP listener is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
/// HTTP server side library.
|
||||
namespace listener
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Configuration class used to set various options when constructing and http_listener instance.
|
||||
/// </summary>
|
||||
class http_listener_config
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Create an http_listener configuration with default options.
|
||||
/// </summary>
|
||||
http_listener_config()
|
||||
: m_timeout(utility::seconds(120))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener_config to copy.</param>
|
||||
http_listener_config(const http_listener_config &other)
|
||||
: m_timeout(other.m_timeout)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// <summary>
|
||||
/// <param name="other">http_listener_config to move from.</param>
|
||||
http_listener_config(http_listener_config &&other)
|
||||
: m_timeout(std::move(other.m_timeout))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <returns>http_listener_config instance.</returns>
|
||||
http_listener_config & operator=(const http_listener_config &rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
m_timeout = rhs.m_timeout;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator.
|
||||
/// </summary>
|
||||
/// <returns>http_listener_config instance.</returns>
|
||||
http_listener_config & operator=(http_listener_config &&rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
m_timeout = std::move(rhs.m_timeout);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in seconds).</returns>
|
||||
utility::seconds timeout() const
|
||||
{
|
||||
return m_timeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout (in seconds) used for each send and receive operation on the client.</param>
|
||||
void set_timeout(utility::seconds timeout)
|
||||
{
|
||||
m_timeout = std::move(timeout);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
utility::seconds m_timeout;
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Internal class for pointer to implementation design pattern.
|
||||
/// </summary>
|
||||
class http_listener_impl
|
||||
{
|
||||
public:
|
||||
|
||||
http_listener_impl()
|
||||
: m_closed(true)
|
||||
, m_close_task(pplx::task_from_result())
|
||||
{
|
||||
}
|
||||
|
||||
_ASYNCRTIMP http_listener_impl(http::uri address);
|
||||
_ASYNCRTIMP http_listener_impl(http::uri address, http_listener_config config);
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> open();
|
||||
_ASYNCRTIMP pplx::task<void> close();
|
||||
|
||||
/// <summary>
|
||||
/// Handler for all requests. The HTTP host uses this to dispatch a message to the pipeline.
|
||||
/// </summary>
|
||||
/// <remarks>Only HTTP server implementations should call this API.</remarks>
|
||||
_ASYNCRTIMP void handle_request(http::http_request msg);
|
||||
|
||||
const http::uri & uri() const { return m_uri; }
|
||||
|
||||
const http_listener_config & configuration() const { return m_config; }
|
||||
|
||||
// Handlers
|
||||
std::function<void(http::http_request)> m_all_requests;
|
||||
std::map<http::method, std::function<void(http::http_request)>> m_supported_methods;
|
||||
|
||||
private:
|
||||
|
||||
// Default implementation for TRACE and OPTIONS.
|
||||
void handle_trace(http::http_request message);
|
||||
void handle_options(http::http_request message);
|
||||
|
||||
// Gets a comma separated string containing the methods supported by this listener.
|
||||
utility::string_t get_supported_methods() const;
|
||||
|
||||
http::uri m_uri;
|
||||
http_listener_config m_config;
|
||||
|
||||
// Used to record that the listener is closed.
|
||||
bool m_closed;
|
||||
pplx::task<void> m_close_task;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A class for listening and processing HTTP requests at a specific URI.
|
||||
/// </summary>
|
||||
class http_listener
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Create a listener from a URI.
|
||||
/// </summary>
|
||||
/// <remarks>The listener will not have been opened when returned.</remarks>
|
||||
/// <param name="address">URI at which the listener should accept requests.</param>
|
||||
http_listener(http::uri address)
|
||||
: m_impl(utility::details::make_unique<details::http_listener_impl>(std::move(address)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a listener with specified URI and configuration.
|
||||
/// </summary>
|
||||
/// <param name="address">URI at which the listener should accept requests.</param>
|
||||
/// <param name="config">Configuration to create listener with.</param>
|
||||
http_listener(http::uri address, http_listener_config config)
|
||||
: m_impl(utility::details::make_unique<details::http_listener_impl>(std::move(address), std::move(config)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
/// <remarks>The resulting listener cannot be used for anything, but is useful to initialize a variable
|
||||
/// that will later be overwritten with a real listener instance.</remarks>
|
||||
http_listener()
|
||||
: m_impl(utility::details::make_unique<details::http_listener_impl>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor frees any held resources.
|
||||
/// </summary>
|
||||
/// <remarks>Call close() before allowing a listener to be destroyed.</remarks>
|
||||
_ASYNCRTIMP ~http_listener();
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously open the listener, i.e. start accepting requests.
|
||||
/// </summary>
|
||||
/// <returns>A task that will be completed once this listener is actually opened, accepting requests.</returns>
|
||||
pplx::task<void> open()
|
||||
{
|
||||
return m_impl->open();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously stop accepting requests and close all connections.
|
||||
/// </summary>
|
||||
/// <returns>A task that will be completed once this listener is actually closed, no longer accepting requests.</returns>
|
||||
/// <remarks>
|
||||
/// This function will stop accepting requests and wait for all outstanding handler calls
|
||||
/// to finish before completing the task. Waiting on the task returned from close() within
|
||||
/// a handler and blocking waiting for its result will result in a deadlock.
|
||||
///
|
||||
/// Call close() before allowing a listener to be destroyed.
|
||||
/// </remarks>
|
||||
pplx::task<void> close()
|
||||
{
|
||||
return m_impl->close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a general handler to support all requests.
|
||||
/// </summary>
|
||||
/// <param name="handler">Function object to be called for all requests.</param>
|
||||
void support(const std::function<void(http_request)> &handler)
|
||||
{
|
||||
m_impl->m_all_requests = handler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add support for a specific HTTP method.
|
||||
/// </summary>
|
||||
/// <param name="method">An HTTP method.</param>
|
||||
/// <param name="handler">Function object to be called for all requests for the given HTTP method.</param>
|
||||
void support(const http::method &method, const std::function<void(http_request)> &handler)
|
||||
{
|
||||
m_impl->m_supported_methods[method] = handler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the URI of the listener.
|
||||
/// </summary>
|
||||
/// <returns>The URI this listener is for.</returns>
|
||||
const http::uri & uri() const { return m_impl->uri(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the configuration of this listener.
|
||||
/// </summary>
|
||||
/// <returns>Configuration this listener was constructed with.</returns>
|
||||
const http_listener_config & configuration() const { return m_impl->configuration(); }
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener instance to construct this one from.</param>
|
||||
http_listener(http_listener &&other)
|
||||
: m_impl(std::move(other.m_impl))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator.
|
||||
/// </summary>
|
||||
/// <param name="other">http_listener to replace this one with.</param>
|
||||
http_listener &operator=(http_listener &&other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
m_impl = std::move(other.m_impl);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// No copying of listeners.
|
||||
http_listener(const http_listener &other);
|
||||
http_listener &operator=(const http_listener &other);
|
||||
|
||||
std::unique_ptr<details::http_listener_impl> m_impl;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
#endif
|
1463
3rdparty/cpprestsdk/include/cpprest/http_msg.h
vendored
Normal file
1463
3rdparty/cpprestsdk/include/cpprest/http_msg.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
536
3rdparty/cpprestsdk/include/cpprest/interopstream.h
vendored
Normal file
536
3rdparty/cpprestsdk/include/cpprest/interopstream.h
vendored
Normal file
|
@ -0,0 +1,536 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Adapter classes for async and STD stream buffers, used to connect std-based and async-based APIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4250)
|
||||
#endif
|
||||
|
||||
namespace Concurrency { namespace streams {
|
||||
|
||||
template<typename CharType> class stdio_ostream;
|
||||
template<typename CharType> class stdio_istream;
|
||||
|
||||
namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// The basic_stdio_buffer class serves to support interoperability with STL stream buffers.
|
||||
/// Sitting atop a std::streambuf, which does all the I/O, instances of this class may read
|
||||
/// and write data to standard iostreams. The class itself should not be used in application
|
||||
/// code, it is used by the stream definitions farther down in the header file.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_stdio_buffer : public streambuf_state_manager<_CharType>
|
||||
{
|
||||
typedef concurrency::streams::char_traits<_CharType> traits;
|
||||
typedef typename traits::int_type int_type;
|
||||
typedef typename traits::pos_type pos_type;
|
||||
typedef typename traits::off_type off_type;
|
||||
/// <summary>
|
||||
/// Private constructor
|
||||
/// </summary>
|
||||
basic_stdio_buffer(_In_ std::basic_streambuf<_CharType>* streambuf, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<_CharType>(mode), m_buffer(streambuf)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_stdio_buffer()
|
||||
{
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
private:
|
||||
//
|
||||
// The functions overridden below here are documented elsewhere.
|
||||
// See astreambuf.h for further information.
|
||||
//
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
virtual bool has_size() const { return false; }
|
||||
|
||||
virtual size_t in_avail() const { return (size_t)m_buffer->in_avail(); }
|
||||
|
||||
virtual size_t buffer_size(std::ios_base::openmode) const { return 0; }
|
||||
virtual void set_buffer_size(size_t, std::ios_base::openmode) { return; }
|
||||
|
||||
virtual pplx::task<bool> _sync() { return pplx::task_from_result(m_buffer->pubsync() == 0); }
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch) { return pplx::task_from_result(m_buffer->sputc(ch)); }
|
||||
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t size) { return pplx::task_from_result((size_t)m_buffer->sputn(ptr, size)); }
|
||||
|
||||
size_t _sgetn(_Out_writes_ (size) _CharType *ptr, _In_ size_t size) const { return m_buffer->sgetn(ptr, size); }
|
||||
virtual size_t _scopy(_Out_writes_ (size) _CharType *, _In_ size_t size) { (void)(size); return (size_t)-1; }
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_ (size) _CharType *ptr, _In_ size_t size) { return pplx::task_from_result((size_t)m_buffer->sgetn(ptr, size)); }
|
||||
|
||||
virtual int_type _sbumpc() { return m_buffer->sbumpc(); }
|
||||
virtual int_type _sgetc() { return m_buffer->sgetc(); }
|
||||
|
||||
virtual pplx::task<int_type> _bumpc() { return pplx::task_from_result<int_type>(m_buffer->sbumpc()); }
|
||||
virtual pplx::task<int_type> _getc() { return pplx::task_from_result<int_type>(m_buffer->sgetc()); }
|
||||
virtual pplx::task<int_type> _nextc() { return pplx::task_from_result<int_type>(m_buffer->snextc()); }
|
||||
virtual pplx::task<int_type> _ungetc() { return pplx::task_from_result<int_type>(m_buffer->sungetc()); }
|
||||
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const { return m_buffer->pubseekoff(0, std::ios_base::cur, mode); }
|
||||
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode) { return m_buffer->pubseekpos(pos, mode); }
|
||||
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode) { return m_buffer->pubseekoff(off, dir, mode); }
|
||||
|
||||
virtual _CharType* _alloc(size_t) { return nullptr; }
|
||||
virtual void _commit(size_t) {}
|
||||
|
||||
virtual bool acquire(_CharType*&, size_t&) { return false; }
|
||||
virtual void release(_CharType *, size_t) { }
|
||||
|
||||
template<typename CharType> friend class concurrency::streams::stdio_ostream;
|
||||
template<typename CharType> friend class concurrency::streams::stdio_istream;
|
||||
|
||||
std::basic_streambuf<_CharType>* m_buffer;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// stdio_ostream represents an async ostream derived from a standard synchronous stream, as
|
||||
/// defined by the "std" namespace. It is constructed from a reference to a standard stream, which
|
||||
/// must be valid for the lifetime of the asynchronous stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the <c>stdio_ostream</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// Since std streams are not reference-counted, great care must be taken by an application to make
|
||||
/// sure that the std stream does not get destroyed until all uses of the asynchronous stream are
|
||||
/// done and have been serviced.
|
||||
/// </remarks>
|
||||
template<typename CharType>
|
||||
class stdio_ostream : public basic_ostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source output stream.
|
||||
/// </typeparam>
|
||||
/// <param name="stream">The synchronous stream that this is using for its I/O</param>
|
||||
template <typename AlterCharType>
|
||||
stdio_ostream(std::basic_ostream<AlterCharType>& stream)
|
||||
: basic_ostream<CharType>(streams::streambuf<AlterCharType>(std::shared_ptr<details::basic_stdio_buffer<AlterCharType>>(new details::basic_stdio_buffer<AlterCharType>(stream.rdbuf(), std::ios_base::out))))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
stdio_ostream(const stdio_ostream &other) : basic_ostream<CharType>(other) { }
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
/// <returns>A reference to the output stream object that contains the result of the assignment.</returns>
|
||||
stdio_ostream & operator =(const stdio_ostream &other) { basic_ostream<CharType>::operator=(other); return *this; }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// stdio_istream represents an async istream derived from a standard synchronous stream, as
|
||||
/// defined by the "std" namespace. It is constructed from a reference to a standard stream, which
|
||||
/// must be valid for the lifetime of the asynchronous stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the <c>stdio_istream</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// Since std streams are not reference-counted, great care must be taken by an application to make
|
||||
/// sure that the std stream does not get destroyed until all uses of the asynchronous stream are
|
||||
/// done and have been serviced.
|
||||
/// </remarks>
|
||||
template<typename CharType>
|
||||
class stdio_istream : public basic_istream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>istream</c>
|
||||
/// </typeparam>
|
||||
/// <param name="stream">The synchronous stream that this is using for its I/O</param>
|
||||
template <typename AlterCharType>
|
||||
stdio_istream(std::basic_istream<AlterCharType>& stream)
|
||||
: basic_istream<CharType>(streams::streambuf<AlterCharType>(std::shared_ptr<details::basic_stdio_buffer<AlterCharType>>(new details::basic_stdio_buffer<AlterCharType>(stream.rdbuf(), std::ios_base::in))))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
stdio_istream(const stdio_istream &other) : basic_istream<CharType>(other) { }
|
||||
|
||||
/// <summary>
|
||||
/// Assignment operator
|
||||
/// </summary>
|
||||
/// <param name="other">The source object</param>
|
||||
/// <returns>A reference to the input stream object that contains the result of the assignment.</returns>
|
||||
stdio_istream & operator =(const stdio_istream &other) { basic_istream<CharType>::operator=(other); return *this; }
|
||||
};
|
||||
|
||||
namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// IO streams stream buffer implementation used to interface with an async streambuffer underneath.
|
||||
/// Used for implementing the standard synchronous streams that provide interop between std:: and concurrency::streams::
|
||||
/// </summary>
|
||||
template<typename CharType>
|
||||
class basic_async_streambuf : public std::basic_streambuf<CharType>
|
||||
{
|
||||
public:
|
||||
typedef concurrency::streams::char_traits<CharType> traits;
|
||||
typedef typename traits::int_type int_type;
|
||||
typedef typename traits::pos_type pos_type;
|
||||
typedef typename traits::off_type off_type;
|
||||
|
||||
basic_async_streambuf(const streams::streambuf<CharType> &async_buf) : m_buffer(async_buf)
|
||||
{
|
||||
}
|
||||
protected:
|
||||
|
||||
//
|
||||
// The following are the functions in std::basic_streambuf that we need to override.
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Writes one byte to the stream buffer.
|
||||
/// </summary>
|
||||
int_type overflow(int_type ch)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.putc(CharType(ch)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one byte from the stream buffer without moving the read position.
|
||||
/// </summary>
|
||||
int_type underflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.getc().get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets one byte from the stream buffer and move the read position one character.
|
||||
/// </summary>
|
||||
int_type uflow()
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.bumpc().get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return traits::eof();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a number of characters from the buffer and place it into the provided memory block.
|
||||
/// </summary>
|
||||
std::streamsize xsgetn(_Out_writes_ (count) CharType* ptr, _In_ std::streamsize count)
|
||||
{
|
||||
size_t cnt = size_t(count);
|
||||
size_t read_so_far = 0;
|
||||
|
||||
try
|
||||
{
|
||||
while (read_so_far < cnt)
|
||||
{
|
||||
size_t rd = m_buffer.getn(ptr+read_so_far, cnt-read_so_far).get();
|
||||
read_so_far += rd;
|
||||
if ( rd == 0 )
|
||||
break;
|
||||
}
|
||||
return read_so_far;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a given number of characters from the provided block into the stream buffer.
|
||||
/// </summary>
|
||||
std::streamsize xsputn(const CharType* ptr, std::streamsize count)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.putn_nocopy(ptr, static_cast<size_t>(count)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronizes with the underlying medium.
|
||||
/// </summary>
|
||||
int sync() // must be int as per std::basic_streambuf
|
||||
{
|
||||
try
|
||||
{
|
||||
m_buffer.sync().wait();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given offset relative to the beginning, end, or current position.
|
||||
/// </summary>
|
||||
pos_type seekoff(off_type offset,
|
||||
std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( dir == std::ios_base::cur && offset == 0) // Special case for getting the current position.
|
||||
return m_buffer.getpos(mode);
|
||||
return m_buffer.seekoff(offset,dir,mode);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return (pos_type(-1));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given offset relative to the beginning of the stream.
|
||||
/// </summary>
|
||||
pos_type seekpos(pos_type pos,
|
||||
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_buffer.seekpos(pos, mode);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return (pos_type(-1));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
concurrency::streams::streambuf<CharType> m_buffer;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL ostream which relies on an asynchronous stream for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_ostream : public std::basic_ostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source ostream.
|
||||
/// </typeparam>
|
||||
/// <param name="astream">The asynchronous stream whose stream buffer should be used for I/O</param>
|
||||
template <typename AlterCharType>
|
||||
async_ostream(const streams::basic_ostream<AlterCharType> &astream)
|
||||
: std::basic_ostream<CharType>(&m_strbuf),
|
||||
m_strbuf(astream.streambuf())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>streambuf</c>.
|
||||
/// </typeparam>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
template <typename AlterCharType>
|
||||
async_ostream(const streams::streambuf<AlterCharType> &strbuf)
|
||||
: std::basic_ostream<CharType>(&m_strbuf),
|
||||
m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL istream which relies on an asynchronous stream for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_istream : public std::basic_istream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source istream.
|
||||
/// </typeparam>
|
||||
/// <param name="astream">The asynchronous stream whose stream buffer should be used for I/O</param>
|
||||
template <typename AlterCharType>
|
||||
async_istream(const streams::basic_istream<AlterCharType> &astream)
|
||||
: std::basic_istream<CharType>(&m_strbuf),
|
||||
m_strbuf(astream.streambuf())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <typeparam name="AlterCharType">
|
||||
/// The data type of the basic element of the source <c>streambuf</c>.
|
||||
/// </typeparam>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
template <typename AlterCharType>
|
||||
async_istream(const streams::streambuf<AlterCharType> &strbuf)
|
||||
: std::basic_istream<CharType>(&m_strbuf),
|
||||
m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A concrete STL istream which relies on an asynchronous stream buffer for its I/O.
|
||||
/// </summary>
|
||||
/// <typeparam name="CharType">
|
||||
/// The data type of the basic element of the stream.
|
||||
/// </typeparam>
|
||||
template<typename CharType>
|
||||
class async_iostream : public std::basic_iostream<CharType>
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="strbuf">The asynchronous stream buffer to use for I/O</param>
|
||||
async_iostream(const streams::streambuf<CharType> &strbuf)
|
||||
: std::basic_iostream<CharType>(&m_strbuf),
|
||||
m_strbuf(strbuf)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
details::basic_async_streambuf<CharType> m_strbuf;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus_winrt)
|
||||
|
||||
/// <summary>
|
||||
/// Static class containing factory functions for WinRT streams implemented on top of Casablanca async streams.
|
||||
/// </summary>
|
||||
/// <remarks>WinRT streams are defined in terms of single-byte characters only.</remarks>
|
||||
class winrt_stream
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IInputStream</c> reference from an asynchronous stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream buffer based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IInputStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer passed in must allow reading.
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can pass data to a WinRT component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IInputStream^ __cdecl create_input_stream(const concurrency::streams::streambuf<uint8_t> &buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IOutputStream</c> reference from an asynchronous stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream buffer based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IOutputStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer passed in must allow writing.
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can retrieve data from a WinRT component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IOutputStream^ __cdecl create_output_stream(const concurrency::streams::streambuf<uint8_t> &buffer);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a WinRT <c>IRandomAccessStream reference from an asynchronous input stream.
|
||||
/// </summary>
|
||||
/// <param name="buffer">A stream based on a single-byte character.</param>
|
||||
/// <returns>A reference to a WinRT <c>IRandomAccessStream</c>.</returns>
|
||||
/// <remarks>
|
||||
/// The stream buffer is shared with the caller, allowing data to be passed between the two contexts. For
|
||||
/// example, using a <c>producer_consumer_buffer</c>, a Casablanca-based caller can pass data to and retrieve data
|
||||
/// from a WinRT component.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP static Windows::Storage::Streams::IRandomAccessStream^ __cdecl create_random_access_stream(const concurrency::streams::streambuf<uint8_t> &buffer);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(pop)
|
||||
#endif
|
1936
3rdparty/cpprestsdk/include/cpprest/json.h
vendored
Normal file
1936
3rdparty/cpprestsdk/include/cpprest/json.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
577
3rdparty/cpprestsdk/include/cpprest/oauth1.h
vendored
Normal file
577
3rdparty/cpprestsdk/include/cpprest/oauth1.h
vendored
Normal file
|
@ -0,0 +1,577 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 1.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_OAUTH1_H
|
||||
#define _CASA_OAUTH1_H
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
}
|
||||
|
||||
/// oAuth 1.0 library.
|
||||
namespace oauth1
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
|
||||
class oauth1_handler;
|
||||
|
||||
// State currently used by oauth1_config to authenticate request.
|
||||
// The state varies for every request (due to timestamp and nonce).
|
||||
// The state also contains extra transmitted protocol parameters during
|
||||
// authorization flow (i.e. 'oauth_callback' or 'oauth_verifier').
|
||||
class oauth1_state
|
||||
{
|
||||
public:
|
||||
oauth1_state(utility::string_t timestamp, utility::string_t nonce,
|
||||
utility::string_t extra_key=utility::string_t(),
|
||||
utility::string_t extra_value=utility::string_t()) :
|
||||
m_timestamp(std::move(timestamp)),
|
||||
m_nonce(std::move(nonce)),
|
||||
m_extra_key(std::move(extra_key)),
|
||||
m_extra_value(std::move(extra_value))
|
||||
{}
|
||||
|
||||
const utility::string_t& timestamp() const { return m_timestamp; }
|
||||
void set_timestamp(utility::string_t timestamp) { m_timestamp = std::move(timestamp); }
|
||||
|
||||
const utility::string_t& nonce() const { return m_nonce; }
|
||||
void set_nonce(utility::string_t nonce) { m_nonce = std::move(nonce); }
|
||||
|
||||
const utility::string_t& extra_key() const { return m_extra_key; }
|
||||
void set_extra_key(utility::string_t key) { m_extra_key = std::move(key); }
|
||||
|
||||
const utility::string_t& extra_value() const { return m_extra_value; }
|
||||
void set_extra_value(utility::string_t value) { m_extra_value = std::move(value); }
|
||||
|
||||
private:
|
||||
utility::string_t m_timestamp;
|
||||
utility::string_t m_nonce;
|
||||
utility::string_t m_extra_key;
|
||||
utility::string_t m_extra_value;
|
||||
};
|
||||
|
||||
// Constant strings for OAuth 1.0.
|
||||
typedef utility::string_t oauth1_string;
|
||||
class oauth1_strings
|
||||
{
|
||||
public:
|
||||
#define _OAUTH1_STRINGS
|
||||
#define DAT(a_, b_) _ASYNCRTIMP static const oauth1_string a_;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH1_STRINGS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
} // namespace web::http::oauth1::details
|
||||
|
||||
/// oAuth functionality is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constant strings for OAuth 1.0 signature methods.
|
||||
/// </summary>
|
||||
typedef utility::string_t oauth1_method;
|
||||
class oauth1_methods
|
||||
{
|
||||
public:
|
||||
#define _OAUTH1_METHODS
|
||||
#define DAT(a,b) _ASYNCRTIMP static const oauth1_method a;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH1_METHODS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Exception type for OAuth 1.0 errors.
|
||||
/// </summary>
|
||||
class oauth1_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
oauth1_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
|
||||
~oauth1_exception() CPPREST_NOEXCEPT {}
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 1.0 token and associated information.
|
||||
/// </summary>
|
||||
class oauth1_token
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a OAuth1 token from a given access token and secret.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string.</param>
|
||||
/// <param name="secret">Token secret string.</param>
|
||||
oauth1_token(utility::string_t access_token, utility::string_t secret) :
|
||||
m_token(std::move(access_token)),
|
||||
m_secret(std::move(secret))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Get access token validity state.
|
||||
/// If true, token is a valid access token.
|
||||
/// </summary>
|
||||
/// <returns>Access token validity state of the token.</returns>
|
||||
bool is_valid_access_token() const { return !(access_token().empty() || secret().empty()); }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token.
|
||||
/// </summary>
|
||||
/// <returns>The access token string.</returns>
|
||||
const utility::string_t& access_token() const { return m_token; }
|
||||
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(utility::string_t &&access_token) { m_token = std::move(access_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(const utility::string_t &access_token) { m_token = access_token; }
|
||||
|
||||
/// <summary>
|
||||
/// Get token secret.
|
||||
/// </summary>
|
||||
/// <returns>Token secret string.</returns>
|
||||
const utility::string_t& secret() const { return m_secret; }
|
||||
|
||||
/// <summary>
|
||||
/// Set token secret.
|
||||
/// </summary>
|
||||
/// <param name="secret">Token secret string to set.</param>
|
||||
void set_secret(utility::string_t &&secret) { m_secret = std::move(secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Set token secret.
|
||||
/// </summary>
|
||||
/// <param name="secret">Token secret string to set.</param>
|
||||
void set_secret(const utility::string_t &secret) { m_secret = secret; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves any additional parameters.
|
||||
/// </summary>
|
||||
/// <returns>A map containing the additional parameters.</returns>
|
||||
const std::map<utility::string_t, utility::string_t> &additional_parameters() const { return m_additional_parameters; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets a specific parameter additional parameter.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Parameter name.</param>
|
||||
/// <param name="paramValue">Parameter value.</param>
|
||||
void set_additional_parameter(utility::string_t &¶mName, utility::string_t &¶mValue)
|
||||
{
|
||||
m_additional_parameters[std::move(paramName)] = std::move(paramValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a specific parameter additional parameter.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Parameter name.</param>
|
||||
/// <param name="paramValue">Parameter value.</param>
|
||||
void set_additional_parameter(const utility::string_t ¶mName, const utility::string_t ¶mValue)
|
||||
{
|
||||
m_additional_parameters[paramName] = paramValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all additional parameters.
|
||||
/// </summary>
|
||||
void clear_additional_parameters() { m_additional_parameters.clear(); }
|
||||
|
||||
private:
|
||||
friend class oauth1_config;
|
||||
|
||||
oauth1_token() {}
|
||||
|
||||
utility::string_t m_token;
|
||||
utility::string_t m_secret;
|
||||
std::map<utility::string_t, utility::string_t> m_additional_parameters;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 1.0 configuration class.
|
||||
/// </summary>
|
||||
class oauth1_config
|
||||
{
|
||||
public:
|
||||
oauth1_config(utility::string_t consumer_key, utility::string_t consumer_secret,
|
||||
utility::string_t temp_endpoint, utility::string_t auth_endpoint,
|
||||
utility::string_t token_endpoint, utility::string_t callback_uri,
|
||||
oauth1_method method, utility::string_t realm=utility::string_t()) :
|
||||
m_consumer_key(std::move(consumer_key)),
|
||||
m_consumer_secret(std::move(consumer_secret)),
|
||||
m_temp_endpoint(std::move(temp_endpoint)),
|
||||
m_auth_endpoint(std::move(auth_endpoint)),
|
||||
m_token_endpoint(std::move(token_endpoint)),
|
||||
m_callback_uri(std::move(callback_uri)),
|
||||
m_realm(std::move(realm)),
|
||||
m_method(std::move(method)),
|
||||
m_is_authorization_completed(false)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Builds an authorization URI to be loaded in a web browser/view.
|
||||
/// The URI is built with auth_endpoint() as basis.
|
||||
/// The method creates a task for HTTP request to first obtain a
|
||||
/// temporary token. The authorization URI build based on this token.
|
||||
/// </summary>
|
||||
/// <returns>Authorization URI to be loaded in a web browser/view.</returns>
|
||||
_ASYNCRTIMP pplx::task<utility::string_t> build_authorization_uri();
|
||||
|
||||
/// <summary>
|
||||
/// Fetch an access token based on redirected URI.
|
||||
/// The URI is expected to contain 'oauth_verifier'
|
||||
/// parameter, which is then used to fetch an access token using the
|
||||
/// token_from_verifier() method.
|
||||
/// See: http://tools.ietf.org/html/rfc5849#section-2.2
|
||||
/// The received 'oauth_token' is parsed and verified to match the current token().
|
||||
/// When access token is successfully obtained, set_token() is called, and config is
|
||||
/// ready for use by oauth1_handler.
|
||||
/// </summary>
|
||||
/// <param name="redirected_uri">The URI where web browser/view was redirected after resource owner's authorization.</param>
|
||||
/// <returns>Task that fetches the access token based on redirected URI.</returns>
|
||||
_ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a task with HTTP request to fetch an access token from the token endpoint.
|
||||
/// The request exchanges a verifier code to an access token.
|
||||
/// If successful, the resulting token is set as active via set_token().
|
||||
/// See: http://tools.ietf.org/html/rfc5849#section-2.3
|
||||
/// </summary>
|
||||
/// <param name="verifier">Verifier received via redirect upon successful authorization.</param>
|
||||
/// <returns>Task that fetches the access token based on the verifier.</returns>
|
||||
pplx::task<void> token_from_verifier(utility::string_t verifier)
|
||||
{
|
||||
return _request_token(_generate_auth_state(details::oauth1_strings::verifier, std::move(verifier)), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a task with HTTP request to fetch an access token from the token endpoint.
|
||||
/// If successful, the resulting token is set as active via set_token().
|
||||
/// </summary>
|
||||
/// <returns>Task that fetches the access token based on the verifier.</returns>
|
||||
pplx::task<void> refresh_token(const utility::string_t &key)
|
||||
{
|
||||
return _request_token(_generate_auth_state(key, m_token.additional_parameters().at(key)), false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get consumer key used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <returns>Consumer key string.</returns>
|
||||
const utility::string_t& consumer_key() const { return m_consumer_key; }
|
||||
/// <summary>
|
||||
/// Set consumer key used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <param name="key">Consumer key string to set.</param>
|
||||
void set_consumer_key(utility::string_t key) { m_consumer_key = std::move(key); }
|
||||
|
||||
/// <summary>
|
||||
/// Get consumer secret used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <returns>Consumer secret string.</returns>
|
||||
const utility::string_t& consumer_secret() const { return m_consumer_secret; }
|
||||
/// <summary>
|
||||
/// Set consumer secret used in authorization and authentication.
|
||||
/// </summary>
|
||||
/// <param name="secret">Consumer secret string to set.</param>
|
||||
void set_consumer_secret(utility::string_t secret) { m_consumer_secret = std::move(secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Get temporary token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Temporary token endpoint URI string.</returns>
|
||||
const utility::string_t& temp_endpoint() const { return m_temp_endpoint; }
|
||||
/// <summary>
|
||||
/// Set temporary token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="temp_endpoint">Temporary token endpoint URI string to set.</param>
|
||||
void set_temp_endpoint(utility::string_t temp_endpoint) { m_temp_endpoint = std::move(temp_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Authorization endpoint URI string.</returns>
|
||||
const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
|
||||
/// <summary>
|
||||
/// Set authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="auth_endpoint">Authorization endpoint URI string to set.</param>
|
||||
void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Token endpoint URI string.</returns>
|
||||
const utility::string_t& token_endpoint() const { return m_token_endpoint; }
|
||||
/// <summary>
|
||||
/// Set token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="token_endpoint">Token endpoint URI string to set.</param>
|
||||
void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get callback URI string.
|
||||
/// </summary>
|
||||
/// <returns>Callback URI string.</returns>
|
||||
const utility::string_t& callback_uri() const { return m_callback_uri; }
|
||||
/// <summary>
|
||||
/// Set callback URI string.
|
||||
/// </summary>
|
||||
/// <param name="callback_uri">Callback URI string to set.</param>
|
||||
void set_callback_uri(utility::string_t callback_uri) { m_callback_uri = std::move(callback_uri); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token.
|
||||
/// </summary>
|
||||
/// <returns>Token.</returns>
|
||||
const oauth1_token& token() const
|
||||
{
|
||||
if (m_is_authorization_completed)
|
||||
{
|
||||
// Return the token object only if authorization has been completed.
|
||||
// Otherwise the token object holds a temporary token which should not be
|
||||
// returned to the user.
|
||||
return m_token;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const oauth1_token empty_token;
|
||||
return empty_token;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set token.
|
||||
/// </summary>
|
||||
/// <param name="token">Token to set.</param>
|
||||
void set_token(oauth1_token token)
|
||||
{
|
||||
m_token = std::move(token);
|
||||
m_is_authorization_completed = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get signature method.
|
||||
/// </summary>
|
||||
/// <returns>Signature method.</returns>
|
||||
const oauth1_method& method() const { return m_method; }
|
||||
/// <summary>
|
||||
/// Set signature method.
|
||||
/// </summary>
|
||||
/// <param name="method">Signature method.</param>
|
||||
void set_method(oauth1_method method) { m_method = std::move(method); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authentication realm.
|
||||
/// </summary>
|
||||
/// <returns>Authentication realm string.</returns>
|
||||
const utility::string_t& realm() const { return m_realm; }
|
||||
/// <summary>
|
||||
/// Set authentication realm.
|
||||
/// </summary>
|
||||
/// <param name="realm">Authentication realm string to set.</param>
|
||||
void set_realm(utility::string_t realm) { m_realm = std::move(realm); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns enabled state of the configuration.
|
||||
/// The oauth1_handler will perform OAuth 1.0 authentication only if
|
||||
/// this method returns true.
|
||||
/// Return value is true if access token is valid (=fetched or manually set)
|
||||
/// and both consumer_key() and consumer_secret() are set (=non-empty).
|
||||
/// </summary>
|
||||
/// <returns>The configuration enabled state.</returns>
|
||||
bool is_enabled() const { return token().is_valid_access_token() && !(consumer_key().empty() || consumer_secret().empty()); }
|
||||
|
||||
// Builds signature base string according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.1.1
|
||||
_ASYNCRTIMP utility::string_t _build_signature_base_string(http_request request, details::oauth1_state state) const;
|
||||
|
||||
// Builds HMAC-SHA1 signature according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.2
|
||||
utility::string_t _build_hmac_sha1_signature(http_request request, details::oauth1_state state) const
|
||||
{
|
||||
auto text(_build_signature_base_string(std::move(request), std::move(state)));
|
||||
auto digest(_hmac_sha1(_build_key(), std::move(text)));
|
||||
auto signature(utility::conversions::to_base64(std::move(digest)));
|
||||
return signature;
|
||||
}
|
||||
|
||||
// Builds PLAINTEXT signature according to:
|
||||
// http://tools.ietf.org/html/rfc5849#section-3.4.4
|
||||
utility::string_t _build_plaintext_signature() const
|
||||
{
|
||||
return _build_key();
|
||||
}
|
||||
|
||||
details::oauth1_state _generate_auth_state(utility::string_t extra_key, utility::string_t extra_value)
|
||||
{
|
||||
return details::oauth1_state(_generate_timestamp(), _generate_nonce(), std::move(extra_key), std::move(extra_value));
|
||||
}
|
||||
|
||||
details::oauth1_state _generate_auth_state()
|
||||
{
|
||||
return details::oauth1_state(_generate_timestamp(), _generate_nonce());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets map of parameters to sign.
|
||||
/// </summary>
|
||||
/// <returns>Map of parameters.</returns>
|
||||
const std::map<utility::string_t, utility::string_t>& parameters() const { return m_parameters_to_sign; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a key value parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">Key as a string value.</param>
|
||||
/// <param name="value">Value as a string value.</param>
|
||||
void add_parameter(const utility::string_t &key, const utility::string_t &value) { m_parameters_to_sign[key] = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a key value parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">Key as a string value.</param>
|
||||
/// <param name="value">Value as a string value.</param>
|
||||
void add_parameter(utility::string_t &&key, utility::string_t &&value) { m_parameters_to_sign[std::move(key)] = std::move(value); }
|
||||
|
||||
/// <summary>
|
||||
/// Sets entire map or parameters replacing all previously values.
|
||||
/// </summary>
|
||||
/// <param name="parameters">Map of values.</param>
|
||||
void set_parameters(const std::map<utility::string_t, utility::string_t> ¶meters)
|
||||
{
|
||||
m_parameters_to_sign.clear();
|
||||
m_parameters_to_sign = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all parameters.
|
||||
/// </summary>
|
||||
void clear_parameters() { m_parameters_to_sign.clear(); }
|
||||
|
||||
private:
|
||||
friend class web::http::client::http_client_config;
|
||||
friend class web::http::oauth1::details::oauth1_handler;
|
||||
|
||||
oauth1_config() :
|
||||
m_is_authorization_completed(false)
|
||||
{}
|
||||
|
||||
utility::string_t _generate_nonce()
|
||||
{
|
||||
return m_nonce_generator.generate();
|
||||
}
|
||||
|
||||
static utility::string_t _generate_timestamp()
|
||||
{
|
||||
return utility::conversions::print_string(utility::datetime::utc_timestamp(), std::locale::classic());
|
||||
}
|
||||
|
||||
_ASYNCRTIMP static std::vector<unsigned char> __cdecl _hmac_sha1(const utility::string_t& key, const utility::string_t& data);
|
||||
|
||||
static utility::string_t _build_base_string_uri(const uri& u);
|
||||
|
||||
utility::string_t _build_normalized_parameters(web::http::uri u, const details::oauth1_state& state) const;
|
||||
|
||||
utility::string_t _build_signature(http_request request, details::oauth1_state state) const;
|
||||
|
||||
utility::string_t _build_key() const
|
||||
{
|
||||
return uri::encode_data_string(consumer_secret()) + _XPLATSTR("&") + uri::encode_data_string(m_token.secret());
|
||||
}
|
||||
|
||||
void _authenticate_request(http_request &req)
|
||||
{
|
||||
_authenticate_request(req, _generate_auth_state());
|
||||
}
|
||||
|
||||
_ASYNCRTIMP void _authenticate_request(http_request &req, details::oauth1_state state);
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> _request_token(details::oauth1_state state, bool is_temp_token_request);
|
||||
|
||||
utility::string_t m_consumer_key;
|
||||
utility::string_t m_consumer_secret;
|
||||
oauth1_token m_token;
|
||||
|
||||
utility::string_t m_temp_endpoint;
|
||||
utility::string_t m_auth_endpoint;
|
||||
utility::string_t m_token_endpoint;
|
||||
utility::string_t m_callback_uri;
|
||||
utility::string_t m_realm;
|
||||
oauth1_method m_method;
|
||||
|
||||
std::map<utility::string_t, utility::string_t> m_parameters_to_sign;
|
||||
|
||||
utility::nonce_generator m_nonce_generator;
|
||||
bool m_is_authorization_completed;
|
||||
};
|
||||
|
||||
} // namespace web::http::oauth1::experimental
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
class oauth1_handler : public http_pipeline_stage
|
||||
{
|
||||
public:
|
||||
oauth1_handler(std::shared_ptr<experimental::oauth1_config> cfg) :
|
||||
m_config(std::move(cfg))
|
||||
{}
|
||||
|
||||
virtual pplx::task<http_response> propagate(http_request request) override
|
||||
{
|
||||
if (m_config)
|
||||
{
|
||||
m_config->_authenticate_request(request);
|
||||
}
|
||||
return next_stage()->propagate(request);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<experimental::oauth1_config> m_config;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
523
3rdparty/cpprestsdk/include/cpprest/oauth2.h
vendored
Normal file
523
3rdparty/cpprestsdk/include/cpprest/oauth2.h
vendored
Normal file
|
@ -0,0 +1,523 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 2.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_OAUTH2_H
|
||||
#define _CASA_OAUTH2_H
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
}
|
||||
|
||||
/// oAuth 2.0 library.
|
||||
namespace oauth2
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
|
||||
class oauth2_handler;
|
||||
|
||||
// Constant strings for OAuth 2.0.
|
||||
typedef utility::string_t oauth2_string;
|
||||
class oauth2_strings
|
||||
{
|
||||
public:
|
||||
#define _OAUTH2_STRINGS
|
||||
#define DAT(a_, b_) _ASYNCRTIMP static const oauth2_string a_;
|
||||
#include "cpprest/details/http_constants.dat"
|
||||
#undef _OAUTH2_STRINGS
|
||||
#undef DAT
|
||||
};
|
||||
|
||||
} // namespace web::http::oauth2::details
|
||||
|
||||
/// oAuth functionality is currently in beta.
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Exception type for OAuth 2.0 errors.
|
||||
/// </summary>
|
||||
class oauth2_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
oauth2_exception(utility::string_t msg) : m_msg(utility::conversions::to_utf8string(std::move(msg))) {}
|
||||
~oauth2_exception() CPPREST_NOEXCEPT {}
|
||||
const char* what() const CPPREST_NOEXCEPT { return m_msg.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 2.0 token and associated information.
|
||||
/// </summary>
|
||||
class oauth2_token
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Value for undefined expiration time in expires_in().
|
||||
/// </summary>
|
||||
enum { undefined_expiration = -1 };
|
||||
|
||||
oauth2_token(utility::string_t access_token=utility::string_t()) :
|
||||
m_access_token(std::move(access_token)),
|
||||
m_expires_in(undefined_expiration)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Get access token validity state.
|
||||
/// If true, access token is a valid.
|
||||
/// </summary>
|
||||
/// <returns>Access token validity state.</returns>
|
||||
bool is_valid_access_token() const { return !access_token().empty(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token.
|
||||
/// </summary>
|
||||
/// <returns>Access token string.</returns>
|
||||
const utility::string_t& access_token() const { return m_access_token; }
|
||||
/// <summary>
|
||||
/// Set access token.
|
||||
/// </summary>
|
||||
/// <param name="access_token">Access token string to set.</param>
|
||||
void set_access_token(utility::string_t access_token) { m_access_token = std::move(access_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get refresh token.
|
||||
/// </summary>
|
||||
/// <returns>Refresh token string.</returns>
|
||||
const utility::string_t& refresh_token() const { return m_refresh_token; }
|
||||
/// <summary>
|
||||
/// Set refresh token.
|
||||
/// </summary>
|
||||
/// <param name="refresh_token">Refresh token string to set.</param>
|
||||
void set_refresh_token(utility::string_t refresh_token) { m_refresh_token = std::move(refresh_token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token type.
|
||||
/// </summary>
|
||||
/// <returns>Token type string.</returns>
|
||||
const utility::string_t& token_type() const { return m_token_type; }
|
||||
/// <summary>
|
||||
/// Set token type.
|
||||
/// </summary>
|
||||
/// <param name="token_type">Token type string to set.</param>
|
||||
void set_token_type(utility::string_t token_type) { m_token_type = std::move(token_type); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token scope.
|
||||
/// </summary>
|
||||
/// <returns>Token scope string.</returns>
|
||||
const utility::string_t& scope() const { return m_scope; }
|
||||
/// <summary>
|
||||
/// Set token scope.
|
||||
/// </summary>
|
||||
/// <param name="scope">Token scope string to set.</param>
|
||||
void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the lifetime of the access token in seconds.
|
||||
/// For example, 3600 means the access token will expire in one hour from
|
||||
/// the time when access token response was generated by the authorization server.
|
||||
/// Value of undefined_expiration means expiration time is either
|
||||
/// unset or that it was not returned by the server with the access token.
|
||||
/// </summary>
|
||||
/// <returns>Lifetime of the access token in seconds or undefined_expiration if not set.</returns>
|
||||
int64_t expires_in() const { return m_expires_in; }
|
||||
/// <summary>
|
||||
/// Set lifetime of access token (in seconds).
|
||||
/// </summary>
|
||||
/// <param name="expires_in">Lifetime of access token in seconds.</param>
|
||||
void set_expires_in(int64_t expires_in) { m_expires_in = expires_in; }
|
||||
|
||||
private:
|
||||
utility::string_t m_access_token;
|
||||
utility::string_t m_refresh_token;
|
||||
utility::string_t m_token_type;
|
||||
utility::string_t m_scope;
|
||||
int64_t m_expires_in;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// OAuth 2.0 configuration.
|
||||
///
|
||||
/// Encapsulates functionality for:
|
||||
/// - Authenticating requests with an access token.
|
||||
/// - Performing the OAuth 2.0 authorization code grant authorization flow.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1
|
||||
/// - Performing the OAuth 2.0 implicit grant authorization flow.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.2
|
||||
///
|
||||
/// Performing OAuth 2.0 authorization:
|
||||
/// 1. Set service and client/app parameters:
|
||||
/// - Client/app key & secret (as provided by the service).
|
||||
/// - The service authorization endpoint and token endpoint.
|
||||
/// - Your client/app redirect URI.
|
||||
/// - Use set_state() to assign a unique state string for the authorization
|
||||
/// session (default: "").
|
||||
/// - If needed, use set_bearer_auth() to control bearer token passing in either
|
||||
/// query or header (default: header). See: http://tools.ietf.org/html/rfc6750#section-2
|
||||
/// - If needed, use set_access_token_key() to set "non-standard" access token
|
||||
/// key (default: "access_token").
|
||||
/// - If needed, use set_implicit_grant() to enable implicit grant flow.
|
||||
/// 2. Build authorization URI with build_authorization_uri() and open this in web browser/control.
|
||||
/// 3. The resource owner should then clicks "Yes" to authorize your client/app, and
|
||||
/// as a result the web browser/control is redirected to redirect_uri().
|
||||
/// 5. Capture the redirected URI either in web control or by HTTP listener.
|
||||
/// 6. Pass the redirected URI to token_from_redirected_uri() to obtain access token.
|
||||
/// - The method ensures redirected URI contains same state() as set in step 1.
|
||||
/// - In implicit_grant() is false, this will create HTTP request to fetch access token
|
||||
/// from the service. Otherwise access token is already included in the redirected URI.
|
||||
///
|
||||
/// Usage for issuing authenticated requests:
|
||||
/// 1. Perform authorization as above to obtain the access token or use an existing token.
|
||||
/// - Some services provide option to generate access tokens for testing purposes.
|
||||
/// 2. Pass the resulting oauth2_config with the access token to http_client_config::set_oauth2().
|
||||
/// 3. Construct http_client with this http_client_config. As a result, all HTTP requests
|
||||
/// by that client will be OAuth 2.0 authenticated.
|
||||
///
|
||||
/// </summary>
|
||||
class oauth2_config
|
||||
{
|
||||
public:
|
||||
|
||||
oauth2_config(utility::string_t client_key, utility::string_t client_secret,
|
||||
utility::string_t auth_endpoint, utility::string_t token_endpoint,
|
||||
utility::string_t redirect_uri, utility::string_t scope=utility::string_t()) :
|
||||
m_client_key(std::move(client_key)),
|
||||
m_client_secret(std::move(client_secret)),
|
||||
m_auth_endpoint(std::move(auth_endpoint)),
|
||||
m_token_endpoint(std::move(token_endpoint)),
|
||||
m_redirect_uri(std::move(redirect_uri)),
|
||||
m_scope(std::move(scope)),
|
||||
m_implicit_grant(false),
|
||||
m_bearer_auth(true),
|
||||
m_http_basic_auth(true),
|
||||
m_access_token_key(details::oauth2_strings::access_token)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Builds an authorization URI to be loaded in the web browser/view.
|
||||
/// The URI is built with auth_endpoint() as basis.
|
||||
/// The implicit_grant() affects the built URI by selecting
|
||||
/// either authorization code or implicit grant flow.
|
||||
/// You can set generate_state to generate a new random state string.
|
||||
/// </summary>
|
||||
/// <param name="generate_state">If true, a new random state() string is generated
|
||||
/// which replaces the current state(). If false, state() is unchanged and used as-is.</param>
|
||||
/// <returns>Authorization URI string.</returns>
|
||||
_ASYNCRTIMP utility::string_t build_authorization_uri(bool generate_state);
|
||||
|
||||
/// <summary>
|
||||
/// Fetch an access token (and possibly a refresh token) based on redirected URI.
|
||||
/// Behavior depends on the implicit_grant() setting.
|
||||
/// If implicit_grant() is false, the URI is parsed for 'code'
|
||||
/// parameter, and then token_from_code() is called with this code.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1
|
||||
/// Otherwise, redirect URI fragment part is parsed for 'access_token'
|
||||
/// parameter, which directly contains the token(s).
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.2
|
||||
/// In both cases, the 'state' parameter is parsed and is verified to match state().
|
||||
/// </summary>
|
||||
/// <param name="redirected_uri">The URI where web browser/view was redirected after resource owner's authorization.</param>
|
||||
/// <returns>Task that fetches the token(s) based on redirected URI.</returns>
|
||||
_ASYNCRTIMP pplx::task<void> token_from_redirected_uri(const web::http::uri& redirected_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches an access token (and possibly a refresh token) from the token endpoint.
|
||||
/// The task creates an HTTP request to the token_endpoint() which exchanges
|
||||
/// the authorization code for the token(s).
|
||||
/// This also sets the refresh token if one was returned.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.1.3
|
||||
/// </summary>
|
||||
/// <param name="authorization_code">Code received via redirect upon successful authorization.</param>
|
||||
/// <returns>Task that fetches token(s) based on the authorization code.</returns>
|
||||
pplx::task<void> token_from_code(utility::string_t authorization_code)
|
||||
{
|
||||
uri_builder ub;
|
||||
ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::authorization_code, false);
|
||||
ub.append_query(details::oauth2_strings::code, uri::encode_data_string(std::move(authorization_code)), false);
|
||||
ub.append_query(details::oauth2_strings::redirect_uri, uri::encode_data_string(redirect_uri()), false);
|
||||
return _request_token(ub);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a new access token (and possibly a new refresh token) using the refresh token.
|
||||
/// The task creates a HTTP request to the token_endpoint().
|
||||
/// If successful, resulting access token is set as active via set_token().
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-6
|
||||
/// This also sets a new refresh token if one was returned.
|
||||
/// </summary>
|
||||
/// <returns>Task that fetches the token(s) using the refresh token.</returns>
|
||||
pplx::task<void> token_from_refresh()
|
||||
{
|
||||
uri_builder ub;
|
||||
ub.append_query(details::oauth2_strings::grant_type, details::oauth2_strings::refresh_token, false);
|
||||
ub.append_query(details::oauth2_strings::refresh_token, uri::encode_data_string(token().refresh_token()), false);
|
||||
return _request_token(ub);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns enabled state of the configuration.
|
||||
/// The oauth2_handler will perform OAuth 2.0 authentication only if
|
||||
/// this method returns true.
|
||||
/// Return value is true if access token is valid (=fetched or manually set).
|
||||
/// </summary>
|
||||
/// <returns>The configuration enabled state.</returns>
|
||||
bool is_enabled() const { return token().is_valid_access_token(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client key.
|
||||
/// </summary>
|
||||
/// <returns>Client key string.</returns>
|
||||
const utility::string_t& client_key() const { return m_client_key; }
|
||||
/// <summary>
|
||||
/// Set client key.
|
||||
/// </summary>
|
||||
/// <param name="client_key">Client key string to set.</param>
|
||||
void set_client_key(utility::string_t client_key) { m_client_key = std::move(client_key); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client secret.
|
||||
/// </summary>
|
||||
/// <returns>Client secret string.</returns>
|
||||
const utility::string_t& client_secret() const { return m_client_secret; }
|
||||
/// <summary>
|
||||
/// Set client secret.
|
||||
/// </summary>
|
||||
/// <param name="client_secret">Client secret string to set.</param>
|
||||
void set_client_secret(utility::string_t client_secret) { m_client_secret = std::move(client_secret); }
|
||||
|
||||
/// <summary>
|
||||
/// Get authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Authorization endpoint URI string.</returns>
|
||||
const utility::string_t& auth_endpoint() const { return m_auth_endpoint; }
|
||||
/// <summary>
|
||||
/// Set authorization endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="auth_endpoint">Authorization endpoint URI string to set.</param>
|
||||
void set_auth_endpoint(utility::string_t auth_endpoint) { m_auth_endpoint = std::move(auth_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <returns>Token endpoint URI string.</returns>
|
||||
const utility::string_t& token_endpoint() const { return m_token_endpoint; }
|
||||
/// <summary>
|
||||
/// Set token endpoint URI string.
|
||||
/// </summary>
|
||||
/// <param name="token_endpoint">Token endpoint URI string to set.</param>
|
||||
void set_token_endpoint(utility::string_t token_endpoint) { m_token_endpoint = std::move(token_endpoint); }
|
||||
|
||||
/// <summary>
|
||||
/// Get redirect URI string.
|
||||
/// </summary>
|
||||
/// <returns>Redirect URI string.</returns>
|
||||
const utility::string_t& redirect_uri() const { return m_redirect_uri; }
|
||||
/// <summary>
|
||||
/// Set redirect URI string.
|
||||
/// </summary>
|
||||
/// <param name="redirect_uri">Redirect URI string to set.</param>
|
||||
void set_redirect_uri(utility::string_t redirect_uri) { m_redirect_uri = std::move(redirect_uri); }
|
||||
|
||||
/// <summary>
|
||||
/// Get scope used in authorization for token.
|
||||
/// </summary>
|
||||
/// <returns>Scope string used in authorization.</returns>
|
||||
const utility::string_t& scope() const { return m_scope; }
|
||||
/// <summary>
|
||||
/// Set scope for authorization for token.
|
||||
/// </summary>
|
||||
/// <param name="scope">Scope string for authorization for token.</param>
|
||||
void set_scope(utility::string_t scope) { m_scope = std::move(scope); }
|
||||
|
||||
/// <summary>
|
||||
/// Get client state string used in authorization.
|
||||
/// </summary>
|
||||
/// <returns>Client state string used in authorization.</returns>
|
||||
const utility::string_t& state() { return m_state; }
|
||||
/// <summary>
|
||||
/// Set client state string for authorization for token.
|
||||
/// The state string is used in authorization for security reasons
|
||||
/// (to uniquely identify authorization sessions).
|
||||
/// If desired, suitably secure state string can be automatically generated
|
||||
/// by build_authorization_uri().
|
||||
/// A good state string consist of 30 or more random alphanumeric characters.
|
||||
/// </summary>
|
||||
/// <param name="state">Client authorization state string to set.</param>
|
||||
void set_state(utility::string_t state) { m_state = std::move(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Get token.
|
||||
/// </summary>
|
||||
/// <returns>Token.</returns>
|
||||
const oauth2_token& token() const { return m_token; }
|
||||
/// <summary>
|
||||
/// Set token.
|
||||
/// </summary>
|
||||
/// <param name="token">Token to set.</param>
|
||||
void set_token(oauth2_token token) { m_token = std::move(token); }
|
||||
|
||||
/// <summary>
|
||||
/// Get implicit grant setting for authorization.
|
||||
/// </summary>
|
||||
/// <returns>Implicit grant setting for authorization.</returns>
|
||||
bool implicit_grant() const { return m_implicit_grant; }
|
||||
/// <summary>
|
||||
/// Set implicit grant setting for authorization.
|
||||
/// False means authorization code grant is used for authorization.
|
||||
/// True means implicit grant is used.
|
||||
/// Default: False.
|
||||
/// </summary>
|
||||
/// <param name="implicit_grant">The implicit grant setting to set.</param>
|
||||
void set_implicit_grant(bool implicit_grant) { m_implicit_grant = implicit_grant; }
|
||||
|
||||
/// <summary>
|
||||
/// Get bearer token authentication setting.
|
||||
/// </summary>
|
||||
/// <returns>Bearer token authentication setting.</returns>
|
||||
bool bearer_auth() const { return m_bearer_auth; }
|
||||
/// <summary>
|
||||
/// Set bearer token authentication setting.
|
||||
/// This must be selected based on what the service accepts.
|
||||
/// True means access token is passed in the request header. (http://tools.ietf.org/html/rfc6750#section-2.1)
|
||||
/// False means access token in passed in the query parameters. (http://tools.ietf.org/html/rfc6750#section-2.3)
|
||||
/// Default: True.
|
||||
/// </summary>
|
||||
/// <param name="bearer_auth">The bearer token authentication setting to set.</param>
|
||||
void set_bearer_auth(bool bearer_auth) { m_bearer_auth = bearer_auth; }
|
||||
|
||||
/// <summary>
|
||||
/// Get HTTP Basic authentication setting for token endpoint.
|
||||
/// </summary>
|
||||
/// <returns>HTTP Basic authentication setting for token endpoint.</returns>
|
||||
bool http_basic_auth() const { return m_http_basic_auth; }
|
||||
/// <summary>
|
||||
/// Set HTTP Basic authentication setting for token endpoint.
|
||||
/// This setting must be selected based on what the service accepts.
|
||||
/// True means HTTP Basic authentication is used for the token endpoint.
|
||||
/// False means client key & secret are passed in the HTTP request body.
|
||||
/// Default: True.
|
||||
/// </summary>
|
||||
/// <param name="http_basic_auth">The HTTP Basic authentication setting to set.</param>
|
||||
void set_http_basic_auth(bool http_basic_auth) { m_http_basic_auth = http_basic_auth; }
|
||||
|
||||
/// <summary>
|
||||
/// Get access token key.
|
||||
/// </summary>
|
||||
/// <returns>Access token key string.</returns>
|
||||
const utility::string_t& access_token_key() const { return m_access_token_key; }
|
||||
/// <summary>
|
||||
/// Set access token key.
|
||||
/// If the service requires a "non-standard" key you must set it here.
|
||||
/// Default: "access_token".
|
||||
/// </summary>
|
||||
void set_access_token_key(utility::string_t access_token_key) { m_access_token_key = std::move(access_token_key); }
|
||||
|
||||
private:
|
||||
friend class web::http::client::http_client_config;
|
||||
friend class web::http::oauth2::details::oauth2_handler;
|
||||
|
||||
oauth2_config() :
|
||||
m_implicit_grant(false),
|
||||
m_bearer_auth(true),
|
||||
m_http_basic_auth(true)
|
||||
{}
|
||||
|
||||
_ASYNCRTIMP pplx::task<void> _request_token(uri_builder& request_body);
|
||||
|
||||
oauth2_token _parse_token_from_json(const json::value& token_json);
|
||||
|
||||
void _authenticate_request(http_request &req) const
|
||||
{
|
||||
if (bearer_auth())
|
||||
{
|
||||
req.headers().add(header_names::authorization, _XPLATSTR("Bearer ") + token().access_token());
|
||||
}
|
||||
else
|
||||
{
|
||||
uri_builder ub(req.request_uri());
|
||||
ub.append_query(access_token_key(), token().access_token());
|
||||
req.set_request_uri(ub.to_uri());
|
||||
}
|
||||
}
|
||||
|
||||
utility::string_t m_client_key;
|
||||
utility::string_t m_client_secret;
|
||||
utility::string_t m_auth_endpoint;
|
||||
utility::string_t m_token_endpoint;
|
||||
utility::string_t m_redirect_uri;
|
||||
utility::string_t m_scope;
|
||||
utility::string_t m_state;
|
||||
|
||||
bool m_implicit_grant;
|
||||
bool m_bearer_auth;
|
||||
bool m_http_basic_auth;
|
||||
utility::string_t m_access_token_key;
|
||||
|
||||
oauth2_token m_token;
|
||||
|
||||
utility::nonce_generator m_state_generator;
|
||||
};
|
||||
|
||||
} // namespace web::http::oauth2::experimental
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
class oauth2_handler : public http_pipeline_stage
|
||||
{
|
||||
public:
|
||||
oauth2_handler(std::shared_ptr<experimental::oauth2_config> cfg) :
|
||||
m_config(std::move(cfg))
|
||||
{}
|
||||
|
||||
virtual pplx::task<http_response> propagate(http_request request) override
|
||||
{
|
||||
if (m_config)
|
||||
{
|
||||
m_config->_authenticate_request(request);
|
||||
}
|
||||
return next_stage()->propagate(request);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<experimental::oauth2_config> m_config;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
709
3rdparty/cpprestsdk/include/cpprest/producerconsumerstream.h
vendored
Normal file
709
3rdparty/cpprestsdk/include/cpprest/producerconsumerstream.h
vendored
Normal file
|
@ -0,0 +1,709 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a basic memory-based stream buffer, which allows consumer / producer pairs to communicate
|
||||
* data via a buffer.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
#define _CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/astreambuf.h"
|
||||
|
||||
namespace Concurrency { namespace streams {
|
||||
|
||||
namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// The basic_producer_consumer_buffer class serves as a memory-based steam buffer that supports both writing and reading
|
||||
/// sequences of characters. It can be used as a consumer/producer buffer.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_producer_consumer_buffer : public streams::details::streambuf_state_manager<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef typename ::concurrency::streams::char_traits<_CharType> traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_producer_consumer_buffer(size_t alloc_size)
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::out | std::ios_base::in),
|
||||
m_alloc_size(alloc_size),
|
||||
m_allocBlock(nullptr),
|
||||
m_total(0), m_total_read(0), m_total_written(0),
|
||||
m_synced(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_producer_consumer_buffer()
|
||||
{
|
||||
// Note: there is no need to call 'wait()' on the result of close(),
|
||||
// since we happen to know that close() will return without actually
|
||||
// doing anything asynchronously. Should the implementation of _close_write()
|
||||
// change in that regard, this logic may also have to change.
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
|
||||
_ASSERTE(m_requests.empty());
|
||||
m_blocks.clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <c>can_seek<c/> is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it will not have any effect on what is returned by subsequent calls to <see cref="::buffer_size method" />.</remarks>
|
||||
virtual void set_buffer_size(size_t , std::ios_base::openmode = std::ios_base::in)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, <c>in_avail</c> returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> to read data without
|
||||
/// incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const { return m_total; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if ( ((mode & std::ios_base::in) && !this->can_read()) ||
|
||||
((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
if (mode == std::ios_base::in)
|
||||
return (pos_type)m_total_read;
|
||||
else if (mode == std::ios_base::out)
|
||||
return (pos_type)m_total_written;
|
||||
else
|
||||
return (pos_type)traits::eof();
|
||||
}
|
||||
|
||||
// Seeking is not supported
|
||||
virtual pos_type seekpos(pos_type, std::ios_base::openmode) { return (pos_type)traits::eof(); }
|
||||
virtual pos_type seekoff(off_type , std::ios_base::seekdir , std::ios_base::openmode ) { return (pos_type)traits::eof(); }
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support alloc/commit.</returns>
|
||||
virtual _CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We always allocate a new block even if the count could be satisfied by
|
||||
// the current write block. While this does lead to wasted space it allows for
|
||||
// easier book keeping
|
||||
|
||||
_ASSERTE(!m_allocBlock);
|
||||
m_allocBlock = std::make_shared<_block>(count);
|
||||
return m_allocBlock->wbegin();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
virtual void _commit(size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
// The count does not reflect the actual size of the block.
|
||||
// Since we do not allow any more writes to this block it would suffice.
|
||||
// If we ever change the algorithm to reuse blocks then this needs to be revisited.
|
||||
|
||||
_ASSERTE((bool)m_allocBlock);
|
||||
m_allocBlock->update_write_head(count);
|
||||
m_blocks.push_back(m_allocBlock);
|
||||
m_allocBlock = nullptr;
|
||||
|
||||
update_write_head(count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr.'</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
count = 0;
|
||||
ptr = nullptr;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
if (m_blocks.empty())
|
||||
{
|
||||
// If the write head has been closed then have reached the end of the
|
||||
// stream (return true), otherwise more data could be written later (return false).
|
||||
return !this->can_write();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto block = m_blocks.front();
|
||||
|
||||
count = block->rd_chars_left();
|
||||
ptr = block->rbegin();
|
||||
|
||||
_ASSERTE(ptr != nullptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to de-allocate the
|
||||
/// memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr == nullptr) return;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
auto block = m_blocks.front();
|
||||
|
||||
_ASSERTE(block->rd_chars_left() >= count);
|
||||
block->m_read += count;
|
||||
|
||||
update_read_head(count);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual pplx::task<bool> _sync()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
m_synced = in_avail();
|
||||
|
||||
fulfill_outstanding();
|
||||
|
||||
return pplx::task_from_result(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
return pplx::task_from_result((this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof());
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count)
|
||||
{
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::task_completion_event<size_t> tce;
|
||||
enqueue_request(_request(count, [this, ptr, count, tce]()
|
||||
{
|
||||
// VS 2010 resolves read to a global function. Explicit
|
||||
// invocation through the "this" pointer fixes the issue.
|
||||
tce.set(this->read(ptr, count));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual size_t _sgetn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(count) ? this->read(ptr, count) : (size_t)traits::requires_async();
|
||||
}
|
||||
|
||||
virtual size_t _scopy(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(count) ? this->read(ptr, count, false) : (size_t)traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]()
|
||||
{
|
||||
tce.set(this->read_byte(true));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual int_type _sbumpc()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(1) ? this->read_byte(true) : traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _getc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]()
|
||||
{
|
||||
tce.set(this->read_byte(false));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
int_type _sgetc()
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
return can_satisfy(1) ? this->read_byte(false) : traits::requires_async();
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
pplx::task_completion_event<int_type> tce;
|
||||
enqueue_request(_request(1, [this, tce]()
|
||||
{
|
||||
this->read_byte(true);
|
||||
tce.set(this->read_byte(false));
|
||||
}));
|
||||
return pplx::create_task(tce);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc()
|
||||
{
|
||||
return pplx::task_from_result<int_type>(traits::eof());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// <summary>
|
||||
/// Close the stream buffer for writing
|
||||
/// </summary>
|
||||
pplx::task<void> _close_write()
|
||||
{
|
||||
// First indicate that there could be no more writes.
|
||||
// Fulfill outstanding relies on that to flush all the
|
||||
// read requests.
|
||||
this->m_stream_can_write = false;
|
||||
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(this->m_lock);
|
||||
|
||||
// This runs on the thread that called close.
|
||||
this->fulfill_outstanding();
|
||||
}
|
||||
|
||||
return pplx::task_from_result();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the write head by an offset specified by count
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void update_write_head(size_t count)
|
||||
{
|
||||
m_total += count;
|
||||
m_total_written += count;
|
||||
fulfill_outstanding();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes count characters from ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType *ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
// If no one is going to read, why bother?
|
||||
// Just pretend to be writing!
|
||||
if (!this->can_read()) return count;
|
||||
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
// Allocate a new block if necessary
|
||||
if ( m_blocks.empty() || m_blocks.back()->wr_chars_left() < count )
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> alloc = m_alloc_size.Max(count);
|
||||
m_blocks.push_back(std::make_shared<_block>(alloc));
|
||||
}
|
||||
|
||||
// The block at the back is always the write head
|
||||
auto last = m_blocks.back();
|
||||
auto countWritten = last->write(ptr, count);
|
||||
_ASSERTE(countWritten == count);
|
||||
|
||||
update_write_head(countWritten);
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fulfill pending requests
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void fulfill_outstanding()
|
||||
{
|
||||
while ( !m_requests.empty() )
|
||||
{
|
||||
auto req = m_requests.front();
|
||||
|
||||
// If we cannot satisfy the request then we need
|
||||
// to wait for the producer to write data
|
||||
if (!can_satisfy(req.size())) return;
|
||||
|
||||
// We have enough data to satisfy this request
|
||||
req.complete();
|
||||
|
||||
// Remove it from the request queue
|
||||
m_requests.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a memory block
|
||||
/// </summary>
|
||||
class _block
|
||||
{
|
||||
public:
|
||||
_block(size_t size)
|
||||
: m_read(0), m_pos(0), m_size(size), m_data(new _CharType[size])
|
||||
{
|
||||
}
|
||||
|
||||
~_block()
|
||||
{
|
||||
delete [] m_data;
|
||||
}
|
||||
|
||||
// Read head
|
||||
size_t m_read;
|
||||
|
||||
// Write head
|
||||
size_t m_pos;
|
||||
|
||||
// Allocation size (of m_data)
|
||||
size_t m_size;
|
||||
|
||||
// The data store
|
||||
_CharType * m_data;
|
||||
|
||||
// Pointer to the read head
|
||||
_CharType * rbegin()
|
||||
{
|
||||
return m_data + m_read;
|
||||
}
|
||||
|
||||
// Pointer to the write head
|
||||
_CharType * wbegin()
|
||||
{
|
||||
return m_data + m_pos;
|
||||
}
|
||||
|
||||
// Read up to count characters from the block
|
||||
size_t read(_Out_writes_ (count) _CharType * dest, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> avail(rd_chars_left());
|
||||
auto countRead = static_cast<size_t>(avail.Min(count));
|
||||
|
||||
_CharType * beg = rbegin();
|
||||
_CharType * end = rbegin() + countRead;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(beg, end, stdext::checked_array_iterator<_CharType *>(dest, count));
|
||||
#else
|
||||
std::copy(beg, end, dest);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
m_read += countRead;
|
||||
}
|
||||
|
||||
return countRead;
|
||||
}
|
||||
|
||||
// Write count characters into the block
|
||||
size_t write(const _CharType * src, size_t count)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> avail(wr_chars_left());
|
||||
auto countWritten = static_cast<size_t>(avail.Min(count));
|
||||
|
||||
const _CharType * srcEnd = src + countWritten;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(src, srcEnd, stdext::checked_array_iterator<_CharType *>(wbegin(), static_cast<size_t>(avail)));
|
||||
#else
|
||||
std::copy(src, srcEnd, wbegin());
|
||||
#endif // _WIN32
|
||||
|
||||
update_write_head(countWritten);
|
||||
return countWritten;
|
||||
}
|
||||
|
||||
void update_write_head(size_t count)
|
||||
{
|
||||
m_pos += count;
|
||||
}
|
||||
|
||||
size_t rd_chars_left() const { return m_pos-m_read; }
|
||||
size_t wr_chars_left() const { return m_size-m_pos; }
|
||||
|
||||
private:
|
||||
|
||||
// Copy is not supported
|
||||
_block(const _block&);
|
||||
_block& operator=(const _block&);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a request on the stream buffer - typically reads
|
||||
/// </summary>
|
||||
class _request
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::function<void()> func_type;
|
||||
_request(size_t count, const func_type& func)
|
||||
: m_func(func), m_count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void complete()
|
||||
{
|
||||
m_func();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
func_type m_func;
|
||||
size_t m_count;
|
||||
};
|
||||
|
||||
void enqueue_request(_request req)
|
||||
{
|
||||
pplx::extensibility::scoped_critical_section_t l(m_lock);
|
||||
|
||||
if (can_satisfy(req.size()))
|
||||
{
|
||||
// We can immediately fulfill the request.
|
||||
req.complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We must wait for data to arrive.
|
||||
m_requests.push(req);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t count)
|
||||
{
|
||||
return (m_synced > 0) || (this->in_avail() >= count) || !this->can_write();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine shall only be called if can_satisfy() returned true.
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
size_t read(_Out_writes_ (count) _CharType *ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
_ASSERTE(can_satisfy(count));
|
||||
|
||||
size_t read = 0;
|
||||
|
||||
for (auto iter = begin(m_blocks); iter != std::end(m_blocks); ++iter)
|
||||
{
|
||||
auto block = *iter;
|
||||
auto read_from_block = block->read(ptr + read, count - read, advance);
|
||||
|
||||
read += read_from_block;
|
||||
|
||||
_ASSERTE(count >= read);
|
||||
if (read == count) break;
|
||||
}
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_read_head(read);
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the read head by the specified offset
|
||||
/// </summary>
|
||||
/// <remarks>This should be called with the lock held</remarks>
|
||||
void update_read_head(size_t count)
|
||||
{
|
||||
m_total -= count;
|
||||
m_total_read += count;
|
||||
|
||||
if ( m_synced > 0 )
|
||||
m_synced = (m_synced > count) ? (m_synced-count) : 0;
|
||||
|
||||
// The block at the front is always the read head.
|
||||
// Purge empty blocks so that the block at the front reflects the read head
|
||||
while (!m_blocks.empty())
|
||||
{
|
||||
// If front block is not empty - we are done
|
||||
if (m_blocks.front()->rd_chars_left() > 0) break;
|
||||
|
||||
// The block has no more data to be read. Relase the block
|
||||
m_blocks.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
// The in/out mode for the buffer
|
||||
std::ios_base::openmode m_mode;
|
||||
|
||||
// Default block size
|
||||
msl::safeint3::SafeInt<size_t> m_alloc_size;
|
||||
|
||||
// Block used for alloc/commit
|
||||
std::shared_ptr<_block> m_allocBlock;
|
||||
|
||||
// Total available data
|
||||
size_t m_total;
|
||||
|
||||
size_t m_total_read;
|
||||
size_t m_total_written;
|
||||
|
||||
// Keeps track of the number of chars that have been flushed but still
|
||||
// remain to be consumed by a read operation.
|
||||
size_t m_synced;
|
||||
|
||||
// The producer-consumer buffer is intended to be used concurrently by a reader
|
||||
// and a writer, who are not coordinating their accesses to the buffer (coordination
|
||||
// being what the buffer is for in the first place). Thus, we have to protect
|
||||
// against some of the internal data elements against concurrent accesses
|
||||
// and the possibility of inconsistent states. A simple non-recursive lock
|
||||
// should be sufficient for those purposes.
|
||||
pplx::extensibility::critical_section_t m_lock;
|
||||
|
||||
// Memory blocks
|
||||
std::deque<std::shared_ptr<_block>> m_blocks;
|
||||
|
||||
// Queue of requests
|
||||
std::queue<_request> m_requests;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The producer_consumer_buffer class serves as a memory-based steam buffer that supports both writing and reading
|
||||
/// sequences of bytes. It can be used as a consumer/producer buffer.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>producer_consumer_buffer</c>.
|
||||
/// </typeparam>
|
||||
/// <remarks>
|
||||
/// This is a reference-counted version of basic_producer_consumer_buffer.</remarks>
|
||||
template<typename _CharType>
|
||||
class producer_consumer_buffer : public streambuf<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a producer_consumer_buffer.
|
||||
/// </summary>
|
||||
/// <param name="alloc_size">The internal default block size.</param>
|
||||
producer_consumer_buffer(size_t alloc_size = 512)
|
||||
: streambuf<_CharType>(std::make_shared<details::basic_producer_consumer_buffer<_CharType>>(alloc_size))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
642
3rdparty/cpprestsdk/include/cpprest/rawptrstream.h
vendored
Normal file
642
3rdparty/cpprestsdk/include/cpprest/rawptrstream.h
vendored
Normal file
|
@ -0,0 +1,642 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* This file defines a stream buffer that is based on a raw pointer and block size. Unlike a vector-based
|
||||
* stream buffer, the buffer cannot be expanded or contracted, it has a fixed capacity.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_RAWPTR_STREAMS_H
|
||||
#define _CASA_RAWPTR_STREAMS_H
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
|
||||
namespace Concurrency { namespace streams {
|
||||
|
||||
// Forward declarations
|
||||
template <typename _CharType> class rawptr_buffer;
|
||||
|
||||
namespace details {
|
||||
|
||||
/// <summary>
|
||||
/// The basic_rawptr_buffer class serves as a memory-based steam buffer that supports both writing and reading
|
||||
/// sequences of characters to and from a fixed-size block.
|
||||
/// </summary>
|
||||
template<typename _CharType>
|
||||
class basic_rawptr_buffer : public streams::details::streambuf_state_manager<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
typedef typename basic_streambuf<_CharType>::traits traits;
|
||||
typedef typename basic_streambuf<_CharType>::int_type int_type;
|
||||
typedef typename basic_streambuf<_CharType>::pos_type pos_type;
|
||||
typedef typename basic_streambuf<_CharType>::off_type off_type;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
basic_rawptr_buffer()
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::in | std::ios_base::out),
|
||||
m_data(nullptr),
|
||||
m_current_position(0),
|
||||
m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~basic_rawptr_buffer()
|
||||
{
|
||||
this->_close_read();
|
||||
this->_close_write();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/// <summary>
|
||||
/// can_seek is used to determine whether a stream buffer supports seeking.
|
||||
/// </summary>
|
||||
virtual bool can_seek() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// <c>has_size<c/> is used to determine whether a stream buffer supports size().
|
||||
/// </summary>
|
||||
virtual bool has_size() const { return this->is_open(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the stream, if known. Calls to <c>has_size</c> will determine whether
|
||||
/// the result of <c>size</c> can be relied on.
|
||||
/// </summary>
|
||||
virtual utility::size64_t size() const
|
||||
{
|
||||
return utility::size64_t(m_size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the stream buffer size, if one has been set.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will always return '0'.</remarks>
|
||||
virtual size_t buffer_size(std::ios_base::openmode = std::ios_base::in) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the stream buffer implementation to buffer or not buffer.
|
||||
/// </summary>
|
||||
/// <param name="size">The size to use for internal buffering, 0 if no buffering should be done.</param>
|
||||
/// <param name="direction">The direction of buffering (in or out)</param>
|
||||
/// <remarks>An implementation that does not support buffering will silently ignore calls to this function and it will not have
|
||||
/// any effect on what is returned by subsequent calls to buffer_size().</remarks>
|
||||
virtual void set_buffer_size(size_t , std::ios_base::openmode = std::ios_base::in)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For any input stream, in_avail returns the number of characters that are immediately available
|
||||
/// to be consumed without blocking. May be used in conjunction with <cref="::sbumpc method"/> and sgetn() to
|
||||
/// read data without incurring the overhead of using tasks.
|
||||
/// </summary>
|
||||
virtual size_t in_avail() const
|
||||
{
|
||||
// See the comment in seek around the restiction that we do not allow read head to
|
||||
// seek beyond the current size.
|
||||
_ASSERTE(m_current_position <= m_size);
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_size);
|
||||
return (size_t)(writeend - readhead);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the stream buffer, preventing further read or write operations.
|
||||
/// </summary>
|
||||
/// <param name="mode">The I/O mode (in or out) to close for.</param>
|
||||
virtual pplx::task<void> close(std::ios_base::openmode mode)
|
||||
{
|
||||
if (mode & std::ios_base::in)
|
||||
{
|
||||
this->_close_read().get(); // Safe to call get() here.
|
||||
}
|
||||
|
||||
if (mode & std::ios_base::out)
|
||||
{
|
||||
this->_close_write().get(); // Safe to call get() here.
|
||||
}
|
||||
|
||||
if ( !this->can_read() && !this->can_write() )
|
||||
{
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
// Exceptions will be propagated out of _close_read or _close_write
|
||||
return pplx::task_from_result();
|
||||
}
|
||||
|
||||
virtual pplx::task<bool> _sync()
|
||||
{
|
||||
return pplx::task_from_result(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _putc(_CharType ch)
|
||||
{
|
||||
if (m_current_position >= m_size)
|
||||
return pplx::task_from_result<int_type>(traits::eof());
|
||||
int_type retVal = (this->write(&ch, 1) == 1) ? static_cast<int_type>(ch) : traits::eof();
|
||||
return pplx::task_from_result<int_type>(retVal);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count)
|
||||
{
|
||||
msl::safeint3::SafeInt<size_t> newSize = msl::safeint3::SafeInt<size_t>(count) + m_current_position;
|
||||
if ( newSize > m_size )
|
||||
return pplx::task_from_exception<size_t>(std::make_exception_ptr(std::runtime_error("Writing past the end of the buffer")));
|
||||
return pplx::task_from_result<size_t>(this->write(ptr, count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocates a contiguous memory block and returns it.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to allocate.</param>
|
||||
/// <returns>A pointer to a block to write to, null if the stream buffer implementation does not support alloc/commit.</returns>
|
||||
_CharType* _alloc(size_t count)
|
||||
{
|
||||
if (!this->can_write()) return nullptr;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> readhead(m_current_position);
|
||||
msl::safeint3::SafeInt<size_t> writeend(m_size);
|
||||
size_t space_left = (size_t)(writeend - readhead);
|
||||
|
||||
if (space_left < count) return nullptr;
|
||||
|
||||
// Let the caller copy the data
|
||||
return (_CharType*)(m_data+m_current_position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits a block already allocated by the stream buffer.
|
||||
/// </summary>
|
||||
/// <param name="count">The number of characters to be committed.</param>
|
||||
void _commit(size_t actual)
|
||||
{
|
||||
// Update the write position and satisfy any pending reads
|
||||
update_current_position(m_current_position+actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pointer to the next already allocated contiguous block of data.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A reference to a pointer variable that will hold the address of the block on success.</param>
|
||||
/// <param name="count">The number of contiguous characters available at the address in 'ptr.'</param>
|
||||
/// <returns><c>true</c> if the operation succeeded, <c>false</c> otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// A return of false does not necessarily indicate that a subsequent read operation would fail, only that
|
||||
/// there is no block to return immediately or that the stream buffer does not support the operation.
|
||||
/// The stream buffer may not de-allocate the block until <see cref="::release method" /> is called.
|
||||
/// If the end of the stream is reached, the function will return <c>true</c>, a null pointer, and a count of zero;
|
||||
/// a subsequent read will not succeed.
|
||||
/// </remarks>
|
||||
virtual bool acquire(_Out_ _CharType*& ptr, _Out_ size_t& count)
|
||||
{
|
||||
count = 0;
|
||||
ptr = nullptr;
|
||||
|
||||
if (!this->can_read()) return false;
|
||||
|
||||
count = in_avail();
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
ptr = (_CharType*)(m_data+m_current_position);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = nullptr;
|
||||
|
||||
// Can only be open for read OR write, not both. If there is no data then
|
||||
// we have reached the end of the stream so indicate such with true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases a block of data acquired using <see cref="::acquire method"/>. This frees the stream buffer to de-allocate the
|
||||
/// memory, if it so desires. Move the read position ahead by the count.
|
||||
/// </summary>
|
||||
/// <param name="ptr">A pointer to the block of data to be released.</param>
|
||||
/// <param name="count">The number of characters that were read.</param>
|
||||
virtual void release(_Out_writes_opt_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
if (ptr != nullptr)
|
||||
update_current_position(m_current_position + count);
|
||||
}
|
||||
|
||||
virtual pplx::task<size_t> _getn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return pplx::task_from_result(this->read(ptr, count));
|
||||
}
|
||||
|
||||
size_t _sgetn(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count);
|
||||
}
|
||||
|
||||
virtual size_t _scopy(_Out_writes_ (count) _CharType *ptr, _In_ size_t count)
|
||||
{
|
||||
return this->read(ptr, count, false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _bumpc()
|
||||
{
|
||||
return pplx::task_from_result(this->read_byte(true));
|
||||
}
|
||||
|
||||
virtual int_type _sbumpc()
|
||||
{
|
||||
return this->read_byte(true);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _getc()
|
||||
{
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
int_type _sgetc()
|
||||
{
|
||||
return this->read_byte(false);
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _nextc()
|
||||
{
|
||||
if (m_current_position >= m_size-1)
|
||||
return pplx::task_from_result(basic_streambuf<_CharType>::traits::eof());
|
||||
|
||||
this->read_byte(true);
|
||||
return pplx::task_from_result(this->read_byte(false));
|
||||
}
|
||||
|
||||
virtual pplx::task<int_type> _ungetc()
|
||||
{
|
||||
auto pos = seekoff(-1, std::ios_base::cur, std::ios_base::in);
|
||||
if ( pos == (pos_type)traits::eof())
|
||||
return pplx::task_from_result(traits::eof());
|
||||
return this->getc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current read or write position in the stream.
|
||||
/// </summary>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The current position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the direction parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type getpos(std::ios_base::openmode mode) const
|
||||
{
|
||||
if ( ((mode & std::ios_base::in) && !this->can_read()) ||
|
||||
((mode & std::ios_base::out) && !this->can_write()))
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
|
||||
if (mode == std::ios_base::in)
|
||||
return (pos_type)m_current_position;
|
||||
else if (mode == std::ios_base::out)
|
||||
return (pos_type)m_current_position;
|
||||
else
|
||||
return (pos_type)traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to the given position.
|
||||
/// </summary>
|
||||
/// <param name="pos">The offset from the beginning of the stream.</param>
|
||||
/// <param name="direction">The I/O direction to seek (see remarks).</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors. For such streams, the direction parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekpos(pos_type position, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg(0);
|
||||
pos_type end(m_size);
|
||||
|
||||
if (position >= beg)
|
||||
{
|
||||
auto pos = static_cast<size_t>(position);
|
||||
|
||||
// Read head
|
||||
if ((mode & std::ios_base::in) && this->can_read())
|
||||
{
|
||||
if (position <= end)
|
||||
{
|
||||
// We do not allow reads to seek beyond the end or before the start position.
|
||||
update_current_position(pos);
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
// Write head
|
||||
if ((mode & std::ios_base::out) && this->can_write())
|
||||
{
|
||||
// Update write head and satisfy read requests if any
|
||||
update_current_position(pos);
|
||||
|
||||
return static_cast<pos_type>(m_current_position);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeks to a position given by a relative offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The relative position to seek to</param>
|
||||
/// <param name="way">The starting point (beginning, end, current) for the seek.</param>
|
||||
/// <param name="mode">The I/O direction to seek (see remarks)</param>
|
||||
/// <returns>The position. EOF if the operation fails.</returns>
|
||||
/// <remarks>Some streams may have separate write and read cursors.
|
||||
/// For such streams, the mode parameter defines whether to move the read or the write cursor.</remarks>
|
||||
virtual pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode mode)
|
||||
{
|
||||
pos_type beg = 0;
|
||||
pos_type cur = static_cast<pos_type>(m_current_position);
|
||||
pos_type end = static_cast<pos_type>(m_size);
|
||||
|
||||
switch ( way )
|
||||
{
|
||||
case std::ios_base::beg:
|
||||
return seekpos(beg + offset, mode);
|
||||
|
||||
case std::ios_base::cur:
|
||||
return seekpos(cur + offset, mode);
|
||||
|
||||
case std::ios_base::end:
|
||||
return seekpos(end + offset, mode);
|
||||
|
||||
default:
|
||||
return static_cast<pos_type>(traits::eof());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename _CharType1> friend class ::concurrency::streams::rawptr_buffer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
basic_rawptr_buffer(const _CharType* data, size_t size)
|
||||
: streambuf_state_manager<_CharType>(std::ios_base::in),
|
||||
m_data(const_cast<_CharType*>(data)),
|
||||
m_size(size),
|
||||
m_current_position(0)
|
||||
{
|
||||
validate_mode(std::ios_base::in);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <param name="mode">The stream mode (in, out, etc.).</param>
|
||||
basic_rawptr_buffer(_CharType* data, size_t size, std::ios_base::openmode mode)
|
||||
: streambuf_state_manager<_CharType>(mode),
|
||||
m_data(data),
|
||||
m_size(size),
|
||||
m_current_position(0)
|
||||
{
|
||||
validate_mode(mode);
|
||||
}
|
||||
|
||||
static void validate_mode(std::ios_base::openmode mode)
|
||||
{
|
||||
// Disallow simultaneous use of the stream buffer for writing and reading.
|
||||
if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
|
||||
throw std::invalid_argument("this combination of modes on raw pointer stream not supported");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the request can be satisfied.
|
||||
/// </summary>
|
||||
bool can_satisfy(size_t) const
|
||||
{
|
||||
// We can always satisfy a read, at least partially, unless the
|
||||
// read position is at the very end of the buffer.
|
||||
return (in_avail() > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a byte from the stream and returns it as int_type.
|
||||
/// Note: This routine must only be called if can_satisfy() returns true.
|
||||
/// </summary>
|
||||
int_type read_byte(bool advance = true)
|
||||
{
|
||||
_CharType value;
|
||||
auto read_size = this->read(&value, 1, advance);
|
||||
return read_size == 1 ? static_cast<int_type>(value) : traits::eof();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads up to count characters into ptr and returns the count of characters copied.
|
||||
/// The return value (actual characters copied) could be <= count.
|
||||
/// Note: This routine must only be called if can_satisfy() returns true.
|
||||
/// </summary>
|
||||
size_t read(_Out_writes_ (count) _CharType *ptr, _In_ size_t count, bool advance = true)
|
||||
{
|
||||
if (!can_satisfy(count))
|
||||
return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> request_size(count);
|
||||
msl::safeint3::SafeInt<size_t> read_size = request_size.Min(in_avail());
|
||||
|
||||
size_t newPos = m_current_position + read_size;
|
||||
|
||||
auto readBegin = m_data + m_current_position;
|
||||
auto readEnd = m_data + newPos;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(readBegin, readEnd, stdext::checked_array_iterator<_CharType *>(ptr, count));
|
||||
#else
|
||||
std::copy(readBegin, readEnd, ptr);
|
||||
#endif // _WIN32
|
||||
|
||||
if (advance)
|
||||
{
|
||||
update_current_position(newPos);
|
||||
}
|
||||
|
||||
return (size_t) read_size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write count characters from the ptr into the stream buffer
|
||||
/// </summary>
|
||||
size_t write(const _CharType *ptr, size_t count)
|
||||
{
|
||||
if (!this->can_write() || (count == 0)) return 0;
|
||||
|
||||
msl::safeint3::SafeInt<size_t> newSize = msl::safeint3::SafeInt<size_t>(count) +m_current_position;
|
||||
|
||||
if ( newSize > m_size )
|
||||
throw std::runtime_error("Writing past the end of the buffer");
|
||||
|
||||
// Copy the data
|
||||
#ifdef _WIN32
|
||||
// Avoid warning C4996: Use checked iterators under SECURE_SCL
|
||||
std::copy(ptr, ptr + count, stdext::checked_array_iterator<_CharType *>(m_data, m_size, m_current_position));
|
||||
#else
|
||||
std::copy(ptr, ptr + count, m_data+m_current_position);
|
||||
#endif // _WIN32
|
||||
|
||||
// Update write head and satisfy pending reads if any
|
||||
update_current_position(newSize);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the current read or write position
|
||||
/// </summary>
|
||||
void update_current_position(size_t newPos)
|
||||
{
|
||||
// The new write head
|
||||
m_current_position = newPos;
|
||||
|
||||
_ASSERTE(m_current_position <= m_size);
|
||||
}
|
||||
|
||||
// The actual memory block
|
||||
_CharType* m_data;
|
||||
|
||||
// The size of the memory block
|
||||
size_t m_size;
|
||||
|
||||
// Read/write head
|
||||
size_t m_current_position;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// The <c>rawptr_buffer</c> class serves as a memory-based stream buffer that supports reading
|
||||
/// sequences of characters to or from a fixed-size block. Note that it cannot be used simultaneously for reading as well as writing.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>rawptr_buffer</c>.
|
||||
/// </typeparam>
|
||||
template<typename _CharType>
|
||||
class rawptr_buffer : public streambuf<_CharType>
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr_buffer given a pointer to a memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
rawptr_buffer(const char_type* data, size_t size)
|
||||
: streambuf<char_type>(std::shared_ptr<details::basic_rawptr_buffer<char_type>>(new details::basic_rawptr_buffer<char_type>(data, size)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr_buffer given a pointer to a memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
rawptr_buffer(char_type* data, size_t size, std::ios_base::openmode mode = std::ios::out)
|
||||
: streambuf<char_type>(std::shared_ptr<details::basic_rawptr_buffer<char_type>>(new details::basic_rawptr_buffer<char_type>(data, size, mode)))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
rawptr_buffer()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The rawptr_stream class is used to create memory-backed streams that support writing or reading
|
||||
/// sequences of characters to / from a fixed-size block.
|
||||
/// </summary>
|
||||
/// <typeparam name="_CharType">
|
||||
/// The data type of the basic element of the <c>rawptr_stream</c>.
|
||||
/// </typeparam>
|
||||
template<typename _CharType>
|
||||
class rawptr_stream
|
||||
{
|
||||
public:
|
||||
typedef _CharType char_type;
|
||||
typedef rawptr_buffer<_CharType> buffer_type;
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a read-only memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(const char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(data, size));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a writable memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened input stream.</returns>
|
||||
static concurrency::streams::basic_istream<char_type> open_istream(char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_istream<char_type>(buffer_type(data, size, std::ios::in));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a rawptr-stream given a pointer to a writable memory block and the size of the block.
|
||||
/// </summary>
|
||||
/// <param name="data">The address (pointer to) the memory block.</param>
|
||||
/// <param name="size">The memory block size, measured in number of characters.</param>
|
||||
/// <returns>An opened output stream.</returns>
|
||||
static concurrency::streams::basic_ostream<char_type> open_ostream(char_type* data, size_t size)
|
||||
{
|
||||
return concurrency::streams::basic_ostream<char_type>(buffer_type(data, size, std::ios::out));
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespaces
|
||||
|
||||
#endif
|
1799
3rdparty/cpprestsdk/include/cpprest/streams.h
vendored
Normal file
1799
3rdparty/cpprestsdk/include/cpprest/streams.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
35
3rdparty/cpprestsdk/include/cpprest/uri.h
vendored
Normal file
35
3rdparty/cpprestsdk/include/cpprest/uri.h
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_URI_H
|
||||
#define _CASA_URI_H
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
#include "cpprest/uri_builder.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
266
3rdparty/cpprestsdk/include/cpprest/uri_builder.h
vendored
Normal file
266
3rdparty/cpprestsdk/include/cpprest/uri_builder.h
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Builder style class for creating URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder for constructing URIs incrementally.
|
||||
/// </summary>
|
||||
class uri_builder
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Creates a builder with an initially empty URI.
|
||||
/// </summary>
|
||||
uri_builder() {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a builder with a existing URI object.
|
||||
/// </summary>
|
||||
/// <param name="uri_str">Encoded string containing the URI.</param>
|
||||
uri_builder(const uri &uri_str): m_uri(uri_str.m_components) {}
|
||||
|
||||
/// <summary>
|
||||
/// Get the scheme component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI scheme as a string.</returns>
|
||||
const utility::string_t &scheme() const { return m_uri.m_scheme; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the user information component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI user information as a string.</returns>
|
||||
const utility::string_t &user_info() const { return m_uri.m_user_info; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the host component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI host as a string.</returns>
|
||||
const utility::string_t &host() const { return m_uri.m_host; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||||
/// </summary>
|
||||
/// <returns>The URI port as an integer.</returns>
|
||||
int port() const { return m_uri.m_port; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the path component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI path as a string.</returns>
|
||||
const utility::string_t &path() const { return m_uri.m_path; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the query component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI query as a string.</returns>
|
||||
const utility::string_t &query() const { return m_uri.m_query; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the fragment component of the URI as an encoded string.
|
||||
/// </summary>
|
||||
/// <returns>The URI fragment as a string.</returns>
|
||||
const utility::string_t &fragment() const { return m_uri.m_fragment; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the scheme of the URI.
|
||||
/// </summary>
|
||||
/// <param name="scheme">Uri scheme.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_scheme(const utility::string_t &scheme)
|
||||
{
|
||||
m_uri.m_scheme = scheme;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user info component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="user_info">User info as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_user_info(const utility::string_t &user_info, bool do_encoding = false)
|
||||
{
|
||||
m_uri.m_user_info = do_encoding ? uri::encode_uri(user_info, uri::components::user_info) : user_info;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the host component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="host">Host as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_host(const utility::string_t &host, bool do_encoding = false)
|
||||
{
|
||||
m_uri.m_host = do_encoding ? uri::encode_uri(host, uri::components::host) : host;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the port component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="port">Port as an integer.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_port(int port)
|
||||
{
|
||||
m_uri.m_port = port;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the port component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="port">Port as a string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
/// <remarks>When string can't be converted to an integer the port is left unchanged.</remarks>
|
||||
uri_builder & set_port(const utility::string_t &port)
|
||||
{
|
||||
utility::istringstream_t portStream(port);
|
||||
int port_tmp;
|
||||
portStream >> port_tmp;
|
||||
if(portStream.fail() || portStream.bad())
|
||||
{
|
||||
throw std::invalid_argument("invalid port argument, must be non empty string containing integer value");
|
||||
}
|
||||
m_uri.m_port = port_tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the path component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="path">Path as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_path(const utility::string_t &path, bool do_encoding = false)
|
||||
{
|
||||
m_uri.m_path = do_encoding ? uri::encode_uri(path, uri::components::path) : path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set the query component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="query">Query as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_query(const utility::string_t &query, bool do_encoding = false)
|
||||
{
|
||||
m_uri.m_query = do_encoding ? uri::encode_uri(query, uri::components::query) : query;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the fragment component of the URI.
|
||||
/// </summary>
|
||||
/// <param name="fragment">Fragment as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||||
uri_builder & set_fragment(const utility::string_t &fragment, bool do_encoding = false)
|
||||
{
|
||||
m_uri.m_fragment = do_encoding ? uri::encode_uri(fragment, uri::components::fragment) : fragment;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all components of the underlying URI in this uri_builder.
|
||||
/// </summary>
|
||||
void clear()
|
||||
{
|
||||
m_uri = details::uri_components();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends another path to the path of this uri_builder.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to append as a already encoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder &append_path(const utility::string_t &path, bool do_encoding = false);
|
||||
|
||||
/// <summary>
|
||||
/// Appends another query to the query of this uri_builder.
|
||||
/// </summary>
|
||||
/// <param name="query">Query to append as a decoded string.</param>
|
||||
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder &append_query(const utility::string_t &query, bool do_encoding = false);
|
||||
|
||||
/// <summary>
|
||||
/// Appends an relative uri (Path, Query and fragment) at the end of the current uri.
|
||||
/// </summary>
|
||||
/// <param name="relative_uri">The relative uri to append.</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
_ASYNCRTIMP uri_builder &append(const uri &relative_uri);
|
||||
|
||||
/// <summary>
|
||||
/// Appends another query to the query of this uri_builder, encoding it first. This overload is useful when building a query segment of
|
||||
/// the form "element=10", where the right hand side of the query is stored as a type other than a string, for instance, an integral type.
|
||||
/// </summary>
|
||||
/// <param name="name">The name portion of the query string</param>
|
||||
/// <param name="value">The value portion of the query string</param>
|
||||
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||||
template<typename T>
|
||||
uri_builder &append_query(utility::string_t name, const T &value, bool do_encoding = true)
|
||||
{
|
||||
utility::ostringstream_t ss;
|
||||
ss.imbue(std::locale::classic());
|
||||
ss << name << _XPLATSTR("=") << value;
|
||||
return append_query(ss.str(), do_encoding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combine and validate the URI components into a encoded string. An exception will be thrown if the URI is invalid.
|
||||
/// </summary>
|
||||
/// <returns>The created URI as a string.</returns>
|
||||
_ASYNCRTIMP utility::string_t to_string();
|
||||
|
||||
/// <summary>
|
||||
/// Combine and validate the URI components into a URI class instance. An exception will be thrown if the URI is invalid.
|
||||
/// </summary>
|
||||
/// <returns>The create URI as a URI class instance.</returns>
|
||||
_ASYNCRTIMP uri to_uri();
|
||||
|
||||
/// <summary>
|
||||
/// Validate the generated URI from all existing components of this uri_builder.
|
||||
/// </summary>
|
||||
/// <returns>Whether the URI is valid.</returns>
|
||||
_ASYNCRTIMP bool is_valid();
|
||||
|
||||
private:
|
||||
details::uri_components m_uri;
|
||||
};
|
||||
} // namespace web
|
22
3rdparty/cpprestsdk/include/cpprest/version.h
vendored
Normal file
22
3rdparty/cpprestsdk/include/cpprest/version.h
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
*/
|
||||
#define CPPREST_VERSION_REVISION 0
|
||||
#define CPPREST_VERSION_MINOR 6
|
||||
#define CPPREST_VERSION_MAJOR 2
|
||||
|
||||
#define CPPREST_VERSION (CPPREST_VERSION_MAJOR*100000+CPPREST_VERSION_MINOR*100+CPPREST_VERSION_REVISION)
|
627
3rdparty/cpprestsdk/include/cpprest/ws_client.h
vendored
Normal file
627
3rdparty/cpprestsdk/include/cpprest/ws_client.h
vendored
Normal file
|
@ -0,0 +1,627 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Websocket client side implementation
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef _CASA_WS_CLIENT_H
|
||||
#define _CASA_WS_CLIENT_H
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_headers.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/ws_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
|
||||
// For backwards compatibility for when in the experimental namespace.
|
||||
// At next major release this should be deleted.
|
||||
namespace experimental = web;
|
||||
|
||||
// In the past namespace was accidentally called 'web_sockets'. To avoid breaking code
|
||||
// alias it. At our next major release this should be deleted.
|
||||
namespace web_sockets = websockets;
|
||||
|
||||
namespace websockets
|
||||
{
|
||||
/// WebSocket client side library.
|
||||
namespace client
|
||||
{
|
||||
|
||||
/// Websocket close status values.
|
||||
enum class websocket_close_status
|
||||
{
|
||||
normal = 1000,
|
||||
going_away = 1001,
|
||||
protocol_error = 1002,
|
||||
unsupported = 1003, //or data_mismatch
|
||||
abnormal_close = 1006,
|
||||
inconsistent_datatype = 1007,
|
||||
policy_violation = 1008,
|
||||
too_large = 1009,
|
||||
negotiate_error = 1010,
|
||||
server_terminate = 1011,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client configuration class, used to set the possible configuration options
|
||||
/// used to create an websocket_client instance.
|
||||
/// </summary>
|
||||
class websocket_client_config
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Creates a websocket client configuration with default settings.
|
||||
/// </summary>
|
||||
websocket_client_config() : m_sni_enabled(true) {}
|
||||
|
||||
/// <summary>
|
||||
/// Get the web proxy object
|
||||
/// </summary>
|
||||
/// <returns>A reference to the web proxy object.</returns>
|
||||
const web_proxy& proxy() const
|
||||
{
|
||||
return m_proxy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the web proxy object
|
||||
/// </summary>
|
||||
/// <param name="proxy">The web proxy object.</param>
|
||||
void set_proxy(const web_proxy &proxy)
|
||||
{
|
||||
m_proxy = proxy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the client credentials
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client credentials.</returns>
|
||||
const web::credentials& credentials() const
|
||||
{
|
||||
return m_credentials;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the client credentials
|
||||
/// </summary>
|
||||
/// <param name="cred">The client credentials.</param>
|
||||
void set_credentials(const web::credentials &cred)
|
||||
{
|
||||
m_credentials = cred;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables Server Name Indication (SNI). Default is on.
|
||||
/// </summary>
|
||||
void disable_sni()
|
||||
{
|
||||
m_sni_enabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if Server Name Indication (SNI) is enabled.
|
||||
/// </summary>
|
||||
/// <returns>True if enabled, false otherwise.</returns>
|
||||
bool is_sni_enabled() const
|
||||
{
|
||||
return m_sni_enabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the server host name to use for TLS Server Name Indication (SNI).
|
||||
/// </summary>
|
||||
/// <remarks>By default the host name is set to the websocket URI host.</remarks>
|
||||
/// <param name="name">The host name to use, as a string.</param>
|
||||
void set_server_name(const utf8string &name)
|
||||
{
|
||||
m_sni_hostname = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server host name to usefor TLS Server Name Indication (SNI).
|
||||
/// </summary>
|
||||
/// <returns>Host name as a string.</returns>
|
||||
const utf8string & server_name() const
|
||||
{
|
||||
return m_sni_hostname;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers of the HTTP request message used in the WebSocket protocol handshake.
|
||||
/// </summary>
|
||||
/// <returns>HTTP headers for the WebSocket protocol handshake.</returns>
|
||||
/// <remarks>
|
||||
/// Use the <seealso cref="http_headers::add Method"/> to fill in desired headers.
|
||||
/// </remarks>
|
||||
web::http::http_headers &headers() { return m_headers; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a const reference to the headers of the WebSocket protocol handshake HTTP message.
|
||||
/// </summary>
|
||||
/// <returns>HTTP headers.</returns>
|
||||
const web::http::http_headers &headers() const { return m_headers; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a subprotocol to the request headers.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the subprotocol.</param>
|
||||
/// <remarks>If additional subprotocols have already been specified, the new one will just be added.</remarks>
|
||||
_ASYNCRTIMP void add_subprotocol(const ::utility::string_t &name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of the specified subprotocols.
|
||||
/// </summary>
|
||||
/// <returns>Vector of all the subprotocols </returns>
|
||||
/// <remarks>If you want all the subprotocols in a comma separated string
|
||||
/// they can be directly looked up in the headers using 'Sec-WebSocket-Protocol'.</remarks>
|
||||
_ASYNCRTIMP std::vector<::utility::string_t> subprotocols() const;
|
||||
|
||||
private:
|
||||
web::web_proxy m_proxy;
|
||||
web::credentials m_credentials;
|
||||
web::http::http_headers m_headers;
|
||||
bool m_sni_enabled;
|
||||
utf8string m_sni_hostname;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a websocket error. This class holds an error message and an optional error code.
|
||||
/// </summary>
|
||||
class websocket_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <c>websocket_exception</c> with just a string message and no error code.
|
||||
/// </summary>
|
||||
/// <param name="whatArg">Error message string.</param>
|
||||
websocket_exception(const utility::string_t &whatArg)
|
||||
: m_msg(utility::conversions::to_utf8string(whatArg)) {}
|
||||
|
||||
#ifdef _WIN32
|
||||
/// <summary>
|
||||
/// Creates an <c>websocket_exception</c> with just a string message and no error code.
|
||||
/// </summary>
|
||||
/// <param name="whatArg">Error message string.</param>
|
||||
websocket_exception(std::string whatArg) : m_msg(std::move(whatArg)) {}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code using the current platform error category.
|
||||
/// The message of the error code will be used as the what() string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
websocket_exception(int errorCode)
|
||||
: m_errorCode(utility::details::create_error_code(errorCode))
|
||||
{
|
||||
m_msg = m_errorCode.message();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code using the current platform error category.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
websocket_exception(int errorCode, const utility::string_t &whatArg)
|
||||
: m_errorCode(utility::details::create_error_code(errorCode)),
|
||||
m_msg(utility::conversions::to_utf8string(whatArg))
|
||||
{}
|
||||
|
||||
#ifdef _WIN32
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
websocket_exception(int errorCode, std::string whatArg)
|
||||
: m_errorCode(utility::details::create_error_code(errorCode)),
|
||||
m_msg(std::move(whatArg))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message to use as the what() argument.
|
||||
/// <param name="code">Error code.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
/// </summary>
|
||||
websocket_exception(std::error_code code, std::string whatArg) :
|
||||
m_errorCode(std::move(code)),
|
||||
m_msg(std::move(whatArg))
|
||||
{}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and category. The message of the error code will be used
|
||||
/// as the <c>what</c> string message.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">Error code value.</param>
|
||||
/// <param name="cat">Error category for the code.</param>
|
||||
websocket_exception(int errorCode, const std::error_category &cat) : m_errorCode(std::error_code(errorCode, cat))
|
||||
{
|
||||
m_msg = m_errorCode.message();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <c>websocket_exception</c> from a error code and string message to use as the what() argument.
|
||||
/// <param name="code">Error code.</param>
|
||||
/// <param name="whatArg">Message to use in what() string.</param>
|
||||
/// </summary>
|
||||
websocket_exception(std::error_code code, const utility::string_t &whatArg) :
|
||||
m_errorCode(std::move(code)),
|
||||
m_msg(utility::conversions::to_utf8string(whatArg))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string identifying the cause of the exception.
|
||||
/// </summary>
|
||||
/// <returns>A null terminated character string.</returns>
|
||||
const char* what() const CPPREST_NOEXCEPT
|
||||
{
|
||||
return m_msg.c_str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the underlying error code for the cause of the exception.
|
||||
/// </summary>
|
||||
/// <returns>The <c>error_code</c> object associated with the exception.</returns>
|
||||
const std::error_code & error_code() const CPPREST_NOEXCEPT
|
||||
{
|
||||
return m_errorCode;
|
||||
}
|
||||
|
||||
private:
|
||||
std::error_code m_errorCode;
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
|
||||
// Interface to be implemented by the websocket client callback implementations.
|
||||
class websocket_client_callback_impl
|
||||
{
|
||||
public:
|
||||
|
||||
websocket_client_callback_impl(websocket_client_config config) :
|
||||
m_config(std::move(config)) {}
|
||||
|
||||
virtual ~websocket_client_callback_impl() CPPREST_NOEXCEPT{}
|
||||
|
||||
virtual pplx::task<void> connect() = 0;
|
||||
|
||||
virtual pplx::task<void> send(websocket_outgoing_message &msg) = 0;
|
||||
|
||||
virtual void set_message_handler(const std::function<void(const websocket_incoming_message&)>& handler) = 0;
|
||||
|
||||
virtual pplx::task<void> close() = 0;
|
||||
|
||||
virtual pplx::task<void> close(websocket_close_status close_status, const utility::string_t &close_reason = _XPLATSTR("")) = 0;
|
||||
|
||||
virtual void set_close_handler(const std::function<void(websocket_close_status, const utility::string_t&, const std::error_code&)>& handler) = 0;
|
||||
|
||||
const web::uri& uri() const
|
||||
{
|
||||
return m_uri;
|
||||
}
|
||||
|
||||
void set_uri(const web::uri &uri)
|
||||
{
|
||||
m_uri = uri;
|
||||
}
|
||||
|
||||
const websocket_client_config& config() const
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
static void verify_uri(const web::uri& uri)
|
||||
{
|
||||
// Most of the URI schema validation is taken care by URI class.
|
||||
// We only need to check certain things specific to websockets.
|
||||
if (uri.scheme() != _XPLATSTR("ws") && uri.scheme() != _XPLATSTR("wss"))
|
||||
{
|
||||
throw std::invalid_argument("URI scheme must be 'ws' or 'wss'");
|
||||
}
|
||||
|
||||
if (uri.host().empty())
|
||||
{
|
||||
throw std::invalid_argument("URI must contain a hostname.");
|
||||
}
|
||||
|
||||
// Fragment identifiers are meaningless in the context of WebSocket URIs
|
||||
// and MUST NOT be used on these URIs.
|
||||
if (!uri.fragment().empty())
|
||||
{
|
||||
throw std::invalid_argument("WebSocket URI must not contain fragment identifiers");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
web::uri m_uri;
|
||||
websocket_client_config m_config;
|
||||
};
|
||||
|
||||
// Interface to be implemented by the websocket client task implementations.
|
||||
class websocket_client_task_impl
|
||||
{
|
||||
|
||||
public:
|
||||
_ASYNCRTIMP websocket_client_task_impl(websocket_client_config config);
|
||||
|
||||
_ASYNCRTIMP virtual ~websocket_client_task_impl() CPPREST_NOEXCEPT;
|
||||
|
||||
_ASYNCRTIMP pplx::task<websocket_incoming_message> receive();
|
||||
|
||||
_ASYNCRTIMP void close_pending_tasks_with_error(const websocket_exception &exc);
|
||||
|
||||
const std::shared_ptr<websocket_client_callback_impl> & callback_client() const { return m_callback_client; };
|
||||
|
||||
private:
|
||||
void set_handler();
|
||||
|
||||
// When a message arrives, if there are tasks waiting for a message, signal the topmost one.
|
||||
// Else enqueue the message in a queue.
|
||||
// m_receive_queue_lock : to guard access to the queue & m_client_closed
|
||||
std::mutex m_receive_queue_lock;
|
||||
// Queue to store incoming messages when there are no tasks waiting for a message
|
||||
std::queue<websocket_incoming_message> m_receive_msg_queue;
|
||||
// Queue to maintain the receive tasks when there are no messages(yet).
|
||||
std::queue<pplx::task_completion_event<websocket_incoming_message>> m_receive_task_queue;
|
||||
|
||||
// Initially set to false, becomes true if a close frame is received from the server or
|
||||
// if the underlying connection is aborted or terminated.
|
||||
bool m_client_closed;
|
||||
|
||||
std::shared_ptr<websocket_client_callback_impl> m_callback_client;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client class, used to maintain a connection to a remote host for an extended session.
|
||||
/// </summary>
|
||||
class websocket_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new websocket_client.
|
||||
/// </summary>
|
||||
websocket_client() :
|
||||
m_client(std::make_shared<details::websocket_client_task_impl>(websocket_client_config()))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new websocket_client.
|
||||
/// </summary>
|
||||
/// <param name="config">The client configuration object containing the possible configuration options to initialize the <c>websocket_client</c>. </param>
|
||||
websocket_client(websocket_client_config config) :
|
||||
m_client(std::make_shared<details::websocket_client_task_impl>(std::move(config)))
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the remote network destination. The connect method initiates the websocket handshake with the
|
||||
/// remote network destination, takes care of the protocol upgrade request.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri address to connect. </param>
|
||||
/// <returns>An asynchronous operation that is completed once the client has successfully connected to the websocket server.</returns>
|
||||
pplx::task<void> connect(const web::uri &uri)
|
||||
{
|
||||
m_client->callback_client()->verify_uri(uri);
|
||||
m_client->callback_client()->set_uri(uri);
|
||||
auto client = m_client;
|
||||
return m_client->callback_client()->connect().then([client](pplx::task<void> result)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.get();
|
||||
}
|
||||
catch (const websocket_exception& ex)
|
||||
{
|
||||
client->close_pending_tasks_with_error(ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a websocket message to the server .
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed once the message is sent.</returns>
|
||||
pplx::task<void> send(websocket_outgoing_message msg)
|
||||
{
|
||||
return m_client->callback_client()->send(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receive a websocket message.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed when a message has been received by the client endpoint.</returns>
|
||||
pplx::task<websocket_incoming_message> receive()
|
||||
{
|
||||
return m_client->receive();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the server.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close()
|
||||
{
|
||||
return m_client->callback_client()->close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the server.
|
||||
/// </summary>
|
||||
/// <param name="close_status">Endpoint MAY use the following pre-defined status codes when sending a Close frame.</param>
|
||||
/// <param name="close_reason">While closing an established connection, an endpoint may indicate the reason for closure.</param>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close(websocket_close_status close_status, const utility::string_t& close_reason=_XPLATSTR(""))
|
||||
{
|
||||
return m_client->callback_client()->close(close_status, close_reason);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client URI.
|
||||
/// </summary>
|
||||
/// <returns>URI connected to.</returns>
|
||||
const web::uri& uri() const
|
||||
{
|
||||
return m_client->callback_client()->uri();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client config object.
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
const websocket_client_config& config() const
|
||||
{
|
||||
return m_client->callback_client()->config();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<details::websocket_client_task_impl> m_client;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Websocket client class, used to maintain a connection to a remote host for an extended session, uses callback APIs for handling receive and close event instead of async task.
|
||||
/// For some scenarios would be a alternative for the websocket_client like if you want to special handling on close event.
|
||||
/// </summary>
|
||||
class websocket_callback_client
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Creates a new websocket_callback_client.
|
||||
/// </summary>
|
||||
_ASYNCRTIMP websocket_callback_client();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new websocket_callback_client.
|
||||
/// </summary>
|
||||
/// <param name="client_config">The client configuration object containing the possible configuration options to initialize the <c>websocket_client</c>. </param>
|
||||
_ASYNCRTIMP websocket_callback_client(websocket_client_config client_config);
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the remote network destination. The connect method initiates the websocket handshake with the
|
||||
/// remote network destination, takes care of the protocol upgrade request.
|
||||
/// </summary>
|
||||
/// <param name="uri">The uri address to connect. </param>
|
||||
/// <returns>An asynchronous operation that is completed once the client has successfully connected to the websocket server.</returns>
|
||||
pplx::task<void> connect(const web::uri &uri)
|
||||
{
|
||||
m_client->verify_uri(uri);
|
||||
m_client->set_uri(uri);
|
||||
return m_client->connect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a websocket message to the server .
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed once the message is sent.</returns>
|
||||
pplx::task<void> send(websocket_outgoing_message msg)
|
||||
{
|
||||
return m_client->send(msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the received handler for notification of client websocket messages.
|
||||
/// </summary>
|
||||
/// <param name="handler">A function representing the incoming websocket messages handler. It's parameters are:
|
||||
/// msg: a <c>websocket_incoming_message</c> value indicating the message received
|
||||
/// </param>
|
||||
/// <remarks>If this handler is not set before connecting incoming messages will be missed.</remarks>
|
||||
void set_message_handler(const std::function<void(const websocket_incoming_message& msg)>& handler)
|
||||
{
|
||||
m_client->set_message_handler(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the server.
|
||||
/// </summary>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close()
|
||||
{
|
||||
return m_client->close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes a websocket client connection, sends a close frame to the server and waits for a close message from the server.
|
||||
/// </summary>
|
||||
/// <param name="close_status">Endpoint MAY use the following pre-defined status codes when sending a Close frame.</param>
|
||||
/// <param name="close_reason">While closing an established connection, an endpoint may indicate the reason for closure.</param>
|
||||
/// <returns>An asynchronous operation that is completed the connection has been successfully closed.</returns>
|
||||
pplx::task<void> close(websocket_close_status close_status, const utility::string_t& close_reason = _XPLATSTR(""))
|
||||
{
|
||||
return m_client->close(close_status, close_reason);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the closed handler for notification of client websocket closing event.
|
||||
/// </summary>
|
||||
/// <param name="handler">The handler for websocket closing event, It's parameters are:
|
||||
/// close_status: The pre-defined status codes used by the endpoint when sending a Close frame.
|
||||
/// reason: The reason string used by the endpoint when sending a Close frame.
|
||||
/// error: The error code if the websocket is closed with abnormal error.
|
||||
/// </param>
|
||||
void set_close_handler(const std::function<void(websocket_close_status close_status, const utility::string_t& reason, const std::error_code& error)>& handler)
|
||||
{
|
||||
m_client->set_close_handler(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client URI.
|
||||
/// </summary>
|
||||
/// <returns>URI connected to.</returns>
|
||||
const web::uri& uri() const
|
||||
{
|
||||
return m_client->uri();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the websocket client config object.
|
||||
/// </summary>
|
||||
/// <returns>A reference to the client configuration object.</returns>
|
||||
const websocket_client_config& config() const
|
||||
{
|
||||
return m_client->config();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<details::websocket_client_callback_impl> m_client;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
242
3rdparty/cpprestsdk/include/cpprest/ws_msg.h
vendored
Normal file
242
3rdparty/cpprestsdk/include/cpprest/ws_msg.h
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Websocket incoming and outgoing message definitions.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "cpprest/containerstream.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace websockets
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
class winrt_callback_client;
|
||||
class wspp_callback_client;
|
||||
#if defined(__cplusplus_winrt)
|
||||
ref class ReceiveContext;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The different types of websocket message.
|
||||
/// Text type contains UTF-8 encoded data.
|
||||
/// Interpretation of Binary type is left to the application.
|
||||
/// Note: The fragment types and control frames like close, ping, pong are not supported on WinRT.
|
||||
/// </summary>
|
||||
enum class websocket_message_type
|
||||
{
|
||||
text_message,
|
||||
binary_message,
|
||||
close,
|
||||
ping,
|
||||
pong
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents an outgoing websocket message
|
||||
/// </summary>
|
||||
class websocket_outgoing_message
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing body of the message.</param>
|
||||
void set_utf8_message(std::string &&data)
|
||||
{
|
||||
this->set_message(concurrency::streams::container_buffer<std::string>(std::move(data)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing body of the message.</param>
|
||||
void set_utf8_message(const std::string &data)
|
||||
{
|
||||
this->set_message(concurrency::streams::container_buffer<std::string>(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <remarks>Upon sending, the entire stream may be buffered to determine the length.</remarks>
|
||||
void set_utf8_message(const concurrency::streams::istream &istream)
|
||||
{
|
||||
this->set_message(istream, SIZE_MAX, websocket_message_type::text_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a UTF-8 message as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <param name="len">number of bytes to send.</param>
|
||||
void set_utf8_message(const concurrency::streams::istream &istream, size_t len)
|
||||
{
|
||||
this->set_message(istream, len, websocket_message_type::text_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets binary data as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">casablanca input stream representing the body of the message.</param>
|
||||
/// <param name="len">number of bytes to send.</param>
|
||||
void set_binary_message(const concurrency::streams::istream &istream, size_t len)
|
||||
{
|
||||
this->set_message(istream, len, websocket_message_type::binary_message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets binary data as the message body.
|
||||
/// </summary>
|
||||
/// <param name="istream">Input stream representing the body of the message.</param>
|
||||
/// <remarks>Upon sending, the entire stream may be buffered to determine the length.</remarks>
|
||||
void set_binary_message(const concurrency::streams::istream &istream)
|
||||
{
|
||||
this->set_message(istream, SIZE_MAX, websocket_message_type::binary_message);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class details::winrt_callback_client;
|
||||
friend class details::wspp_callback_client;
|
||||
|
||||
pplx::task_completion_event<void> m_body_sent;
|
||||
concurrency::streams::streambuf<uint8_t> m_body;
|
||||
websocket_message_type m_msg_type;
|
||||
size_t m_length;
|
||||
|
||||
void signal_body_sent() const
|
||||
{
|
||||
m_body_sent.set();
|
||||
}
|
||||
|
||||
void signal_body_sent(const std::exception_ptr &e) const
|
||||
{
|
||||
m_body_sent.set_exception(e);
|
||||
}
|
||||
|
||||
const pplx::task_completion_event<void> & body_sent() const { return m_body_sent; }
|
||||
|
||||
void set_message(const concurrency::streams::container_buffer<std::string> &buffer)
|
||||
{
|
||||
m_msg_type = websocket_message_type::text_message;
|
||||
m_length = static_cast<size_t>(buffer.size());
|
||||
m_body = buffer;
|
||||
}
|
||||
|
||||
void set_message(const concurrency::streams::istream &istream, size_t len, websocket_message_type msg_type)
|
||||
{
|
||||
m_msg_type = msg_type;
|
||||
m_length = len;
|
||||
m_body = istream.streambuf();
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents an incoming websocket message
|
||||
/// </summary>
|
||||
class websocket_incoming_message
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the body of the incoming message as a string value, only if the message type is UTF-8.
|
||||
/// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out.
|
||||
/// </summary>
|
||||
/// <returns>String containing body of the message.</returns>
|
||||
_ASYNCRTIMP pplx::task<std::string> extract_string() const;
|
||||
|
||||
/// <summary>
|
||||
/// Produces a stream which the caller may use to retrieve body from an incoming message.
|
||||
/// Can be used for both UTF-8 (text) and binary message types.
|
||||
/// </summary>
|
||||
/// <returns>A readable, open asynchronous stream.</returns>
|
||||
/// <remarks>
|
||||
/// This cannot be used in conjunction with any other means of getting the body of the message.
|
||||
/// </remarks>
|
||||
concurrency::streams::istream body() const
|
||||
{
|
||||
auto to_uint8_t_stream = [](const concurrency::streams::streambuf<uint8_t> &buf) -> concurrency::streams::istream
|
||||
{
|
||||
return buf.create_istream();
|
||||
};
|
||||
return to_uint8_t_stream(m_body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the received message.
|
||||
/// </summary>
|
||||
size_t length() const
|
||||
{
|
||||
return static_cast<size_t>(m_body.size());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the type of the received message.
|
||||
/// </summary>
|
||||
CASABLANCA_DEPRECATED("Incorrectly spelled API, use message_type() instead.")
|
||||
websocket_message_type messge_type() const
|
||||
{
|
||||
return m_msg_type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the type of the received message, either string or binary.
|
||||
/// </summary>
|
||||
/// <returns>websocket_message_type</returns>
|
||||
websocket_message_type message_type() const
|
||||
{
|
||||
return m_msg_type;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class details::winrt_callback_client;
|
||||
friend class details::wspp_callback_client;
|
||||
#if defined(__cplusplus_winrt)
|
||||
friend ref class details::ReceiveContext;
|
||||
#endif
|
||||
|
||||
// Store message body in a container buffer backed by a string.
|
||||
// Allows for optimization in the string message cases.
|
||||
concurrency::streams::container_buffer<std::string> m_body;
|
||||
websocket_message_type m_msg_type;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
237
3rdparty/cpprestsdk/include/pplx/pplx.h
vendored
Normal file
237
3rdparty/cpprestsdk/include/pplx/pplx.h
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Parallel Patterns Library
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PPLX_H
|
||||
#define _PPLX_H
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
|
||||
#error This file must not be included for Visual Studio 12 or later
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#if defined(_WIN32) || defined(__cplusplus_winrt)
|
||||
#define _WIN32
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _NO_PPLXIMP
|
||||
#define _PPLXIMP
|
||||
#else
|
||||
#ifdef _PPLX_EXPORT
|
||||
#define _PPLXIMP __declspec(dllexport)
|
||||
#else
|
||||
#define _PPLXIMP __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
|
||||
// Use PPLx
|
||||
#ifdef _WIN32
|
||||
#include "pplx/pplxwin.h"
|
||||
#elif defined(__APPLE__)
|
||||
#undef _PPLXIMP
|
||||
#define _PPLXIMP
|
||||
#include "pplx/pplxlinux.h"
|
||||
#else
|
||||
#include "pplx/pplxlinux.h"
|
||||
#endif // _WIN32
|
||||
|
||||
// Common implementation across all the non-concrt versions
|
||||
#include "pplx/pplxcancellation_token.h"
|
||||
#include <functional>
|
||||
|
||||
// conditional expression is constant
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127)
|
||||
#endif
|
||||
|
||||
#pragma pack(push,_CRT_PACKING)
|
||||
|
||||
/// <summary>
|
||||
/// The <c>pplx</c> namespace provides classes and functions that give you access to the Concurrency Runtime,
|
||||
/// a concurrent programming framework for C++. For more information, see <see cref="Concurrency Runtime"/>.
|
||||
/// </summary>
|
||||
/**/
|
||||
namespace pplx
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Sets the ambient scheduler to be used by the PPL constructs.
|
||||
/// </summary>
|
||||
_PPLXIMP void _pplx_cdecl set_ambient_scheduler(std::shared_ptr<pplx::scheduler_interface> _Scheduler);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ambient scheduler to be used by the PPL constructs
|
||||
/// </summary>
|
||||
_PPLXIMP std::shared_ptr<pplx::scheduler_interface> _pplx_cdecl get_ambient_scheduler();
|
||||
|
||||
namespace details
|
||||
{
|
||||
//
|
||||
// An internal exception that is used for cancellation. Users do not "see" this exception except through the
|
||||
// resulting stack unwind. This exception should never be intercepted by user code. It is intended
|
||||
// for use by the runtime only.
|
||||
//
|
||||
class _Interruption_exception : public std::exception
|
||||
{
|
||||
public:
|
||||
_Interruption_exception(){}
|
||||
};
|
||||
|
||||
template<typename _T>
|
||||
struct _AutoDeleter
|
||||
{
|
||||
_AutoDeleter(_T *_PPtr) : _Ptr(_PPtr) {}
|
||||
~_AutoDeleter () { delete _Ptr; }
|
||||
_T *_Ptr;
|
||||
};
|
||||
|
||||
struct _TaskProcHandle
|
||||
{
|
||||
_TaskProcHandle()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~_TaskProcHandle() {}
|
||||
virtual void invoke() const = 0;
|
||||
|
||||
static void _pplx_cdecl _RunChoreBridge(void * _Parameter)
|
||||
{
|
||||
auto _PTaskHandle = static_cast<_TaskProcHandle *>(_Parameter);
|
||||
_AutoDeleter<_TaskProcHandle> _AutoDeleter(_PTaskHandle);
|
||||
_PTaskHandle->invoke();
|
||||
}
|
||||
};
|
||||
|
||||
enum _TaskInliningMode
|
||||
{
|
||||
// Disable inline scheduling
|
||||
_NoInline = 0,
|
||||
// Let runtime decide whether to do inline scheduling or not
|
||||
_DefaultAutoInline = 16,
|
||||
// Always do inline scheduling
|
||||
_ForceInline = -1,
|
||||
};
|
||||
|
||||
// This is an abstraction that is built on top of the scheduler to provide these additional functionalities
|
||||
// - Ability to wait on a work item
|
||||
// - Ability to cancel a work item
|
||||
// - Ability to inline work on invocation of RunAndWait
|
||||
class _TaskCollectionImpl
|
||||
{
|
||||
public:
|
||||
|
||||
typedef _TaskProcHandle _TaskProcHandle_t;
|
||||
|
||||
_TaskCollectionImpl(scheduler_ptr _PScheduler)
|
||||
: _M_pScheduler(_PScheduler)
|
||||
{
|
||||
}
|
||||
|
||||
void _ScheduleTask(_TaskProcHandle_t* _PTaskHandle, _TaskInliningMode _InliningMode)
|
||||
{
|
||||
if (_InliningMode == _ForceInline)
|
||||
{
|
||||
_TaskProcHandle_t::_RunChoreBridge(_PTaskHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
_M_pScheduler->schedule(_TaskProcHandle_t::_RunChoreBridge, _PTaskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void _Cancel()
|
||||
{
|
||||
// No cancellation support
|
||||
}
|
||||
|
||||
void _RunAndWait()
|
||||
{
|
||||
// No inlining support yet
|
||||
_Wait();
|
||||
}
|
||||
|
||||
void _Wait()
|
||||
{
|
||||
_M_Completed.wait();
|
||||
}
|
||||
|
||||
void _Complete()
|
||||
{
|
||||
_M_Completed.set();
|
||||
}
|
||||
|
||||
scheduler_ptr _GetScheduler() const
|
||||
{
|
||||
return _M_pScheduler;
|
||||
}
|
||||
|
||||
// Fire and forget
|
||||
static void _RunTask(TaskProc_t _Proc, void * _Parameter, _TaskInliningMode _InliningMode)
|
||||
{
|
||||
if (_InliningMode == _ForceInline)
|
||||
{
|
||||
_Proc(_Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Schedule the work on the ambient scheduler
|
||||
get_ambient_scheduler()->schedule(_Proc, _Parameter);
|
||||
}
|
||||
}
|
||||
|
||||
static bool _pplx_cdecl _Is_cancellation_requested()
|
||||
{
|
||||
// We do not yet have the ability to determine the current task. So return false always
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
|
||||
extensibility::event_t _M_Completed;
|
||||
scheduler_ptr _M_pScheduler;
|
||||
};
|
||||
|
||||
// For create_async lambdas that return a (non-task) result, we oversubscriber the current task for the duration of the
|
||||
// lambda.
|
||||
struct _Task_generator_oversubscriber {};
|
||||
|
||||
typedef _TaskCollectionImpl _TaskCollection_t;
|
||||
typedef _TaskInliningMode _TaskInliningMode_t;
|
||||
typedef _Task_generator_oversubscriber _Task_generator_oversubscriber_t;
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace pplx
|
||||
|
||||
#pragma pack(pop)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // _PPLX_H
|
1092
3rdparty/cpprestsdk/include/pplx/pplxcancellation_token.h
vendored
Normal file
1092
3rdparty/cpprestsdk/include/pplx/pplxcancellation_token.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
84
3rdparty/cpprestsdk/include/pplx/pplxconv.h
vendored
Normal file
84
3rdparty/cpprestsdk/include/pplx/pplxconv.h
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Utilities to convert between PPL tasks and PPLX tasks
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PPLXCONV_H
|
||||
#define _PPLXCONV_H
|
||||
|
||||
#ifndef _WIN32
|
||||
#error This is only supported on Windows
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1700) && (_MSC_VER < 1800) && !CPPREST_FORCE_PPLX
|
||||
|
||||
#include <ppltasks.h>
|
||||
#include "pplx/pplxtasks.h"
|
||||
|
||||
namespace pplx
|
||||
{
|
||||
namespace _Ppl_conv_helpers
|
||||
{
|
||||
template<typename _Tc, typename _F>
|
||||
auto _Set_value(_Tc _Tcp, const _F& _Func) -> decltype(_Tcp.set(_Func())) { return _Tcp.set(_Func()); }
|
||||
|
||||
template<typename _Tc, typename _F>
|
||||
auto _Set_value(_Tc _Tcp, const _F& _Func, ...) -> decltype(_Tcp.set()) { _Func(); return _Tcp.set(); }
|
||||
|
||||
template<typename _TaskType, typename _OtherTaskType, typename _OtherTCEType>
|
||||
_OtherTaskType _Convert_task(_TaskType _Task)
|
||||
{
|
||||
_OtherTCEType _Tc;
|
||||
_Task.then([_Tc](_TaskType _Task2) {
|
||||
try
|
||||
{
|
||||
_Ppl_conv_helpers::_Set_value(_Tc, [=]{ return _Task2.get(); });
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
_Tc.set_exception(std::current_exception());
|
||||
}
|
||||
});
|
||||
_OtherTaskType _T_other(_Tc);
|
||||
return _T_other;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _TaskType>
|
||||
concurrency::task<_TaskType> pplx_task_to_concurrency_task(pplx::task<_TaskType> _Task)
|
||||
{
|
||||
return _Ppl_conv_helpers::_Convert_task<typename pplx::task<_TaskType>, concurrency::task<_TaskType>, concurrency::task_completion_event<_TaskType>>(_Task);
|
||||
}
|
||||
|
||||
template<typename _TaskType>
|
||||
pplx::task<_TaskType> concurrency_task_to_pplx_task(concurrency::task<_TaskType> _Task)
|
||||
{
|
||||
return _Ppl_conv_helpers::_Convert_task<typename concurrency::task<_TaskType>, pplx::task<_TaskType>, pplx::task_completion_event<_TaskType>>(_Task);
|
||||
}
|
||||
} // namespace pplx
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _PPLXCONV_H
|
259
3rdparty/cpprestsdk/include/pplx/pplxinterface.h
vendored
Normal file
259
3rdparty/cpprestsdk/include/pplx/pplxinterface.h
vendored
Normal file
|
@ -0,0 +1,259 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* PPL interfaces
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef _PPLXINTERFACE_H
|
||||
#define _PPLXINTERFACE_H
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) && !CPPREST_FORCE_PPLX
|
||||
#error This file must not be included for Visual Studio 12 or later
|
||||
#endif
|
||||
|
||||
#if defined(_CRTBLD)
|
||||
#elif defined(_WIN32)
|
||||
#if (_MSC_VER >= 1700)
|
||||
#define _USE_REAL_ATOMICS
|
||||
#endif
|
||||
#else // GCC compiler
|
||||
#define _USE_REAL_ATOMICS
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#ifdef _USE_REAL_ATOMICS
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
// This prevents users from requiring -Wno-attributes when using gcc-4.8 with the android NDK.
|
||||
#define _pplx_cdecl
|
||||
#else
|
||||
#define _pplx_cdecl __cdecl
|
||||
#endif
|
||||
|
||||
namespace pplx
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An elementary abstraction for a task, defined as <c>void (__cdecl * TaskProc_t)(void *)</c>. A <c>TaskProc</c> is called to
|
||||
/// invoke the body of a task.
|
||||
/// </summary>
|
||||
/**/
|
||||
typedef void (_pplx_cdecl * TaskProc_t)(void *);
|
||||
|
||||
/// <summary>
|
||||
/// Scheduler Interface
|
||||
/// </summary>
|
||||
struct __declspec(novtable) scheduler_interface
|
||||
{
|
||||
virtual void schedule( TaskProc_t, _In_ void* ) = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a pointer to a scheduler. This class exists to allow the
|
||||
/// the specification of a shared lifetime by using shared_ptr or just
|
||||
/// a plain reference by using raw pointer.
|
||||
/// </summary>
|
||||
struct scheduler_ptr
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a scheduler pointer from shared_ptr to scheduler
|
||||
/// </summary>
|
||||
explicit scheduler_ptr(std::shared_ptr<scheduler_interface> scheduler) : m_sharedScheduler(std::move(scheduler))
|
||||
{
|
||||
m_scheduler = m_sharedScheduler.get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a scheduler pointer from raw pointer to scheduler
|
||||
/// </summary>
|
||||
explicit scheduler_ptr(_In_opt_ scheduler_interface * pScheduler) : m_scheduler(pScheduler)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Behave like a pointer
|
||||
/// </summary>
|
||||
scheduler_interface *operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the raw pointer to the scheduler
|
||||
/// </summary>
|
||||
scheduler_interface * get() const
|
||||
{
|
||||
return m_scheduler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the scheduler pointer is non-null
|
||||
/// </summary>
|
||||
operator bool() const { return get() != nullptr; }
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<scheduler_interface> m_sharedScheduler;
|
||||
scheduler_interface * m_scheduler;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Describes the execution status of a <c>task_group</c> or <c>structured_task_group</c> object. A value of this type is returned
|
||||
/// by numerous methods that wait on tasks scheduled to a task group to complete.
|
||||
/// </summary>
|
||||
/// <seealso cref="task_group Class"/>
|
||||
/// <seealso cref="task_group::wait Method"/>
|
||||
/// <seealso cref="task_group::run_and_wait Method"/>
|
||||
/// <seealso cref="structured_task_group Class"/>
|
||||
/// <seealso cref="structured_task_group::wait Method"/>
|
||||
/// <seealso cref="structured_task_group::run_and_wait Method"/>
|
||||
/**/
|
||||
enum task_group_status
|
||||
{
|
||||
/// <summary>
|
||||
/// The tasks queued to the <c>task_group</c> object have not completed. Note that this value is not presently returned by
|
||||
/// the Concurrency Runtime.
|
||||
/// </summary>
|
||||
/**/
|
||||
not_complete,
|
||||
|
||||
/// <summary>
|
||||
/// The tasks queued to the <c>task_group</c> or <c>structured_task_group</c> object completed successfully.
|
||||
/// </summary>
|
||||
/**/
|
||||
completed,
|
||||
|
||||
/// <summary>
|
||||
/// The <c>task_group</c> or <c>structured_task_group</c> object was canceled. One or more tasks may not have executed.
|
||||
/// </summary>
|
||||
/**/
|
||||
canceled
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Atomics
|
||||
/// </summary>
|
||||
#ifdef _USE_REAL_ATOMICS
|
||||
typedef std::atomic<long> atomic_long;
|
||||
typedef std::atomic<size_t> atomic_size_t;
|
||||
|
||||
template<typename _T>
|
||||
_T atomic_compare_exchange(std::atomic<_T>& _Target, _T _Exchange, _T _Comparand)
|
||||
{
|
||||
_T _Result = _Comparand;
|
||||
_Target.compare_exchange_strong(_Result, _Exchange);
|
||||
return _Result;
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
_T atomic_exchange(std::atomic<_T>& _Target, _T _Value)
|
||||
{
|
||||
return _Target.exchange(_Value);
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
_T atomic_increment(std::atomic<_T>& _Target)
|
||||
{
|
||||
return _Target.fetch_add(1) + 1;
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
_T atomic_decrement(std::atomic<_T>& _Target)
|
||||
{
|
||||
return _Target.fetch_sub(1) - 1;
|
||||
}
|
||||
|
||||
template<typename _T>
|
||||
_T atomic_add(std::atomic<_T>& _Target, _T value)
|
||||
{
|
||||
return _Target.fetch_add(value) + value;
|
||||
}
|
||||
|
||||
#else // not _USE_REAL_ATOMICS
|
||||
|
||||
typedef long volatile atomic_long;
|
||||
typedef size_t volatile atomic_size_t;
|
||||
|
||||
template<class T>
|
||||
inline T atomic_exchange(T volatile& _Target, T _Value)
|
||||
{
|
||||
return _InterlockedExchange(&_Target, _Value);
|
||||
}
|
||||
|
||||
inline long atomic_increment(long volatile & _Target)
|
||||
{
|
||||
return _InterlockedIncrement(&_Target);
|
||||
}
|
||||
|
||||
inline long atomic_add(long volatile & _Target, long value)
|
||||
{
|
||||
return _InterlockedExchangeAdd(&_Target, value) + value;
|
||||
}
|
||||
|
||||
inline size_t atomic_increment(size_t volatile & _Target)
|
||||
{
|
||||
#if (defined(_M_IX86) || defined(_M_ARM))
|
||||
return static_cast<size_t>(_InterlockedIncrement(reinterpret_cast<long volatile *>(&_Target)));
|
||||
#else
|
||||
return static_cast<size_t>(_InterlockedIncrement64(reinterpret_cast<__int64 volatile *>(&_Target)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline long atomic_decrement(long volatile & _Target)
|
||||
{
|
||||
return _InterlockedDecrement(&_Target);
|
||||
}
|
||||
|
||||
inline size_t atomic_decrement(size_t volatile & _Target)
|
||||
{
|
||||
#if (defined(_M_IX86) || defined(_M_ARM))
|
||||
return static_cast<size_t>(_InterlockedDecrement(reinterpret_cast<long volatile *>(&_Target)));
|
||||
#else
|
||||
return static_cast<size_t>(_InterlockedDecrement64(reinterpret_cast<__int64 volatile *>(&_Target)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline long atomic_compare_exchange(long volatile & _Target, long _Exchange, long _Comparand)
|
||||
{
|
||||
return _InterlockedCompareExchange(&_Target, _Exchange, _Comparand);
|
||||
}
|
||||
|
||||
inline size_t atomic_compare_exchange(size_t volatile & _Target, size_t _Exchange, size_t _Comparand)
|
||||
{
|
||||
#if (defined(_M_IX86) || defined(_M_ARM))
|
||||
return static_cast<size_t>(_InterlockedCompareExchange(reinterpret_cast<long volatile *>(_Target), static_cast<long>(_Exchange), static_cast<long>(_Comparand)));
|
||||
#else
|
||||
return static_cast<size_t>(_InterlockedCompareExchange64(reinterpret_cast<__int64 volatile *>(_Target), static_cast<__int64>(_Exchange), static_cast<__int64>(_Comparand)));
|
||||
#endif
|
||||
}
|
||||
#endif // _USE_REAL_ATOMICS
|
||||
|
||||
}} // namespace pplx
|
||||
|
||||
#endif // _PPLXINTERFACE_H
|
329
3rdparty/cpprestsdk/include/pplx/pplxlinux.h
vendored
Normal file
329
3rdparty/cpprestsdk/include/pplx/pplxlinux.h
vendored
Normal file
|
@ -0,0 +1,329 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Linux specific pplx implementations
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#if (defined(_MSC_VER))
|
||||
#error This file must not be included for Visual Studio
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <signal.h>
|
||||
#include "pthread.h"
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#else
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#endif
|
||||
|
||||
#include "pplx/pplxinterface.h"
|
||||
|
||||
|
||||
namespace pplx
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
namespace cpprest_synchronization = ::boost;
|
||||
#else
|
||||
namespace cpprest_synchronization = ::std;
|
||||
#endif
|
||||
namespace details
|
||||
{
|
||||
namespace platform
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a unique identifier for the execution thread where this routine in invoked
|
||||
/// </summary>
|
||||
_PPLXIMP long _pplx_cdecl GetCurrentThreadId();
|
||||
|
||||
/// <summary>
|
||||
/// Yields the execution of the current execution thread - typically when spin-waiting
|
||||
/// </summary>
|
||||
_PPLXIMP void _pplx_cdecl YieldExecution();
|
||||
|
||||
/// <summary>
|
||||
/// Caputeres the callstack
|
||||
/// </summary>
|
||||
__declspec(noinline) inline static size_t CaptureCallstack(void **, size_t, size_t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manual reset event
|
||||
/// </summary>
|
||||
class event_impl
|
||||
{
|
||||
private:
|
||||
cpprest_synchronization::mutex _lock;
|
||||
cpprest_synchronization::condition_variable _condition;
|
||||
bool _signaled;
|
||||
public:
|
||||
|
||||
static const unsigned int timeout_infinite = 0xFFFFFFFF;
|
||||
|
||||
event_impl()
|
||||
: _signaled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
cpprest_synchronization::lock_guard<cpprest_synchronization::mutex> lock(_lock);
|
||||
_signaled = true;
|
||||
_condition.notify_all();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
cpprest_synchronization::lock_guard<cpprest_synchronization::mutex> lock(_lock);
|
||||
_signaled = false;
|
||||
}
|
||||
|
||||
unsigned int wait(unsigned int timeout)
|
||||
{
|
||||
cpprest_synchronization::unique_lock<cpprest_synchronization::mutex> lock(_lock);
|
||||
if (timeout == event_impl::timeout_infinite)
|
||||
{
|
||||
_condition.wait(lock, [this]() -> bool { return _signaled; });
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpprest_synchronization::chrono::milliseconds period(timeout);
|
||||
auto status = _condition.wait_for(lock, period, [this]() -> bool { return _signaled; });
|
||||
_ASSERTE(status == _signaled);
|
||||
// Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite
|
||||
// Note: this must be consistent with the behavior of the Windows version, which is based on WaitForSingleObjectEx
|
||||
return status ? 0: event_impl::timeout_infinite;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int wait()
|
||||
{
|
||||
return wait(event_impl::timeout_infinite);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Reader writer lock
|
||||
/// </summary>
|
||||
class reader_writer_lock_impl
|
||||
{
|
||||
private:
|
||||
|
||||
pthread_rwlock_t _M_reader_writer_lock;
|
||||
|
||||
public:
|
||||
|
||||
class scoped_lock_read
|
||||
{
|
||||
public:
|
||||
explicit scoped_lock_read(reader_writer_lock_impl &_Reader_writer_lock) : _M_reader_writer_lock(_Reader_writer_lock)
|
||||
{
|
||||
_M_reader_writer_lock.lock_read();
|
||||
}
|
||||
|
||||
~scoped_lock_read()
|
||||
{
|
||||
_M_reader_writer_lock.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
reader_writer_lock_impl& _M_reader_writer_lock;
|
||||
scoped_lock_read(const scoped_lock_read&); // no copy constructor
|
||||
scoped_lock_read const & operator=(const scoped_lock_read&); // no assignment operator
|
||||
};
|
||||
|
||||
reader_writer_lock_impl()
|
||||
{
|
||||
pthread_rwlock_init(&_M_reader_writer_lock, nullptr);
|
||||
}
|
||||
|
||||
~reader_writer_lock_impl()
|
||||
{
|
||||
pthread_rwlock_destroy(&_M_reader_writer_lock);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
pthread_rwlock_wrlock(&_M_reader_writer_lock);
|
||||
}
|
||||
|
||||
void lock_read()
|
||||
{
|
||||
pthread_rwlock_rdlock(&_M_reader_writer_lock);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
pthread_rwlock_unlock(&_M_reader_writer_lock);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Recursive mutex
|
||||
/// </summary>
|
||||
class recursive_lock_impl
|
||||
{
|
||||
public:
|
||||
|
||||
recursive_lock_impl()
|
||||
: _M_owner(-1), _M_recursionCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
~recursive_lock_impl()
|
||||
{
|
||||
_ASSERTE(_M_owner == -1);
|
||||
_ASSERTE(_M_recursionCount == 0);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
auto id = ::pplx::details::platform::GetCurrentThreadId();
|
||||
|
||||
if ( _M_owner == id )
|
||||
{
|
||||
_M_recursionCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_M_cs.lock();
|
||||
_M_owner = id;
|
||||
_M_recursionCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
_ASSERTE(_M_owner == ::pplx::details::platform::GetCurrentThreadId());
|
||||
_ASSERTE(_M_recursionCount >= 1);
|
||||
|
||||
_M_recursionCount--;
|
||||
|
||||
if ( _M_recursionCount == 0 )
|
||||
{
|
||||
_M_owner = -1;
|
||||
_M_cs.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
cpprest_synchronization::mutex _M_cs;
|
||||
volatile long _M_owner;
|
||||
long _M_recursionCount;
|
||||
};
|
||||
|
||||
#if defined(__APPLE__)
|
||||
class apple_scheduler : public pplx::scheduler_interface
|
||||
#else
|
||||
class linux_scheduler : public pplx::scheduler_interface
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
_PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param);
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A generic RAII wrapper for locks that implements the critical_section interface
|
||||
/// cpprest_synchronization::lock_guard
|
||||
/// </summary>
|
||||
template<class _Lock>
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
explicit scoped_lock(_Lock& _Critical_section) : _M_critical_section(_Critical_section)
|
||||
{
|
||||
_M_critical_section.lock();
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
_M_critical_section.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
_Lock& _M_critical_section;
|
||||
|
||||
scoped_lock(const scoped_lock&); // no copy constructor
|
||||
scoped_lock const & operator=(const scoped_lock&); // no assignment operator
|
||||
};
|
||||
|
||||
// The extensibility namespace contains the type definitions that are used internally
|
||||
namespace extensibility
|
||||
{
|
||||
typedef ::pplx::details::event_impl event_t;
|
||||
|
||||
typedef cpprest_synchronization::mutex critical_section_t;
|
||||
typedef scoped_lock<critical_section_t> scoped_critical_section_t;
|
||||
|
||||
typedef ::pplx::details::reader_writer_lock_impl reader_writer_lock_t;
|
||||
typedef scoped_lock<reader_writer_lock_t> scoped_rw_lock_t;
|
||||
typedef ::pplx::extensibility::reader_writer_lock_t::scoped_lock_read scoped_read_lock_t;
|
||||
|
||||
typedef ::pplx::details::recursive_lock_impl recursive_lock_t;
|
||||
typedef scoped_lock<recursive_lock_t> scoped_recursive_lock_t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default scheduler type
|
||||
/// </summary>
|
||||
#if defined(__APPLE__)
|
||||
typedef details::apple_scheduler default_scheduler_t;
|
||||
#else
|
||||
typedef details::linux_scheduler default_scheduler_t;
|
||||
#endif
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Terminate the process due to unhandled exception
|
||||
/// </summary>
|
||||
#ifndef _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
|
||||
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() do { \
|
||||
raise(SIGTRAP); \
|
||||
std::terminate(); \
|
||||
} while(false)
|
||||
#endif //_REPORT_PPLTASK_UNOBSERVED_EXCEPTION
|
||||
}
|
||||
|
||||
//see: http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
|
||||
// this is critical to inline
|
||||
__attribute__ ((always_inline))
|
||||
inline void* _ReturnAddress() { return __builtin_return_address(0); }
|
||||
|
||||
} // namespace pplx
|
||||
|
||||
#endif // !_WIN32
|
7362
3rdparty/cpprestsdk/include/pplx/pplxtasks.h
vendored
Normal file
7362
3rdparty/cpprestsdk/include/pplx/pplxtasks.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
297
3rdparty/cpprestsdk/include/pplx/pplxwin.h
vendored
Normal file
297
3rdparty/cpprestsdk/include/pplx/pplxwin.h
vendored
Normal file
|
@ -0,0 +1,297 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Windows specific pplx implementations
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(_WIN32) || _MSC_VER < 1800 || CPPREST_FORCE_PPLX
|
||||
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
#include "pplx/pplxinterface.h"
|
||||
|
||||
namespace pplx
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
namespace platform
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a unique identifier for the execution thread where this routine in invoked
|
||||
/// </summary>
|
||||
_PPLXIMP long __cdecl GetCurrentThreadId();
|
||||
|
||||
/// <summary>
|
||||
/// Yields the execution of the current execution thread - typically when spin-waiting
|
||||
/// </summary>
|
||||
_PPLXIMP void __cdecl YieldExecution();
|
||||
|
||||
/// <summary>
|
||||
/// Captures the callstack
|
||||
/// </summary>
|
||||
__declspec(noinline) _PPLXIMP size_t __cdecl CaptureCallstack(void **, size_t, size_t);
|
||||
|
||||
#if defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
// Internal API which retrieves the next async id.
|
||||
/// </summary>
|
||||
_PPLXIMP unsigned int __cdecl GetNextAsyncId();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manual reset event
|
||||
/// </summary>
|
||||
class event_impl
|
||||
{
|
||||
public:
|
||||
|
||||
static const unsigned int timeout_infinite = 0xFFFFFFFF;
|
||||
|
||||
_PPLXIMP event_impl();
|
||||
|
||||
_PPLXIMP ~event_impl();
|
||||
|
||||
_PPLXIMP void set();
|
||||
|
||||
_PPLXIMP void reset();
|
||||
|
||||
_PPLXIMP unsigned int wait(unsigned int timeout);
|
||||
|
||||
unsigned int wait()
|
||||
{
|
||||
return wait(event_impl::timeout_infinite);
|
||||
}
|
||||
|
||||
private:
|
||||
// Windows events
|
||||
void * _M_impl;
|
||||
|
||||
event_impl(const event_impl&); // no copy constructor
|
||||
event_impl const & operator=(const event_impl&); // no assignment operator
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Mutex - lock for mutual exclusion
|
||||
/// </summary>
|
||||
class critical_section_impl
|
||||
{
|
||||
public:
|
||||
|
||||
_PPLXIMP critical_section_impl();
|
||||
|
||||
_PPLXIMP ~critical_section_impl();
|
||||
|
||||
_PPLXIMP void lock();
|
||||
|
||||
_PPLXIMP void unlock();
|
||||
|
||||
private:
|
||||
|
||||
typedef void * _PPLX_BUFFER;
|
||||
|
||||
// Windows critical section
|
||||
_PPLX_BUFFER _M_impl[8];
|
||||
|
||||
critical_section_impl(const critical_section_impl&); // no copy constructor
|
||||
critical_section_impl const & operator=(const critical_section_impl&); // no assignment operator
|
||||
};
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/// <summary>
|
||||
/// Reader writer lock
|
||||
/// </summary>
|
||||
class reader_writer_lock_impl
|
||||
{
|
||||
public:
|
||||
|
||||
class scoped_lock_read
|
||||
{
|
||||
public:
|
||||
explicit scoped_lock_read(reader_writer_lock_impl &_Reader_writer_lock) : _M_reader_writer_lock(_Reader_writer_lock)
|
||||
{
|
||||
_M_reader_writer_lock.lock_read();
|
||||
}
|
||||
|
||||
~scoped_lock_read()
|
||||
{
|
||||
_M_reader_writer_lock.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
reader_writer_lock_impl& _M_reader_writer_lock;
|
||||
scoped_lock_read(const scoped_lock_read&); // no copy constructor
|
||||
scoped_lock_read const & operator=(const scoped_lock_read&); // no assignment operator
|
||||
};
|
||||
|
||||
_PPLXIMP reader_writer_lock_impl();
|
||||
|
||||
_PPLXIMP void lock();
|
||||
|
||||
_PPLXIMP void lock_read();
|
||||
|
||||
_PPLXIMP void unlock();
|
||||
|
||||
private:
|
||||
|
||||
// Windows slim reader writer lock
|
||||
void * _M_impl;
|
||||
|
||||
// Slim reader writer lock doesn't have a general 'unlock' method.
|
||||
// We need to track how it was acquired and release accordingly.
|
||||
// true - lock exclusive
|
||||
// false - lock shared
|
||||
bool m_locked_exclusive;
|
||||
};
|
||||
#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
|
||||
/// <summary>
|
||||
/// Recursive mutex
|
||||
/// </summary>
|
||||
class recursive_lock_impl
|
||||
{
|
||||
public:
|
||||
|
||||
recursive_lock_impl()
|
||||
: _M_owner(-1), _M_recursionCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
~recursive_lock_impl()
|
||||
{
|
||||
_ASSERTE(_M_owner == -1);
|
||||
_ASSERTE(_M_recursionCount == 0);
|
||||
}
|
||||
|
||||
void recursive_lock_impl::lock()
|
||||
{
|
||||
auto id = ::pplx::details::platform::GetCurrentThreadId();
|
||||
|
||||
if ( _M_owner == id )
|
||||
{
|
||||
_M_recursionCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_M_cs.lock();
|
||||
_M_owner = id;
|
||||
_M_recursionCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void recursive_lock_impl::unlock()
|
||||
{
|
||||
_ASSERTE(_M_owner == ::pplx::details::platform::GetCurrentThreadId());
|
||||
_ASSERTE(_M_recursionCount >= 1);
|
||||
|
||||
_M_recursionCount--;
|
||||
|
||||
if ( _M_recursionCount == 0 )
|
||||
{
|
||||
_M_owner = -1;
|
||||
_M_cs.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pplx::details::critical_section_impl _M_cs;
|
||||
long _M_recursionCount;
|
||||
volatile long _M_owner;
|
||||
};
|
||||
|
||||
class windows_scheduler : public pplx::scheduler_interface
|
||||
{
|
||||
public:
|
||||
_PPLXIMP virtual void schedule( TaskProc_t proc, _In_ void* param);
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
|
||||
/// <summary>
|
||||
/// A generic RAII wrapper for locks that implement the critical_section interface
|
||||
/// std::lock_guard
|
||||
/// </summary>
|
||||
template<class _Lock>
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
explicit scoped_lock(_Lock& _Critical_section) : _M_critical_section(_Critical_section)
|
||||
{
|
||||
_M_critical_section.lock();
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
_M_critical_section.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
_Lock& _M_critical_section;
|
||||
|
||||
scoped_lock(const scoped_lock&); // no copy constructor
|
||||
scoped_lock const & operator=(const scoped_lock&); // no assignment operator
|
||||
};
|
||||
|
||||
// The extensibility namespace contains the type definitions that are used internally
|
||||
namespace extensibility
|
||||
{
|
||||
typedef ::pplx::details::event_impl event_t;
|
||||
|
||||
typedef ::pplx::details::critical_section_impl critical_section_t;
|
||||
typedef scoped_lock<critical_section_t> scoped_critical_section_t;
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
typedef ::pplx::details::reader_writer_lock_impl reader_writer_lock_t;
|
||||
typedef scoped_lock<reader_writer_lock_t> scoped_rw_lock_t;
|
||||
typedef reader_writer_lock_t::scoped_lock_read scoped_read_lock_t;
|
||||
#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
|
||||
|
||||
typedef ::pplx::details::recursive_lock_impl recursive_lock_t;
|
||||
typedef scoped_lock<recursive_lock_t> scoped_recursive_lock_t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default scheduler type
|
||||
/// </summary>
|
||||
typedef details::windows_scheduler default_scheduler_t;
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Terminate the process due to unhandled exception
|
||||
/// </summary>
|
||||
|
||||
#ifndef _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
|
||||
#define _REPORT_PPLTASK_UNOBSERVED_EXCEPTION() do { \
|
||||
__debugbreak(); \
|
||||
std::terminate(); \
|
||||
} while(false)
|
||||
#endif // _REPORT_PPLTASK_UNOBSERVED_EXCEPTION
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace pplx
|
||||
|
||||
#endif
|
161
3rdparty/cpprestsdk/include/pplx/threadpool.h
vendored
Normal file
161
3rdparty/cpprestsdk/include/pplx/threadpool.h
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
/***
|
||||
* ==++==
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ==--==
|
||||
*
|
||||
* Simple Linux implementation of a static thread pool.
|
||||
*
|
||||
* For the latest on this and related APIs, please see http://casablanca.codeplex.com.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#pragma clang diagnostic ignored "-Wunreachable-code"
|
||||
#endif
|
||||
#include "boost/asio.hpp"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
#include <atomic>
|
||||
#include <jni.h>
|
||||
#include "pplx/pplx.h"
|
||||
#endif
|
||||
|
||||
namespace crossplat {
|
||||
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
// IDEA: Break this section into a separate android/jni header
|
||||
extern std::atomic<JavaVM*> JVM;
|
||||
JNIEnv* get_jvm_env();
|
||||
|
||||
struct java_local_ref_deleter
|
||||
{
|
||||
void operator()(jobject lref) const
|
||||
{
|
||||
crossplat::get_jvm_env()->DeleteLocalRef(lref);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using java_local_ref = std::unique_ptr<typename std::remove_pointer<T>::type, java_local_ref_deleter>;
|
||||
#endif
|
||||
|
||||
class threadpool
|
||||
{
|
||||
public:
|
||||
|
||||
threadpool(size_t n)
|
||||
: m_service(n),
|
||||
m_work(m_service)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
add_thread();
|
||||
}
|
||||
|
||||
static threadpool& shared_instance();
|
||||
|
||||
~threadpool()
|
||||
{
|
||||
m_service.stop();
|
||||
for (auto iter = m_threads.begin(); iter != m_threads.end(); ++iter)
|
||||
{
|
||||
pthread_t t = *iter;
|
||||
void* res;
|
||||
pthread_join(t, &res);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void schedule(T task)
|
||||
{
|
||||
m_service.post(task);
|
||||
}
|
||||
|
||||
boost::asio::io_service& service()
|
||||
{
|
||||
return m_service;
|
||||
}
|
||||
|
||||
private:
|
||||
struct _cancel_thread { };
|
||||
|
||||
void add_thread()
|
||||
{
|
||||
pthread_t t;
|
||||
auto result = pthread_create(&t, nullptr, &thread_start, this);
|
||||
if (result == 0)
|
||||
m_threads.push_back(t);
|
||||
}
|
||||
|
||||
void remove_thread()
|
||||
{
|
||||
schedule([]() -> void { throw _cancel_thread(); });
|
||||
}
|
||||
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
static void detach_from_java(void*)
|
||||
{
|
||||
JVM.load()->DetachCurrentThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* thread_start(void *arg)
|
||||
{
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
// Calling get_jvm_env() here forces the thread to be attached.
|
||||
get_jvm_env();
|
||||
pthread_cleanup_push(detach_from_java, nullptr);
|
||||
#endif
|
||||
threadpool* _this = reinterpret_cast<threadpool*>(arg);
|
||||
try
|
||||
{
|
||||
_this->m_service.run();
|
||||
}
|
||||
catch (const _cancel_thread&)
|
||||
{
|
||||
// thread was cancelled
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Something bad happened
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
// Reach into the depths of the 'droid!
|
||||
// NOTE: Uses internals of the bionic library
|
||||
// Written against android ndk r9d, 7/26/2014
|
||||
__pthread_cleanup_pop(&__cleanup, true);
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
#if (defined(ANDROID) || defined(__ANDROID__))
|
||||
pthread_cleanup_pop(true);
|
||||
#endif
|
||||
return arg;
|
||||
}
|
||||
|
||||
std::vector<pthread_t> m_threads;
|
||||
boost::asio::io_service m_service;
|
||||
boost::asio::io_service::work m_work;
|
||||
};
|
||||
|
||||
}
|
18
3rdparty/cpprestsdk/libs/websocketpp/.gitattributes
vendored
Normal file
18
3rdparty/cpprestsdk/libs/websocketpp/.gitattributes
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Lineendings
|
||||
*.sln eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
*.vcxproj* eol=crlf
|
||||
|
||||
# Whitespace rules
|
||||
# strict (no trailing, no tabs)
|
||||
*.cpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
|
||||
*.hpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
|
||||
*.c whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
|
||||
*.h whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol
|
||||
|
||||
# normal (no trailing)
|
||||
*.sql whitespace=trailing-space,space-before-tab,cr-at-eol
|
||||
*.txt whitespace=trailing-space,space-before-tab,cr-at-eol
|
||||
|
||||
# special files which must ignore whitespace
|
||||
*.patch whitespace=-trailing-space
|
90
3rdparty/cpprestsdk/libs/websocketpp/.gitignore
vendored
Normal file
90
3rdparty/cpprestsdk/libs/websocketpp/.gitignore
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
# make .git* files visible to git
|
||||
!.gitignore
|
||||
!.gitattributes
|
||||
|
||||
.DS_Store
|
||||
|
||||
#vim stuff
|
||||
*~
|
||||
*.swp
|
||||
|
||||
*.o
|
||||
*.so
|
||||
*.so.?
|
||||
*.so.?.?.?
|
||||
*.a
|
||||
*.dylib
|
||||
lib/*
|
||||
|
||||
# CMake
|
||||
*.cmake
|
||||
*.dir
|
||||
CMakeFiles
|
||||
INSTALL.*
|
||||
ZERO_CHECK.*
|
||||
CMakeCache.txt
|
||||
install_manifest.txt
|
||||
|
||||
# Windows/Visual Studio
|
||||
*.vcproj*
|
||||
*.sln
|
||||
*.suo
|
||||
*.ncb
|
||||
*/Debug/*
|
||||
*/*/Debug/*
|
||||
bin/Debug
|
||||
*/Release/*
|
||||
*/*/Release/*
|
||||
*/RelWithDebInfo/*
|
||||
*/*/RelWithDebInfo/*
|
||||
|
||||
# explicitly allow this path with /debug/ in it
|
||||
!websocketpp/transport/debug/*
|
||||
|
||||
objs_shared/
|
||||
objs_static/
|
||||
|
||||
examples/chat_server/chat_server
|
||||
examples/echo_server/echo_server
|
||||
examples/chat_client/chat_client
|
||||
examples/echo_client/echo_client
|
||||
test/basic/tests
|
||||
libwebsocketpp.dylib.0.1.0
|
||||
|
||||
websocketpp.xcodeproj/xcuserdata/*
|
||||
websocketpp.xcodeproj/project.xcworkspace/xcuserdata/*
|
||||
policy_based_notes.hpp
|
||||
|
||||
examples/echo_server_tls/echo_server_tls
|
||||
|
||||
examples/fuzzing_client/fuzzing_client
|
||||
|
||||
examples/stress_client/stress_client
|
||||
|
||||
examples/broadcast_server_tls/broadcast_server
|
||||
|
||||
test/basic/perf
|
||||
|
||||
examples/echo_server_tls/echo_server_tls
|
||||
|
||||
examples/concurrent_server/concurrent_server
|
||||
|
||||
examples/fuzzing_server_tls/fuzzing_server
|
||||
|
||||
examples/wsperf/wsperf
|
||||
|
||||
.sconsign.dblite
|
||||
|
||||
build/
|
||||
doxygen/
|
||||
examples/wsperf/wsperf_client
|
||||
|
||||
*.out
|
||||
|
||||
*.log
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.user
|
||||
install
|
23
3rdparty/cpprestsdk/libs/websocketpp/.travis.yml
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/.travis.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
before_install:
|
||||
- sudo apt-get install libboost-regex1.48-dev libboost-system1.48-dev libboost-thread1.48-dev libboost-test1.48-dev libboost-random1.48-dev -y
|
||||
env:
|
||||
global:
|
||||
- BOOST_INCLUDES=/usr/include
|
||||
- BOOST_LIBS=/usr/lib
|
||||
script: scons -j 2 && scons test
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- permessage-deflate
|
||||
- experimental
|
||||
- 0.3.x-cmake
|
||||
- develop
|
||||
notifications:
|
||||
recipients:
|
||||
- travis@zaphoyd.com
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
244
3rdparty/cpprestsdk/libs/websocketpp/CMakeLists.txt
vendored
Normal file
244
3rdparty/cpprestsdk/libs/websocketpp/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,244 @@
|
|||
|
||||
############ Setup project and cmake
|
||||
|
||||
# Project name
|
||||
project (websocketpp)
|
||||
|
||||
# Minimum cmake requirement. We should require a quite recent
|
||||
# cmake for the dependency find macros etc. to be up to date.
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
set (WEBSOCKETPP_MAJOR_VERSION 0)
|
||||
set (WEBSOCKETPP_MINOR_VERSION 5)
|
||||
set (WEBSOCKETPP_PATCH_VERSION 1)
|
||||
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})
|
||||
|
||||
set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
set (DEF_INSTALL_CMAKE_DIR cmake)
|
||||
else ()
|
||||
set (DEF_INSTALL_CMAKE_DIR lib/cmake/websocketpp)
|
||||
endif ()
|
||||
set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
|
||||
|
||||
# Make relative paths absolute (needed later on)
|
||||
foreach (p INCLUDE CMAKE)
|
||||
set (var INSTALL_${p}_DIR)
|
||||
if (NOT IS_ABSOLUTE "${${var}}")
|
||||
set (${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
# Set CMake library search policy
|
||||
if (COMMAND cmake_policy)
|
||||
cmake_policy (SET CMP0003 NEW)
|
||||
cmake_policy (SET CMP0005 NEW)
|
||||
endif ()
|
||||
|
||||
# Disable unnecessary build types
|
||||
set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "Configurations" FORCE)
|
||||
|
||||
# Include our cmake macros
|
||||
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
include (CMakeHelpers)
|
||||
|
||||
############ Paths
|
||||
|
||||
set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp)
|
||||
set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin)
|
||||
set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib)
|
||||
|
||||
# CMake install step prefix. I assume linux users want the prefix to
|
||||
# be the default /usr or /usr/local so this is only adjusted on Windows.
|
||||
# - Windows: Build the INSTALL project in your solution file.
|
||||
# - Linux/OSX: make install.
|
||||
if (MSVC)
|
||||
set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install")
|
||||
endif ()
|
||||
|
||||
############ Build customization
|
||||
|
||||
# Override from command line "CMake -D<OPTION>=TRUE/FALSE/0/1/ON/OFF"
|
||||
option (ENABLE_CPP11 "Build websocketpp with CPP11 features enabled." TRUE)
|
||||
option (BUILD_EXAMPLES "Build websocketpp examples." FALSE)
|
||||
option (BUILD_TESTS "Build websocketpp tests." FALSE)
|
||||
|
||||
if (BUILD_TESTS OR BUILD_EXAMPLES)
|
||||
|
||||
############ Compiler specific setup
|
||||
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS "")
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS "")
|
||||
set (WEBSOCKETPP_BOOST_LIBS "")
|
||||
|
||||
# VC9 and C++11 reasoning
|
||||
if (ENABLE_CPP11 AND MSVC AND MSVC90)
|
||||
message("* Detected Visual Studio 9 2008, disabling C++11 support.")
|
||||
set (ENABLE_CPP11 FALSE)
|
||||
endif ()
|
||||
|
||||
# Detect clang. Not officially reported by cmake.
|
||||
execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-v" ERROR_VARIABLE CXX_VER_STDERR)
|
||||
if ("${CXX_VER_STDERR}" MATCHES ".*clang.*")
|
||||
set (CMAKE_COMPILER_IS_CLANGXX 1)
|
||||
endif ()
|
||||
|
||||
# C++11 defines
|
||||
if (ENABLE_CPP11)
|
||||
if (MSVC)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_FUNCTIONAL_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_SYSTEM_ERROR_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_RANDOM_DEVICE_)
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_MEMORY_)
|
||||
else()
|
||||
add_definitions (-D_WEBSOCKETPP_CPP11_STL_)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
# Visual studio
|
||||
if (MSVC)
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL /Gy /GF /Ox /Ob2 /Ot /Oi /MP /arch:SSE2 /fp:fast")
|
||||
set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /INCREMENTAL:NO /OPT:REF /OPT:ICF")
|
||||
add_definitions (/W3 /wd4996 /wd4995 /wd4355)
|
||||
add_definitions (-DUNICODE -D_UNICODE)
|
||||
add_definitions (-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
|
||||
add_definitions (-DNOMINMAX)
|
||||
endif ()
|
||||
|
||||
# g++
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
if (NOT APPLE)
|
||||
add_definitions (-DNDEBUG -Wall -Wcast-align) # todo: should we use CMAKE_C_FLAGS for these?
|
||||
endif ()
|
||||
|
||||
# Try to detect version. Note: Not tested!
|
||||
execute_process (COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" OUTPUT_VARIABLE GCC_VERSION)
|
||||
if ("${GCC_VERSION}" STRGREATER "4.4.0")
|
||||
message("* C++11 support partially enabled due to GCC version ${GCC_VERSION}")
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# clang
|
||||
if (CMAKE_COMPILER_IS_CLANGXX)
|
||||
if (NOT APPLE)
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
|
||||
else()
|
||||
set (WEBSOCKETPP_PLATFORM_LIBS pthread)
|
||||
endif()
|
||||
set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto)
|
||||
set (WEBSOCKETPP_BOOST_LIBS system thread)
|
||||
set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x -stdlib=libc++") # todo: is libc++ really needed here?
|
||||
if (NOT APPLE)
|
||||
add_definitions (-DNDEBUG -Wall -Wno-padded) # todo: should we use CMAKE_C_FLAGS for these?
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# OSX, can override above.
|
||||
if (APPLE)
|
||||
add_definitions (-DNDEBUG -Wall)
|
||||
endif ()
|
||||
|
||||
if (BUILD_EXAMPLES)
|
||||
list (APPEND WEBSOCKETPP_BOOST_LIBS random)
|
||||
endif()
|
||||
|
||||
############ Dependencies
|
||||
|
||||
# Set BOOST_ROOT env variable or pass with cmake -DBOOST_ROOT=path.
|
||||
# BOOST_ROOT can also be defined by a previous run from cmake cache.
|
||||
if (NOT "$ENV{BOOST_ROOT_CPP11}" STREQUAL "")
|
||||
# Scons documentation for BOOST_ROOT_CPP11:
|
||||
# "look for optional second boostroot compiled with clang's libc++ STL library
|
||||
# this prevents warnings/errors when linking code built with two different
|
||||
# incompatible STL libraries."
|
||||
file (TO_CMAKE_PATH "$ENV{BOOST_ROOT_CPP11}" BOOST_ROOT)
|
||||
set (BOOST_ROOT ${BOOST_ROOT} CACHE PATH "BOOST_ROOT dependency path" FORCE)
|
||||
endif ()
|
||||
if ("${BOOST_ROOT}" STREQUAL "")
|
||||
file (TO_CMAKE_PATH "$ENV{BOOST_ROOT}" BOOST_ROOT)
|
||||
# Cache BOOST_ROOT for runs that do not define $ENV{BOOST_ROOT}.
|
||||
set (BOOST_ROOT ${BOOST_ROOT} CACHE PATH "BOOST_ROOT dependency path" FORCE)
|
||||
endif ()
|
||||
|
||||
message ("* Configuring Boost")
|
||||
message (STATUS "-- Using BOOST_ROOT")
|
||||
message (STATUS " " ${BOOST_ROOT})
|
||||
|
||||
if (MSVC)
|
||||
set (Boost_USE_MULTITHREADED TRUE)
|
||||
set (Boost_USE_STATIC_LIBS TRUE)
|
||||
else ()
|
||||
set (Boost_USE_MULTITHREADED FALSE)
|
||||
set (Boost_USE_STATIC_LIBS FALSE)
|
||||
endif ()
|
||||
|
||||
set (Boost_FIND_REQUIRED TRUE)
|
||||
set (Boost_FIND_QUIETLY TRUE)
|
||||
set (Boost_DEBUG FALSE)
|
||||
set (Boost_USE_MULTITHREADED TRUE)
|
||||
set (Boost_ADDITIONAL_VERSIONS "1.39.0" "1.40.0" "1.41.0" "1.42.0" "1.43.0" "1.44.0" "1.46.1") # todo: someone who knows better spesify these!
|
||||
|
||||
find_package (Boost 1.39.0 COMPONENTS "${WEBSOCKETPP_BOOST_LIBS}")
|
||||
|
||||
if (Boost_FOUND)
|
||||
# Boost is a project wide global dependency.
|
||||
include_directories (${Boost_INCLUDE_DIRS})
|
||||
link_directories (${Boost_LIBRARY_DIRS})
|
||||
|
||||
# Pretty print status
|
||||
message (STATUS "-- Include Directories")
|
||||
foreach (include_dir ${Boost_INCLUDE_DIRS})
|
||||
message (STATUS " " ${include_dir})
|
||||
endforeach ()
|
||||
message (STATUS "-- Library Directories")
|
||||
foreach (library_dir ${Boost_LIBRARY_DIRS})
|
||||
message (STATUS " " ${library_dir})
|
||||
endforeach ()
|
||||
message (STATUS "-- Libraries")
|
||||
foreach (boost_lib ${Boost_LIBRARIES})
|
||||
message (STATUS " " ${boost_lib})
|
||||
endforeach ()
|
||||
message ("")
|
||||
else ()
|
||||
message (FATAL_ERROR "Failed to find required dependency: boost")
|
||||
endif ()
|
||||
|
||||
find_package(OpenSSL)
|
||||
endif()
|
||||
|
||||
############ Add projects
|
||||
|
||||
# Add main library
|
||||
add_subdirectory (websocketpp)
|
||||
|
||||
# Add examples
|
||||
if (BUILD_EXAMPLES)
|
||||
add_subdirectory (examples)
|
||||
endif ()
|
||||
|
||||
# Add tests
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory (test)
|
||||
endif ()
|
||||
|
||||
print_used_build_config()
|
||||
|
||||
export (PACKAGE websocketpp)
|
||||
|
||||
configure_file (websocketpp-config.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake" @ONLY)
|
||||
configure_file (websocketpp-configVersion.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake" @ONLY)
|
||||
|
||||
# Install the websocketpp-config.cmake and websocketpp-configVersion.cmake
|
||||
install (FILES
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake"
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
|
145
3rdparty/cpprestsdk/libs/websocketpp/COPYING
vendored
Normal file
145
3rdparty/cpprestsdk/libs/websocketpp/COPYING
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
Main Library:
|
||||
|
||||
Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the WebSocket++ Project nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Bundled Libraries:
|
||||
|
||||
****** Base 64 Library (base64/base64.hpp) ******
|
||||
base64.hpp is a repackaging of the base64.cpp and base64.h files into a
|
||||
single header suitable for use as a header only library. This conversion was
|
||||
done by Peter Thorson (webmaster@zaphoyd.com) in 2012. All modifications to
|
||||
the code are redistributed under the same license as the original, which is
|
||||
listed below.
|
||||
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
****** SHA1 Library (sha1/sha1.hpp) ******
|
||||
sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1
|
||||
library (http://code.google.com/p/smallsha1/) into a single header suitable for
|
||||
use as a header only library. This conversion was done by Peter Thorson
|
||||
(webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed
|
||||
under the same license as the original, which is listed below.
|
||||
|
||||
Copyright (c) 2011, Micael Hildenborg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Micael Hildenborg nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
****** MD5 Library (common/md5.hpp) ******
|
||||
md5.hpp is a reformulation of the md5.h and md5.c code from
|
||||
http://www.opensource.apple.com/source/cups/cups-59/cups/md5.c to allow it to
|
||||
function as a component of a header only library. This conversion was done by
|
||||
Peter Thorson (webmaster@zaphoyd.com) in 2012 for the WebSocket++ project. The
|
||||
changes are released under the same license as the original (listed below)
|
||||
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
****** UTF8 Validation logic (utf8_validation.hpp) ******
|
||||
utf8_validation.hpp is adapted from code originally written by Bjoern Hoehrmann
|
||||
<bjoern@hoehrmann.de>. See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for
|
||||
details.
|
||||
|
||||
The original license:
|
||||
|
||||
Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
|
||||
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.
|
266
3rdparty/cpprestsdk/libs/websocketpp/SConstruct
vendored
Normal file
266
3rdparty/cpprestsdk/libs/websocketpp/SConstruct
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
import os, sys, commands
|
||||
env = Environment(ENV = os.environ)
|
||||
|
||||
# figure out a better way to configure this
|
||||
if os.environ.has_key('CXX'):
|
||||
env['CXX'] = os.environ['CXX']
|
||||
|
||||
if os.environ.has_key('DEBUG'):
|
||||
env['DEBUG'] = os.environ['DEBUG']
|
||||
|
||||
if os.environ.has_key('CXXFLAGS'):
|
||||
#env['CXXFLAGS'] = os.environ['CXXFLAGS']
|
||||
env.Append(CXXFLAGS = os.environ['CXXFLAGS'])
|
||||
|
||||
if os.environ.has_key('LINKFLAGS'):
|
||||
#env['LDFLAGS'] = os.environ['LDFLAGS']
|
||||
env.Append(LINKFLAGS = os.environ['LINKFLAGS'])
|
||||
|
||||
## Boost
|
||||
##
|
||||
## Note: You need to either set BOOSTROOT to the root of a stock Boost distribution
|
||||
## or set BOOST_INCLUDES and BOOST_LIBS if Boost comes with your OS distro e.g. and
|
||||
## needs BOOST_INCLUDES=/usr/include/boost and BOOST_LIBS=/usr/lib like Ubuntu.
|
||||
##
|
||||
if os.environ.has_key('BOOSTROOT'):
|
||||
os.environ['BOOST_ROOT'] = os.environ['BOOSTROOT']
|
||||
|
||||
if os.environ.has_key('BOOST_ROOT'):
|
||||
env['BOOST_INCLUDES'] = os.environ['BOOST_ROOT']
|
||||
env['BOOST_LIBS'] = os.path.join(os.environ['BOOST_ROOT'], 'stage', 'lib')
|
||||
elif os.environ.has_key('BOOST_INCLUDES') and os.environ.has_key('BOOST_LIBS'):
|
||||
env['BOOST_INCLUDES'] = os.environ['BOOST_INCLUDES']
|
||||
env['BOOST_LIBS'] = os.environ['BOOST_LIBS']
|
||||
else:
|
||||
raise SCons.Errors.UserError, "Neither BOOST_ROOT, nor BOOST_INCLUDES + BOOST_LIBS was set!"
|
||||
|
||||
if os.environ.has_key('WSPP_ENABLE_CPP11'):
|
||||
env['WSPP_ENABLE_CPP11'] = True
|
||||
else:
|
||||
env['WSPP_ENABLE_CPP11'] = False
|
||||
|
||||
boost_linkshared = False
|
||||
|
||||
def boostlibs(libnames,localenv):
|
||||
if localenv['PLATFORM'].startswith('win'):
|
||||
# Win/VC++ supports autolinking. nothing to do.
|
||||
# http://www.boost.org/doc/libs/1_49_0/more/getting_started/windows.html#auto-linking
|
||||
return []
|
||||
else:
|
||||
libs = []
|
||||
prefix = localenv['SHLIBPREFIX'] if boost_linkshared else localenv['LIBPREFIX']
|
||||
suffix = localenv['SHLIBSUFFIX'] if boost_linkshared else localenv['LIBSUFFIX']
|
||||
for name in libnames:
|
||||
lib = File(os.path.join(localenv['BOOST_LIBS'], '%sboost_%s%s' % (prefix, name, suffix)))
|
||||
libs.append(lib)
|
||||
return libs
|
||||
|
||||
if env['PLATFORM'].startswith('win'):
|
||||
env.Append(CPPDEFINES = ['WIN32',
|
||||
'NDEBUG',
|
||||
'WIN32_LEAN_AND_MEAN',
|
||||
'_WIN32_WINNT=0x0600',
|
||||
'_CONSOLE',
|
||||
'BOOST_TEST_DYN_LINK',
|
||||
'NOMINMAX',
|
||||
'_WEBSOCKETPP_CPP11_MEMORY_',
|
||||
'_WEBSOCKETPP_CPP11_FUNCTIONAL_'])
|
||||
arch_flags = '/arch:SSE2'
|
||||
opt_flags = '/Ox /Oi /fp:fast'
|
||||
warn_flags = '/W3 /wd4996 /wd4995 /wd4355'
|
||||
env['CCFLAGS'] = '%s /EHsc /GR /GS- /MD /nologo %s %s' % (warn_flags, arch_flags, opt_flags)
|
||||
env['LINKFLAGS'] = '/INCREMENTAL:NO /MANIFEST /NOLOGO /OPT:REF /OPT:ICF /MACHINE:X86'
|
||||
elif env['PLATFORM'] == 'posix':
|
||||
if env.has_key('DEBUG'):
|
||||
env.Append(CCFLAGS = ['-g', '-O0'])
|
||||
else:
|
||||
env.Append(CPPDEFINES = ['NDEBUG'])
|
||||
env.Append(CCFLAGS = ['-O1', '-fomit-frame-pointer'])
|
||||
env.Append(CCFLAGS = ['-Wall'])
|
||||
#env['LINKFLAGS'] = ''
|
||||
elif env['PLATFORM'] == 'darwin':
|
||||
if not os.environ.has_key('CXX'):
|
||||
env['CXX'] = "clang++"
|
||||
if env.has_key('DEBUG'):
|
||||
env.Append(CCFLAGS = ['-g', '-O0'])
|
||||
else:
|
||||
env.Append(CPPDEFINES = ['NDEBUG'])
|
||||
env.Append(CCFLAGS = ['-O1', '-fomit-frame-pointer'])
|
||||
env.Append(CCFLAGS = ['-Wall'])
|
||||
#env['LINKFLAGS'] = ''
|
||||
|
||||
if env['PLATFORM'].startswith('win'):
|
||||
#env['LIBPATH'] = env['BOOST_LIBS']
|
||||
pass
|
||||
else:
|
||||
env['LIBPATH'] = ['/usr/lib',
|
||||
'/usr/local/lib'] #, env['BOOST_LIBS']
|
||||
|
||||
# Compiler specific warning flags
|
||||
if env['CXX'].startswith('g++'):
|
||||
#env.Append(CCFLAGS = ['-Wconversion'])
|
||||
env.Append(CCFLAGS = ['-Wcast-align'])
|
||||
env.Append(CCFLAGS = ['-Wshadow'])
|
||||
env.Append(CCFLAGS = ['-Wunused-parameter'])
|
||||
elif env['CXX'].startswith('clang++'):
|
||||
#env.Append(CCFLAGS = ['-Wcast-align'])
|
||||
#env.Append(CCFLAGS = ['-Wglobal-constructors'])
|
||||
#env.Append(CCFLAGS = ['-Wconversion'])
|
||||
env.Append(CCFLAGS = ['-Wno-padded'])
|
||||
env.Append(CCFLAGS = ['-Wshadow'])
|
||||
env.Append(CCFLAGS = ['-Wunused-parameter'])
|
||||
|
||||
env.Append(CCFLAGS = ['-Wsometimes-uninitialized'])
|
||||
env.Append(CCFLAGS = ['-Wuninitialized'])
|
||||
|
||||
#env.Append(CCFLAGS = ['-Weverything'])
|
||||
#env.Append(CCFLAGS = ['-Wno-documentation'])
|
||||
#env.Append(CCFLAGS = ['-Wno-weak-vtables'])
|
||||
#env.Append(CCFLAGS = ['-Wno-global-constructors'])
|
||||
#env.Append(CCFLAGS = ['-Wno-sign-conversion'])
|
||||
#env.Append(CCFLAGS = ['-Wno-exit-time-destructors'])
|
||||
|
||||
|
||||
|
||||
|
||||
# Wpadded
|
||||
# Wsign-conversion
|
||||
|
||||
platform_libs = []
|
||||
tls_libs = []
|
||||
|
||||
tls_build = False
|
||||
|
||||
if env['PLATFORM'] == 'posix':
|
||||
platform_libs = ['pthread', 'rt']
|
||||
tls_libs = ['ssl', 'crypto']
|
||||
tls_build = True
|
||||
elif env['PLATFORM'] == 'darwin':
|
||||
tls_libs = ['ssl', 'crypto']
|
||||
tls_build = True
|
||||
elif env['PLATFORM'].startswith('win'):
|
||||
# Win/VC++ supports autolinking. nothing to do.
|
||||
pass
|
||||
|
||||
## Append WebSocket++ path
|
||||
env.Append(CPPPATH = ['#'])
|
||||
|
||||
##### Set up C++11 environment
|
||||
polyfill_libs = [] # boost libraries used as drop in replacements for incomplete
|
||||
# C++11 STL implementations
|
||||
env_cpp11 = env.Clone ()
|
||||
|
||||
if env_cpp11['CXX'].startswith('g++'):
|
||||
# TODO: check g++ version
|
||||
GCC_VERSION = commands.getoutput(env_cpp11['CXX'] + ' -dumpversion')
|
||||
|
||||
if GCC_VERSION > "4.4.0":
|
||||
print "C++11 build environment partially enabled"
|
||||
env_cpp11.Append(WSPP_CPP11_ENABLED = "true",CXXFLAGS = ['-std=c++0x'],TOOLSET = ['g++'],CPPDEFINES = ['_WEBSOCKETPP_CPP11_STL_'])
|
||||
else:
|
||||
print "C++11 build environment is not supported on this version of G++"
|
||||
elif env_cpp11['CXX'].startswith('clang++'):
|
||||
print "C++11 build environment enabled"
|
||||
env.Append(CXXFLANGS = ['-stdlib=libc++'],LINKFLAGS=['-stdlib=libc++'])
|
||||
env_cpp11.Append(WSPP_CPP11_ENABLED = "true",CXXFLAGS = ['-std=c++0x','-stdlib=libc++'],LINKFLAGS = ['-stdlib=libc++'],TOOLSET = ['clang++'],CPPDEFINES = ['_WEBSOCKETPP_CPP11_STL_'])
|
||||
|
||||
# look for optional second boostroot compiled with clang's libc++ STL library
|
||||
# this prevents warnings/errors when linking code built with two different
|
||||
# incompatible STL libraries.
|
||||
if os.environ.has_key('BOOST_ROOT_CPP11'):
|
||||
env_cpp11['BOOST_INCLUDES'] = os.environ['BOOST_ROOT_CPP11']
|
||||
env_cpp11['BOOST_LIBS'] = os.path.join(os.environ['BOOST_ROOT_CPP11'], 'stage', 'lib')
|
||||
elif os.environ.has_key('BOOST_INCLUDES_CPP11') and os.environ.has_key('BOOST_LIBS_CPP11'):
|
||||
env_cpp11['BOOST_INCLUDES'] = os.environ['BOOST_INCLUDES_CPP11']
|
||||
env_cpp11['BOOST_LIBS'] = os.environ['BOOST_LIBS_CPP11']
|
||||
else:
|
||||
print "C++11 build environment disabled"
|
||||
|
||||
# if the build system is known to allow the isystem modifier for library include
|
||||
# values then use it for the boost libraries. Otherwise just add them to the
|
||||
# regular CPPPATH values.
|
||||
if env['CXX'].startswith('g++') or env['CXX'].startswith('clang'):
|
||||
env.Append(CPPFLAGS = '-isystem ' + env['BOOST_INCLUDES'])
|
||||
else:
|
||||
env.Append(CPPPATH = [env['BOOST_INCLUDES']])
|
||||
env.Append(LIBPATH = [env['BOOST_LIBS']])
|
||||
|
||||
# if the build system is known to allow the isystem modifier for library include
|
||||
# values then use it for the boost libraries. Otherwise just add them to the
|
||||
# regular CPPPATH values.
|
||||
if env_cpp11['CXX'].startswith('g++') or env_cpp11['CXX'].startswith('clang'):
|
||||
env_cpp11.Append(CPPFLAGS = '-isystem ' + env_cpp11['BOOST_INCLUDES'])
|
||||
else:
|
||||
env_cpp11.Append(CPPPATH = [env_cpp11['BOOST_INCLUDES']])
|
||||
env_cpp11.Append(LIBPATH = [env_cpp11['BOOST_LIBS']])
|
||||
|
||||
releasedir = 'build/release/'
|
||||
debugdir = 'build/debug/'
|
||||
testdir = 'build/test/'
|
||||
builddir = releasedir
|
||||
|
||||
Export('env')
|
||||
Export('env_cpp11')
|
||||
Export('platform_libs')
|
||||
Export('boostlibs')
|
||||
Export('tls_libs')
|
||||
Export('polyfill_libs')
|
||||
|
||||
## END OF CONFIG !!
|
||||
|
||||
## TARGETS:
|
||||
|
||||
if not env['PLATFORM'].startswith('win'):
|
||||
# Unit tests, add test folders with SConscript files to to_test list.
|
||||
to_test = ['utility','http','logger','random','processors','message_buffer','extension','transport/iostream','transport/asio','roles','endpoint','connection','transport'] #,'http','processors','connection'
|
||||
|
||||
for t in to_test:
|
||||
new_tests = SConscript('#/test/'+t+'/SConscript',variant_dir = testdir + t, duplicate = 0)
|
||||
for a in new_tests:
|
||||
new_alias = Alias('test', [a], a.abspath)
|
||||
AlwaysBuild(new_alias)
|
||||
|
||||
# Main test application
|
||||
#main = SConscript('#/examples/dev/SConscript',variant_dir = builddir + 'dev',duplicate = 0)
|
||||
|
||||
# echo_server
|
||||
echo_server = SConscript('#/examples/echo_server/SConscript',variant_dir = builddir + 'echo_server',duplicate = 0)
|
||||
|
||||
# echo_server_tls
|
||||
if tls_build:
|
||||
echo_server_tls = SConscript('#/examples/echo_server_tls/SConscript',variant_dir = builddir + 'echo_server_tls',duplicate = 0)
|
||||
echo_server_both = SConscript('#/examples/echo_server_both/SConscript',variant_dir = builddir + 'echo_server_both',duplicate = 0)
|
||||
|
||||
# broadcast_server
|
||||
broadcast_server = SConscript('#/examples/broadcast_server/SConscript',variant_dir = builddir + 'broadcast_server',duplicate = 0)
|
||||
|
||||
# testee_server
|
||||
testee_server = SConscript('#/examples/testee_server/SConscript',variant_dir = builddir + 'testee_server',duplicate = 0)
|
||||
|
||||
# testee_client
|
||||
testee_client = SConscript('#/examples/testee_client/SConscript',variant_dir = builddir + 'testee_client',duplicate = 0)
|
||||
|
||||
# utility_client
|
||||
utility_client = SConscript('#/examples/utility_client/SConscript',variant_dir = builddir + 'utility_client',duplicate = 0)
|
||||
|
||||
# debug_client
|
||||
debug_client = SConscript('#/examples/debug_client/SConscript',variant_dir = builddir + 'debug_client',duplicate = 0)
|
||||
|
||||
# debug_server
|
||||
debug_server = SConscript('#/examples/debug_server/SConscript',variant_dir = builddir + 'debug_server',duplicate = 0)
|
||||
|
||||
# subprotocol_server
|
||||
subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',variant_dir = builddir + 'subprotocol_server',duplicate = 0)
|
||||
|
||||
# telemetry_server
|
||||
telemetry_server = SConscript('#/examples/telemetry_server/SConscript',variant_dir = builddir + 'telemetry_server',duplicate = 0)
|
||||
|
||||
if not env['PLATFORM'].startswith('win'):
|
||||
# iostream_server
|
||||
iostream_server = SConscript('#/examples/iostream_server/SConscript',variant_dir = builddir + 'iostream_server',duplicate = 0)
|
||||
|
||||
# telemetry_client
|
||||
telemetry_client = SConscript('#/examples/telemetry_client/SConscript',variant_dir = builddir + 'telemetry_client',duplicate = 0)
|
||||
|
||||
# print_server
|
||||
print_server = SConscript('#/examples/print_server/SConscript',variant_dir = builddir + 'print_server',duplicate = 0)
|
234
3rdparty/cpprestsdk/libs/websocketpp/changelog.md
vendored
Normal file
234
3rdparty/cpprestsdk/libs/websocketpp/changelog.md
vendored
Normal file
|
@ -0,0 +1,234 @@
|
|||
HEAD
|
||||
|
||||
0.5.1 - 2015-02-27
|
||||
- Bug: Fixes an issue where some frame data was counted against the max header
|
||||
size limit, resulting in connections that included a lot of frame data
|
||||
immediately after the opening handshake to fail.
|
||||
- Bug: Fix a type in the name of the set method for `max_http_body_size`. #406
|
||||
Thank you jplatte for reporting.
|
||||
|
||||
0.5.0 - 2015-01-22
|
||||
- BREAKING UTILITY CHANGE: Deprecated methods `http::parser::parse_headers`,
|
||||
`http::response::parse_complete`, and `http::request::parse_complete` have
|
||||
been removed.
|
||||
- Security: Disabled SSLv3 in example servers.
|
||||
- Feature: Adds basic support for accessing HTTP request bodies in the http
|
||||
handler. #181
|
||||
- Feature: Adds the ability to register a shutdown handler when using the
|
||||
iostream transport. This provides a clean interface for triggering the shut
|
||||
down of external sockets and other cleanup without hooking in to higher level
|
||||
WebSocket handlers.
|
||||
- Feature: Adds the ability to register a write handler when using the iostream
|
||||
transport. This handler can be used to handle transport output in place of
|
||||
registering an ostream to write to.
|
||||
- Feature: Adds a new logging policy that outputs to syslog. #386 Thank you Tom
|
||||
Hughes for submitting the initial version of this policy.
|
||||
- Improvement: Message payload logging now prints text for text messages rather
|
||||
than binary.
|
||||
- Improvement: Overhaul of handshake state machine. Should make it impossible
|
||||
for exceptions to bubble out of transport methods like `io_service::run`.
|
||||
- Improvement: Overhaul of handshake error reporting. Fail handler error codes
|
||||
will be more detailed and precise. Adds new [fail] and [http] logging channels
|
||||
that log failed websocket connections and successful HTTP connections
|
||||
respectively. A new aggregate channel package, `alevel::access_core`, allows
|
||||
enabling connect, disconnect, fail, and http together. Successful HTTP
|
||||
connections will no longer trigger a fail handler.
|
||||
- Improvement: Ability to terminate connection during an http handler to cleanly
|
||||
suppress the default outgoing HTTP response.
|
||||
- Documentation: Add Sending & Receiving Messages step to chapter one of the
|
||||
`utility_client` tutorial. Update `utility_client` example to match.
|
||||
- Cleanup: Removes unused files & STL includes. Adds required STL includes.
|
||||
Normalizes include order.
|
||||
- Bug: Fixes a fatal state error when a handshake response is completed
|
||||
immediately after that handshake times out. #389
|
||||
- Bug: MinGW fixes; C++11 feature detection, localtime use. #393 Thank you
|
||||
Schebb for reporting, code, and testing.
|
||||
- Bug: Fixes an issue where `websocketpp::exception::what()` could return an out
|
||||
of scope pointer. #397 Thank you fabioang for reporting.
|
||||
- Bug: Fixes an issue where endpoints were not reset properly after a call to
|
||||
`endpoint::listen` failed. #390 Thank you wyyqyl for reporting.
|
||||
|
||||
0.4.0 - 2014-11-04
|
||||
- BREAKING API CHANGE: All WebSocket++ methods now throw an exception of type
|
||||
`websocketpp::exception` which derives from `std::exception`. This normalizes
|
||||
all exception types under the standard exception hierarchy and allows
|
||||
WebSocket++ exceptions to be caught in the same statement as others. The error
|
||||
code that was previously thrown is wrapped in the exception object and can be
|
||||
accessed via the `websocketpp::exception::code()` method.
|
||||
- BREAKING API CHANGE: Custom logging policies have some new required
|
||||
constructors that take generic config settings rather than pointers to
|
||||
std::ostreams. This allows writing logging policies that do not involve the
|
||||
use of std::ostream. This does not affect anyone using the built in logging
|
||||
policies.
|
||||
- BREAKING UTILITY CHANGE: `websocketpp::lib::net::htonll` and
|
||||
`websocketpp::lib::net::ntohll` have been prefixed with an underscore to avoid
|
||||
conflicts with similarly named macros in some operating systems. If you are
|
||||
using the WebSocket++ provided 64 bit host/network byte order functions you
|
||||
will need to switch to the prefixed versions.
|
||||
- BREAKING UTILITY CHANGE: The signature of `base64_encode` has changed from
|
||||
`websocketpp::base64_encode(unsigned char const *, unsigned int)` to
|
||||
`websocketpp::base64_encode(unsigned char const *, size_t)`.
|
||||
- BREAKING UTILITY CHANGE: The signature of `sha1::calc` has changed from
|
||||
`websocketpp::sha1::calc(void const *, int, unsigned char *)` to
|
||||
`websocketpp::sha1::calc(void const *, size_t, unsigned char *)`
|
||||
- Feature: Adds incomplete `minimal_server` and `minimal_client` configs that
|
||||
can be used to build custom configs without pulling in the dependencies of
|
||||
`core` or `core_client`. These configs will offer a stable base config to
|
||||
future-proof custom configs.
|
||||
- Improvement: Core library no longer has std::iostream as a dependency.
|
||||
std::iostream is still required for the optional iostream logging policy and
|
||||
iostream transport.
|
||||
- Bug: C++11 Chrono support was being incorrectly detected by the `boost_config`
|
||||
header. Thank you Max Dmitrichenko for reporting and a patch.
|
||||
- Bug: use of `std::put_time` is now guarded by a unique flag rather than a
|
||||
chrono library flag. Thank you Max Dmitrichenko for reporting.
|
||||
- Bug: Fixes non-thread safe use of std::localtime. #347 #383
|
||||
- Compatibility: Adjust usage of std::min to be more compatible with systems
|
||||
that define a min(...) macro.
|
||||
- Compatibility: Removes unused parameters from all library, test, and example
|
||||
code. This assists with those developing with -Werror and -Wunused-parameter
|
||||
#376
|
||||
- Compatibility: Renames ntohll and htonll methods to avoid conflicts with
|
||||
platform specific macros. #358 #381, #382 Thank you logotype, unphased,
|
||||
svendjo
|
||||
- Cleanup: Removes unused functions, fixes variable shadow warnings, normalizes
|
||||
all whitespace in library, examples, and tests to 4 spaces. #376
|
||||
|
||||
0.3.0 - 2014-08-10
|
||||
- Feature: Adds `start_perpetual` and `stop_perpetual` methods to asio transport
|
||||
These may be used to replace manually managed `asio::io_service::work` objects
|
||||
- Feature: Allow setting pong and handshake timeouts at runtime.
|
||||
- Feature: Allows changing the listen backlog queue length.
|
||||
- Feature: Split tcp init into pre and post init.
|
||||
- Feature: Adds URI method to extract query string from URI. Thank you Banaan
|
||||
for code. #298
|
||||
- Feature: Adds a compile time switch to asio transport config to disable
|
||||
certain multithreading features (some locks, asio strands)
|
||||
- Feature: Adds the ability to pause reading on a connection. Paused connections
|
||||
will not read more data from their socket, allowing TCP flow control to work
|
||||
without blocking the main thread.
|
||||
- Feature: Adds the ability to specify whether or not to use the `SO_REUSEADDR`
|
||||
TCP socket option. The default for this value has been changed from `true` to
|
||||
`false`.
|
||||
- Feature: Adds the ability to specify a maximum message size.
|
||||
- Feature: Adds `close::status::get_string(...)` method to look up a human
|
||||
readable string given a close code value.
|
||||
- Feature: Adds `connection::read_all(...)` method to iostream transport as a
|
||||
convenience method for reading all data into the connection buffer without the
|
||||
end user needing to manually loop on `read_some`.
|
||||
- Improvement: Open, close, and pong timeouts can be disabled entirely by
|
||||
setting their duration to 0.
|
||||
- Improvement: Numerous performance improvements. Including: tuned default
|
||||
buffer sizes based on profiling, caching of handler binding for async
|
||||
reads/writes, non-malloc allocators for read/write handlers, disabling of a
|
||||
number of questionably useful range sanity checks in tight inner loops.
|
||||
- Improvement: Cleaned up the handling of TLS related errors. TLS errors will
|
||||
now be reported with more detail on the info channel rather than all being
|
||||
`tls_short_read` or `pass_through`. In addition, many cases where a TLS short
|
||||
read was in fact expected are no longer classified as errors. Expected TLS
|
||||
short reads and quasi-expected socket shutdown related errors will no longer
|
||||
be reported as unclean WebSocket shutdowns to the application. Information
|
||||
about them will remain in the info error channel for debugging purposes.
|
||||
- Improvement: `start_accept` and `listen` errors are now reported to the caller
|
||||
either via an exception or an ec parameter.
|
||||
- Improvement: Outgoing writes are now batched for improved message throughput
|
||||
and reduced system call and TCP frame overhead.
|
||||
- Bug: Fix some cases of calls to empty lib::function objects.
|
||||
- Bug: Fix memory leak of connection objects due to cached handlers holding on to
|
||||
reference counted pointers. #310 Thank you otaras for reporting.
|
||||
- Bug: Fix issue with const endpoint accessors (such as `get_user_agent`) not
|
||||
compiling due to non-const mutex use. #292 Thank you logofive for reporting.
|
||||
- Bug: Fix handler allocation crash with multithreaded `io_service`.
|
||||
- Bug: Fixes incorrect whitespace handling in header parsing. #301 Thank you
|
||||
Wolfram Schroers for reporting
|
||||
- Bug: Fix a crash when parsing empty HTTP headers. Thank you Thingol for
|
||||
reporting.
|
||||
- Bug: Fix a crash following use of the `stop_listening` function. Thank you
|
||||
Thingol for reporting.
|
||||
- Bug: Fix use of variable names that shadow function parameters. The library
|
||||
should compile cleanly with -Wshadow now. Thank you giszo for reporting. #318
|
||||
- Bug: Fix an issue where `set_open_handshake_timeout` was ignored by server
|
||||
code. Thank you Robin Rowe for reporting.
|
||||
- Bug: Fix an issue where custom timeout values weren't being propagated from
|
||||
endpoints to new connections.
|
||||
- Bug: Fix a number of memory leaks related to server connection failures. #323
|
||||
#333 #334 #335 Thank you droppy and aydany for reporting and patches.
|
||||
reporting.
|
||||
- Compatibility: Fix compile time conflict with Visual Studio's MIN/MAX macros.
|
||||
Thank you Robin Rowe for reporting.
|
||||
- Documentation: Examples and test suite build system now defaults to clang on
|
||||
OS X
|
||||
|
||||
0.3.0-alpha4 - 2013-10-11
|
||||
- HTTP requests ending normally are no longer logged as errors. Thank you Banaan
|
||||
for reporting. #294
|
||||
- Eliminates spurious expired timers in certain error conditions. Thank you
|
||||
Banaan for reporting. #295
|
||||
- Consolidates all bundled library licenses into the COPYING file. #294
|
||||
- Updates bundled sha1 library to one with a cleaner interface and more
|
||||
straight-forward license. Thank you lotodore for reporting and Evgeni Golov
|
||||
for reviewing. #294
|
||||
- Re-introduces strands to asio transport, allowing `io_service` thread pools to
|
||||
be used (with some limitations).
|
||||
- Removes endpoint code that kept track of a connection list that was never used
|
||||
anywhere. Removes a lock and reduces connection creation/deletion complexity
|
||||
from O(log n) to O(1) in the number of connections.
|
||||
- A number of internal changes to transport APIs
|
||||
- Deprecates iostream transport `readsome` in favor of `read_some` which is more
|
||||
consistent with the naming of the rest of the library.
|
||||
- Adds preliminary signaling to iostream transport of eof and fatal transport
|
||||
errors
|
||||
- Updates transport code to use shared pointers rather than raw pointers to
|
||||
prevent asio from retaining pointers to connection methods after the
|
||||
connection goes out of scope. #293 Thank you otaras for reporting.
|
||||
- Fixes an issue where custom headers couldn't be set for client connections
|
||||
Thank you Jerry Win and Wolfram Schroers for reporting.
|
||||
- Fixes a compile error on visual studio when using interrupts. Thank you Javier
|
||||
Rey Neira for reporting this.
|
||||
- Adds new 1012 and 1013 close codes per IANA registry
|
||||
- Add `set_remote_endpoint` method to iostream transport.
|
||||
- Add `set_secure` method to iostream transport.
|
||||
- Fix typo in .gitattributes file. Thank you jstarasov for reporting this. #280
|
||||
- Add missing locale include. Thank you Toninoso for reporting this. #281
|
||||
- Refactors `asio_transport` endpoint and adds full documentation and exception
|
||||
free varients of all methods.
|
||||
- Removes `asio_transport` endpoint method cancel(). Use `stop_listen()` instead
|
||||
- Wrap internal `io_service` `run_one()` method
|
||||
- Suppress error when trying to shut down a connection that was already closed
|
||||
|
||||
0.3.0-alpha3 - 2013-07-16
|
||||
- Minor refactor to bundled sha1 library
|
||||
- HTTP header comparisons are now case insensitive. #220, #275
|
||||
- Refactors URI to be exception free and not use regular expressions. This
|
||||
eliminates the dependency on boost or C++11 regex libraries allowing native
|
||||
C++11 usage on GCC 4.4 and higher and significantly reduces staticly built
|
||||
binary sizes.
|
||||
- Updates handling of Server and User-Agent headers to better handle custom
|
||||
settings and allow suppression of these headers for security purposes.
|
||||
- Fix issue where pong timeout handler always fired. Thank you Steven Klassen
|
||||
for reporting this bug.
|
||||
- Add ping and pong endpoint wrapper methods
|
||||
- Add `get_request()` pass through method to connection to allow calling methods
|
||||
specific to the HTTP policy in use.
|
||||
- Fix issue compile error with `WEBSOCKETPP_STRICT_MASKING` enabled and another
|
||||
issue where `WEBSOCKETPP_STRICT_MASKING` was not applied to incoming messages.
|
||||
Thank you Petter Norby for reporting and testing these bugs. #264
|
||||
- Add additional macro guards for use with boost_config. Thank you breyed
|
||||
for testing and code. #261
|
||||
|
||||
0.3.0-alpha2 - 2013-06-09
|
||||
- Fix a regression that caused servers being sent two close frames in a row
|
||||
to end a connection uncleanly. #259
|
||||
- Fix a regression that caused spurious frames following a legitimate close
|
||||
frames to erroneously trigger handlers. #258
|
||||
- Change default HTTP response error code when no http_handler is defined from
|
||||
500/Internal Server Error to 426/Upgrade Required
|
||||
- Remove timezone from logger timestamp to work around issues with the Windows
|
||||
implementation of strftime. Thank you breyed for testing and code. #257
|
||||
- Switch integer literals to char literals to improve VCPP compatibility.
|
||||
Thank you breyed for testing and code. #257
|
||||
- Add MSVCPP warning suppression for the bundled SHA1 library. Thank you breyed
|
||||
for testing and code. #257
|
||||
|
||||
0.3.0-alpha1 - 2013-06-09
|
||||
- Initial Release
|
52
3rdparty/cpprestsdk/libs/websocketpp/docs/simple_broadcast_server.cpp
vendored
Normal file
52
3rdparty/cpprestsdk/libs/websocketpp/docs/simple_broadcast_server.cpp
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include <set>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
class broadcast_server {
|
||||
public:
|
||||
broadcast_server() {
|
||||
m_server.init_asio();
|
||||
|
||||
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
|
||||
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
|
||||
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
m_connections.insert(hdl);
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
m_connections.erase(hdl);
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
for (auto it : m_connections) {
|
||||
m_server.send(it,msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
};
|
||||
|
||||
int main() {
|
||||
broadcast_server server;
|
||||
server.run(9002);
|
||||
}
|
65
3rdparty/cpprestsdk/libs/websocketpp/docs/simple_count_server_thread.cpp
vendored
Normal file
65
3rdparty/cpprestsdk/libs/websocketpp/docs/simple_count_server_thread.cpp
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
|
||||
class count_server {
|
||||
public:
|
||||
count_server() : m_count(0) {
|
||||
m_server.init_asio();
|
||||
|
||||
m_server.set_open_handler(bind(&count_server::on_open,this,_1));
|
||||
m_server.set_close_handler(bind(&count_server::on_close,this,_1));
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_connections.insert(hdl);
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_connections.erase(hdl);
|
||||
}
|
||||
|
||||
void count() {
|
||||
while (1) {
|
||||
sleep(1);
|
||||
m_count++;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << m_count;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
for (auto it : m_connections) {
|
||||
m_server.send(it,ss.str(),websocketpp::frame::opcode::text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
int m_count;
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
int main() {
|
||||
count_server server;
|
||||
std::thread t(std::bind(&count_server::count,&server));
|
||||
server.run(9002);
|
||||
}
|
6
3rdparty/cpprestsdk/libs/websocketpp/examples/CMakeLists.txt
vendored
Normal file
6
3rdparty/cpprestsdk/libs/websocketpp/examples/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
|
||||
foreach (SUBDIR ${SDIRS})
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt")
|
||||
add_subdirectory (${SUBDIR})
|
||||
endif ()
|
||||
endforeach ()
|
88
3rdparty/cpprestsdk/libs/websocketpp/examples/associative_storage/associative_storage.cpp
vendored
Normal file
88
3rdparty/cpprestsdk/libs/websocketpp/examples/associative_storage/associative_storage.cpp
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include <iostream>
|
||||
#include <map>
|
||||
#include <exception>
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
struct connection_data {
|
||||
int sessionid;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class print_server {
|
||||
public:
|
||||
print_server() : m_next_sessionid(1) {
|
||||
m_server.init_asio();
|
||||
|
||||
m_server.set_open_handler(bind(&print_server::on_open,this,::_1));
|
||||
m_server.set_close_handler(bind(&print_server::on_close,this,::_1));
|
||||
m_server.set_message_handler(bind(&print_server::on_message,this,::_1,::_2));
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
connection_data data;
|
||||
|
||||
data.sessionid = m_next_sessionid++;
|
||||
data.name = "";
|
||||
|
||||
m_connections[hdl] = data;
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
connection_data& data = get_data_from_hdl(hdl);
|
||||
|
||||
std::cout << "Closing connection " << data.name
|
||||
<< " with sessionid " << data.sessionid << std::endl;
|
||||
|
||||
m_connections.erase(hdl);
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
connection_data& data = get_data_from_hdl(hdl);
|
||||
|
||||
if (data.name == "") {
|
||||
data.name = msg->get_payload();
|
||||
std::cout << "Setting name of connection with sessionid "
|
||||
<< data.sessionid << " to " << data.name << std::endl;
|
||||
} else {
|
||||
std::cout << "Got a message from connection " << data.name
|
||||
<< " with sessionid " << data.sessionid << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
connection_data& get_data_from_hdl(connection_hdl hdl) {
|
||||
auto it = m_connections.find(hdl);
|
||||
|
||||
if (it == m_connections.end()) {
|
||||
// this connection is not in the list. This really shouldn't happen
|
||||
// and probably means something else is wrong.
|
||||
throw std::invalid_argument("No data available for session");
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
typedef std::map<connection_hdl,connection_data,std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
int m_next_sessionid;
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
};
|
||||
|
||||
int main() {
|
||||
print_server server;
|
||||
server.run(9002);
|
||||
}
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/broadcast_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/broadcast_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Broadcast Server example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','thread'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
156
3rdparty/cpprestsdk/libs/websocketpp/examples/broadcast_server/broadcast_server.cpp
vendored
Normal file
156
3rdparty/cpprestsdk/libs/websocketpp/examples/broadcast_server/broadcast_server.cpp
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
/*#include <boost/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>*/
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
using websocketpp::lib::thread;
|
||||
using websocketpp::lib::mutex;
|
||||
using websocketpp::lib::unique_lock;
|
||||
using websocketpp::lib::condition_variable;
|
||||
|
||||
/* on_open insert connection_hdl into channel
|
||||
* on_close remove connection_hdl from channel
|
||||
* on_message queue send to all channels
|
||||
*/
|
||||
|
||||
enum action_type {
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
MESSAGE
|
||||
};
|
||||
|
||||
struct action {
|
||||
action(action_type t, connection_hdl h) : type(t), hdl(h) {}
|
||||
action(action_type t, connection_hdl h, server::message_ptr m)
|
||||
: type(t), hdl(h), msg(m) {}
|
||||
|
||||
action_type type;
|
||||
websocketpp::connection_hdl hdl;
|
||||
server::message_ptr msg;
|
||||
};
|
||||
|
||||
class broadcast_server {
|
||||
public:
|
||||
broadcast_server() {
|
||||
// Initialize Asio Transport
|
||||
m_server.init_asio();
|
||||
|
||||
// Register handler callbacks
|
||||
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
|
||||
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
|
||||
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
// listen on specified port
|
||||
m_server.listen(port);
|
||||
|
||||
// Start the server accept loop
|
||||
m_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
try {
|
||||
m_server.run();
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
//std::cout << "on_open" << std::endl;
|
||||
m_actions.push(action(SUBSCRIBE,hdl));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
//std::cout << "on_close" << std::endl;
|
||||
m_actions.push(action(UNSUBSCRIBE,hdl));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
// queue message up for sending by processing thread
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
//std::cout << "on_message" << std::endl;
|
||||
m_actions.push(action(MESSAGE,hdl,msg));
|
||||
lock.unlock();
|
||||
m_action_cond.notify_one();
|
||||
}
|
||||
|
||||
void process_messages() {
|
||||
while(1) {
|
||||
unique_lock<mutex> lock(m_action_lock);
|
||||
|
||||
while(m_actions.empty()) {
|
||||
m_action_cond.wait(lock);
|
||||
}
|
||||
|
||||
action a = m_actions.front();
|
||||
m_actions.pop();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (a.type == SUBSCRIBE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.insert(a.hdl);
|
||||
} else if (a.type == UNSUBSCRIBE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
m_connections.erase(a.hdl);
|
||||
} else if (a.type == MESSAGE) {
|
||||
unique_lock<mutex> con_lock(m_connection_lock);
|
||||
|
||||
con_list::iterator it;
|
||||
for (it = m_connections.begin(); it != m_connections.end(); ++it) {
|
||||
m_server.send(*it,a.msg);
|
||||
}
|
||||
} else {
|
||||
// undefined.
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl> > con_list;
|
||||
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
std::queue<action> m_actions;
|
||||
|
||||
mutex m_action_lock;
|
||||
mutex m_connection_lock;
|
||||
condition_variable m_action_cond;
|
||||
};
|
||||
|
||||
int main() {
|
||||
try {
|
||||
broadcast_server server_instance;
|
||||
|
||||
// Start a thread to run the processing loop
|
||||
thread t(bind(&broadcast_server::process_messages,&server_instance));
|
||||
|
||||
// Run the asio loop with the main thread
|
||||
server_instance.run(9002);
|
||||
|
||||
t.join();
|
||||
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
24
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_client/SConscript
vendored
Normal file
24
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_client/SConscript
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
## Debug client example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
166
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_client/debug_client.cpp
vendored
Normal file
166
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_client/debug_client.cpp
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/asio_client.hpp>
|
||||
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
typedef client::connection_ptr connection_ptr;
|
||||
|
||||
|
||||
|
||||
class perftest {
|
||||
public:
|
||||
typedef perftest type;
|
||||
typedef std::chrono::duration<int,std::micro> dur_type;
|
||||
|
||||
perftest () {
|
||||
m_endpoint.set_access_channels(websocketpp::log::alevel::all);
|
||||
m_endpoint.set_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
m_endpoint.init_asio();
|
||||
|
||||
// Register our handlers
|
||||
m_endpoint.set_socket_init_handler(bind(&type::on_socket_init,this,::_1));
|
||||
//m_endpoint.set_tls_init_handler(bind(&type::on_tls_init,this,::_1));
|
||||
m_endpoint.set_message_handler(bind(&type::on_message,this,::_1,::_2));
|
||||
m_endpoint.set_open_handler(bind(&type::on_open,this,::_1));
|
||||
m_endpoint.set_close_handler(bind(&type::on_close,this,::_1));
|
||||
m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1));
|
||||
}
|
||||
|
||||
void start(std::string uri) {
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = m_endpoint.get_connection(uri, ec);
|
||||
|
||||
if (ec) {
|
||||
m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message());
|
||||
}
|
||||
|
||||
//con->set_proxy("http://humupdates.uchicago.edu:8443");
|
||||
|
||||
m_endpoint.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
m_start = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.run();
|
||||
}
|
||||
|
||||
void on_socket_init(websocketpp::connection_hdl) {
|
||||
m_socket_init = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl) {
|
||||
m_tls_init = std::chrono::high_resolution_clock::now();
|
||||
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void on_fail(websocketpp::connection_hdl hdl) {
|
||||
client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Fail handler" << std::endl;
|
||||
std::cout << con->get_state() << std::endl;
|
||||
std::cout << con->get_local_close_code() << std::endl;
|
||||
std::cout << con->get_local_close_reason() << std::endl;
|
||||
std::cout << con->get_remote_close_code() << std::endl;
|
||||
std::cout << con->get_remote_close_reason() << std::endl;
|
||||
std::cout << con->get_ec() << " - " << con->get_ec().message() << std::endl;
|
||||
}
|
||||
|
||||
void on_open(websocketpp::connection_hdl hdl) {
|
||||
m_open = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.send(hdl, "", websocketpp::frame::opcode::text);
|
||||
}
|
||||
void on_message(websocketpp::connection_hdl hdl, message_ptr) {
|
||||
m_message = std::chrono::high_resolution_clock::now();
|
||||
m_endpoint.close(hdl,websocketpp::close::status::going_away,"");
|
||||
}
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
m_close = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << "Socket Init: " << std::chrono::duration_cast<dur_type>(m_socket_init-m_start).count() << std::endl;
|
||||
std::cout << "TLS Init: " << std::chrono::duration_cast<dur_type>(m_tls_init-m_start).count() << std::endl;
|
||||
std::cout << "Open: " << std::chrono::duration_cast<dur_type>(m_open-m_start).count() << std::endl;
|
||||
std::cout << "Message: " << std::chrono::duration_cast<dur_type>(m_message-m_start).count() << std::endl;
|
||||
std::cout << "Close: " << std::chrono::duration_cast<dur_type>(m_close-m_start).count() << std::endl;
|
||||
}
|
||||
private:
|
||||
client m_endpoint;
|
||||
|
||||
std::chrono::high_resolution_clock::time_point m_start;
|
||||
std::chrono::high_resolution_clock::time_point m_socket_init;
|
||||
std::chrono::high_resolution_clock::time_point m_tls_init;
|
||||
std::chrono::high_resolution_clock::time_point m_open;
|
||||
std::chrono::high_resolution_clock::time_point m_message;
|
||||
std::chrono::high_resolution_clock::time_point m_close;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::string uri = "wss://echo.websocket.org";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
perftest endpoint;
|
||||
endpoint.start(uri);
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
10
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/CMakeLists.txt
vendored
Normal file
10
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (debug_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Debug server example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
174
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/debug_server.cpp
vendored
Normal file
174
3rdparty/cpprestsdk/libs/websocketpp/examples/debug_server/debug_server.cpp
vendored
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/** ====== WARNING ========
|
||||
* This example is presently used as a scratch space. It may or may not be broken
|
||||
* at any given time.
|
||||
*/
|
||||
|
||||
#include <websocketpp/config/debug_asio_no_tls.hpp>
|
||||
|
||||
// Custom logger
|
||||
#include <websocketpp/logger/syslog.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////// Custom Config for debugging custom policies //////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct debug_custom : public websocketpp::config::debug_asio {
|
||||
typedef debug_custom type;
|
||||
typedef debug_asio base;
|
||||
|
||||
typedef base::concurrency_type concurrency_type;
|
||||
|
||||
typedef base::request_type request_type;
|
||||
typedef base::response_type response_type;
|
||||
|
||||
typedef base::message_type message_type;
|
||||
typedef base::con_msg_manager_type con_msg_manager_type;
|
||||
typedef base::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
|
||||
/// Custom Logging policies
|
||||
/*typedef websocketpp::log::syslog<concurrency_type,
|
||||
websocketpp::log::elevel> elog_type;
|
||||
typedef websocketpp::log::syslog<concurrency_type,
|
||||
websocketpp::log::alevel> alog_type;
|
||||
*/
|
||||
typedef base::alog_type alog_type;
|
||||
typedef base::elog_type elog_type;
|
||||
|
||||
typedef base::rng_type rng_type;
|
||||
|
||||
struct transport_config : public base::transport_config {
|
||||
typedef type::concurrency_type concurrency_type;
|
||||
typedef type::alog_type alog_type;
|
||||
typedef type::elog_type elog_type;
|
||||
typedef type::request_type request_type;
|
||||
typedef type::response_type response_type;
|
||||
typedef websocketpp::transport::asio::basic_socket::endpoint
|
||||
socket_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
|
||||
static const long timeout_open_handshake = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef websocketpp::server<debug_custom> server;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef server::message_ptr message_ptr;
|
||||
|
||||
bool validate(server *, websocketpp::connection_hdl) {
|
||||
//sleep(6);
|
||||
return true;
|
||||
}
|
||||
|
||||
void on_http(server* s, websocketpp::connection_hdl hdl) {
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::string res = con->get_request_body();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "got HTTP request with " << res.size() << " bytes of body data.";
|
||||
|
||||
con->set_body(ss.str());
|
||||
con->set_status(websocketpp::http::status_code::ok);
|
||||
}
|
||||
|
||||
void on_fail(server* s, websocketpp::connection_hdl hdl) {
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Fail handler: " << con->get_ec() << " " << con->get_ec().message() << std::endl;
|
||||
}
|
||||
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
std::cout << "Close handler" << std::endl;
|
||||
}
|
||||
|
||||
// Define a callback to handle incoming messages
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
echo_server.set_reuse_addr(true);
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
|
||||
echo_server.set_http_handler(bind(&on_http,&echo_server,::_1));
|
||||
echo_server.set_fail_handler(bind(&on_fail,&echo_server,::_1));
|
||||
echo_server.set_close_handler(&on_close);
|
||||
|
||||
echo_server.set_validate_handler(bind(&validate,&echo_server,::_1));
|
||||
|
||||
// Listen on port 9012
|
||||
echo_server.listen(9012);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (const std::exception & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (websocketpp::lib::error_code e) {
|
||||
std::cout << e.message() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
18
3rdparty/cpprestsdk/libs/websocketpp/examples/dev/SConscript
vendored
Normal file
18
3rdparty/cpprestsdk/libs/websocketpp/examples/dev/SConscript
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
## Main development example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system','timer','chrono'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('main', ["main.cpp"], LIBS = BOOST_LIBS_CPP11)
|
||||
|
||||
Return('prgs')
|
200
3rdparty/cpprestsdk/libs/websocketpp/examples/dev/main.cpp
vendored
Normal file
200
3rdparty/cpprestsdk/libs/websocketpp/examples/dev/main.cpp
vendored
Normal file
|
@ -0,0 +1,200 @@
|
|||
//#ifndef _WEBSOCKETPP_CPP11_STL_
|
||||
// #define _WEBSOCKETPP_CPP11_STL_
|
||||
//#endif
|
||||
|
||||
#include <random>
|
||||
#include <boost/timer/timer.hpp>
|
||||
|
||||
#include <websocketpp/config/core.hpp>
|
||||
|
||||
//#include <websocketpp/security/none.hpp>
|
||||
|
||||
//#include <websocketpp/concurrency/none.hpp>
|
||||
//#include <websocketpp/concurrency/stl.hpp>
|
||||
|
||||
//#include <websocketpp/transport/iostream.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
//typedef websocketpp::concurrency::stl concurrency;
|
||||
//typedef websocketpp::transport::iostream<concurrency> transport;
|
||||
//typedef websocketpp::server<concurrency,transport> server;
|
||||
typedef websocketpp::server<websocketpp::config::core> server;
|
||||
|
||||
/*class handler : public server::handler {
|
||||
bool validate(connection_ptr con) {
|
||||
std::cout << "handler validate" << std::endl;
|
||||
if (con->get_origin() != "http://www.example.com") {
|
||||
con->set_status(websocketpp::http::status_code::FORBIDDEN);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void http(connection_ptr con) {
|
||||
std::cout << "handler http" << std::endl;
|
||||
}
|
||||
|
||||
void on_load(connection_ptr con, ptr old_handler) {
|
||||
std::cout << "handler on_load" << std::endl;
|
||||
}
|
||||
void on_unload(connection_ptr con, ptr new_handler) {
|
||||
std::cout << "handler on_unload" << std::endl;
|
||||
}
|
||||
|
||||
void on_open(connection_ptr con) {
|
||||
std::cout << "handler on_open" << std::endl;
|
||||
}
|
||||
void on_fail(connection_ptr con) {
|
||||
std::cout << "handler on_fail" << std::endl;
|
||||
}
|
||||
|
||||
void on_message(connection_ptr con, message_ptr msg) {
|
||||
std::cout << "handler on_message" << std::endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void on_close(connection_ptr con) {
|
||||
std::cout << "handler on_close" << std::endl;
|
||||
}
|
||||
};*/
|
||||
|
||||
int main() {
|
||||
typedef websocketpp::message_buffer::message<websocketpp::message_buffer::alloc::con_msg_manager>
|
||||
message_type;
|
||||
typedef websocketpp::message_buffer::alloc::con_msg_manager<message_type>
|
||||
con_msg_man_type;
|
||||
|
||||
con_msg_man_type::ptr manager = websocketpp::lib::make_shared<con_msg_man_type>();
|
||||
|
||||
size_t foo = 1024;
|
||||
|
||||
message_type::ptr input = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
message_type::ptr output = manager->get_message(websocketpp::frame::opcode::TEXT,foo);
|
||||
websocketpp::frame::masking_key_type key;
|
||||
|
||||
std::random_device dev;
|
||||
|
||||
|
||||
|
||||
key.i = 0x12345678;
|
||||
|
||||
double m = 18094238402394.0824923;
|
||||
|
||||
/*std::cout << "Some Math" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
for (int i = 0; i < foo; i++) {
|
||||
m /= 1.001;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
std::cout << m << std::endl;
|
||||
|
||||
std::cout << "Random Gen" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
}
|
||||
|
||||
std::cout << "Out of place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(output->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
|
||||
std::cout << "In place accelerated" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::word_mask_exact(reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), reinterpret_cast<uint8_t*>(const_cast<char*>(input->get_raw_payload().data())), foo, key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "Out of place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin(), key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
output->get_raw_payload().replace(0,foo,foo,'\0');
|
||||
std::cout << "In place byte by byte" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
websocketpp::frame::byte_mask(input->get_raw_payload().begin(), input->get_raw_payload().end(), input->get_raw_payload().begin(), key);
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
input->get_raw_payload().replace(0,foo,foo,'a');
|
||||
output->get_raw_payload().replace(0,foo,foo,'b');
|
||||
std::cout << "Copy" << std::endl;
|
||||
{
|
||||
boost::timer::auto_cpu_timer t;
|
||||
|
||||
std::copy(input->get_raw_payload().begin(), input->get_raw_payload().end(), output->get_raw_payload().begin());
|
||||
}
|
||||
|
||||
std::cout << websocketpp::utility::to_hex(input->get_payload().c_str(),20) << std::endl;
|
||||
std::cout << websocketpp::utility::to_hex(output->get_payload().c_str(),20) << std::endl;
|
||||
|
||||
/*server::handler::ptr h(new handler());
|
||||
|
||||
server test_server(h);
|
||||
server::connection_ptr con;
|
||||
|
||||
std::stringstream output;
|
||||
|
||||
test_server.register_ostream(&output);
|
||||
|
||||
con = test_server.get_connection();
|
||||
|
||||
con->start();
|
||||
|
||||
//foo.handle_accept(con,true);
|
||||
|
||||
std::stringstream input;
|
||||
input << "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nOrigin: http://www.example.com\r\n\r\n";
|
||||
//input << "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n";
|
||||
input >> *con;
|
||||
|
||||
std::stringstream input2;
|
||||
input2 << "messageabc2";
|
||||
input2 >> *con;
|
||||
|
||||
std::stringstream input3;
|
||||
input3 << "messageabc3";
|
||||
input3 >> *con;
|
||||
|
||||
std::stringstream input4;
|
||||
input4 << "close";
|
||||
input4 >> *con;
|
||||
|
||||
std::cout << "connection output:" << std::endl;
|
||||
std::cout << output.str() << std::endl;*/
|
||||
}
|
10
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/CMakeLists.txt
vendored
Normal file
10
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (echo_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Main development example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
37
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/echo_handler.hpp
vendored
Normal file
37
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/echo_handler.hpp
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Peter Thorson. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the WebSocket++ Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
#define WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
||||
|
||||
class echo_handler : public server::handler {
|
||||
void on_message(connection_ptr con, std::string msg) {
|
||||
con->write(msg);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // WEBSOCKETPP_ECHO_SERVER_HANDLER_HPP
|
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/echo_server.cpp
vendored
Normal file
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server/echo_server.cpp
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef server::message_ptr message_ptr;
|
||||
|
||||
// Define a callback to handle incoming messages
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
try {
|
||||
// Set logging settings
|
||||
echo_server.set_access_channels(websocketpp::log::alevel::all);
|
||||
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
|
||||
// Listen on port 9002
|
||||
echo_server.listen(9002);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
} catch (...) {
|
||||
std::cout << "other exception" << std::endl;
|
||||
}
|
||||
}
|
15
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/CMakeLists.txt
vendored
Normal file
15
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (echo_server_both)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
endif()
|
24
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/SConscript
vendored
Normal file
24
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/SConscript
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
## Combo plain+tls echo server
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
87
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/echo_server_both.cpp
vendored
Normal file
87
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/echo_server_both.cpp
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include <websocketpp/config/asio.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// define types for two different server endpoints, one for each config we are
|
||||
// using
|
||||
typedef websocketpp::server<websocketpp::config::asio> server_plain;
|
||||
typedef websocketpp::server<websocketpp::config::asio_tls> server_tls;
|
||||
|
||||
// alias some of the bind related functions as they are a bit long
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// type of the ssl context pointer is long so alias it
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
|
||||
// The shared on_message handler takes a template parameter so the function can
|
||||
// resolve any endpoint dependent types like message_ptr or connection_ptr
|
||||
template <typename EndpointType>
|
||||
void on_message(EndpointType* s, websocketpp::connection_hdl hdl,
|
||||
typename EndpointType::message_ptr msg)
|
||||
{
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// No change to TLS init methods from echo_server_tls
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
|
||||
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
ctx->set_password_callback(bind(&get_password));
|
||||
ctx->use_certificate_chain_file("server.pem");
|
||||
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// set up an external io_service to run both endpoints on. This is not
|
||||
// strictly necessary, but simplifies thread management a bit.
|
||||
boost::asio::io_service ios;
|
||||
|
||||
// set up plain endpoint
|
||||
server_plain endpoint_plain;
|
||||
// initialize asio with our external io_service rather than an internal one
|
||||
endpoint_plain.init_asio(&ios);
|
||||
endpoint_plain.set_message_handler(
|
||||
bind(&on_message<server_plain>,&endpoint_plain,::_1,::_2));
|
||||
endpoint_plain.listen(80);
|
||||
endpoint_plain.start_accept();
|
||||
|
||||
// set up tls endpoint
|
||||
server_tls endpoint_tls;
|
||||
endpoint_tls.init_asio(&ios);
|
||||
endpoint_tls.set_message_handler(
|
||||
bind(&on_message<server_tls>,&endpoint_tls,::_1,::_2));
|
||||
// TLS endpoint has an extra handler for the tls init
|
||||
endpoint_tls.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
// tls endpoint listens on a different port
|
||||
endpoint_tls.listen(443);
|
||||
endpoint_tls.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop running both endpoints
|
||||
ios.run();
|
||||
}
|
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/server.pem
vendored
Normal file
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_both/server.pem
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,A0ED66EF872A48A9
|
||||
|
||||
gXuvKojXzApVhhPVNdRliiajbC4PtwQG5c8TA7JADLgwOR7o9t6KtXEr37bDRpvB
|
||||
9aO9P+SJaK5OOp3XKPGthOdqv+tvCRTlmzmC8GjPLBX389DWT2xoGu7JkGwDtdSm
|
||||
rnF49Rlp5bfjpACk5xKNiKeDo1CWfeEJzw9Kto0g+5eMaEdors64oPzjXs3geA2g
|
||||
TxCJSHv9qSX6++pCLKKCUTbyzidAxV/Zb0AAubt5V40QKqX4HhSwwstFnTaX3tlb
|
||||
3QOdY+y04VIkM6d7qN5W8M7NzRkMpZ1qBpQcUMpkhQcRzWP2wub5AAff9D2GntRd
|
||||
4Dz1vn3u41U3Okdr0CNj+iH7byCzuokoAhk6ZQEN6WB+GTpGgfBXdtUZrfpb0MKm
|
||||
UNYP5AF2AmUqJRXhViTDVtu/V2tHF3LGuNT+W2Dz+spFZEq0byEO0N858eR0dikc
|
||||
6jOASvNQbSwD0+mkgBC1gXKKU3ngj2gpJUwljeACdWFd8N2egrZfyI05CmX7vPNC
|
||||
NXbs7k2buWNdjP4/D8IM+HDVidWzQa/kG/qokXKqllem9Egg37lUucwnP3cX2/Hw
|
||||
U2mfaBWzeZtqc+GqRp08rYIql+Reai3sUYlQMnNk01prVY47UQb+dxuqjaxGV5Xx
|
||||
Xkx0s2mfQnNRjL4S7Hjhqelufi6GpkCQ2EGsPpA+6K1ztZ0ame9Q2BE1SXeM/6vU
|
||||
rxT5nRrCxueyXAyQSGcqMX9//gSeK8WWBqG/c1IAMVDa0NWrJeOJhSziE+ta3B0m
|
||||
bHAPBY6vh0iB3lLdRlbUOPbC6R1TpxMOs+6Vbs2+OTifFpvOVymEoZq/nroyg68P
|
||||
vn5uCKogwWA7o8EArf/UTlIwWJmH9bgILdZKld4wMel2HQg16RDzm+mEXAJi52a/
|
||||
FC+fgfphdxltmUJ+rqOyR4AHULjaTWUQqTIB6sdlzgmES1nXAiE71zX//KFqomar
|
||||
O60SPPk3C1bs0x5DsvmGJa8SIfDhyd+D7NPyqwEKqrZsaotYGklNkfqxa6pa8mrc
|
||||
ejxquW1PK4FvBk26+osu5a90Jih0PcQM7DUMMr2WHdTiMSXWAiK2ToYF8Itt25Qv
|
||||
Cd0CsSYw9CJkXNr1u1+mObheaY9QYOmztnSJLy4ZO2JsMhqNwuAueIcwmhXOREq7
|
||||
kzlnGMgJcuSeAS/OBNj8Zgx0c7QQ0kzc+YmnOCsqoMtPsu/CsXJ4iJiM3Tki/2jT
|
||||
bywrTiQwE6R3a/87GREOREX+WLicZBWX3k9/4tBL5XSe1p5wPpuIRQUDvAGNfNHP
|
||||
JN7kujDF4SehilF1qtvCygAwvxHFDj+EwhXKNDKJzoZZIM15rAk3k92n2j6nz1qH
|
||||
a3xOU05yydOlO6F6w51I1QoDddmkzCRNB0TeO3D6rekHsCK1aDWmC+qRcm2ZFtVz
|
||||
sY6fdZN2NEmMQokIh9Opi1f8CSYSizPESMzdu2SF0xVO9n/IGIkn1ksK04O2BZo0
|
||||
X3LBPHLfCRsQNY1eF17bj07fYU2oPZKs/XzJiwxkqK6LFvpeAVaYrtg9fqRO/UVe
|
||||
QhUIj3BL550ocEpa15xLehLrmwzYiW5zwGjSHQ4EgZluGLCwyKGTh4QswEJRA9Rt
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE0DCCA7igAwIBAgIJAM5MuKJezXq0MA0GCSqGSIb3DQEBBQUAMIGgMQswCQYD
|
||||
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xGDAW
|
||||
BgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0KysxFjAU
|
||||
BgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3RlckB6
|
||||
YXBob3lkLmNvbTAeFw0xMTExMTUyMTIwMDZaFw0xMjExMTQyMTIwMDZaMIGgMQsw
|
||||
CQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28x
|
||||
GDAWBgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0Kysx
|
||||
FjAUBgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3Rl
|
||||
ckB6YXBob3lkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANR0
|
||||
tdwAnIB8I9qRZ7QbzEWY95RpM7GIn0u/9oH90PzdHiE0rXSkKT+yw3XUzH0iw5t0
|
||||
5dEwSC+srSP5Vm4cA6kXc94agVVaPW89tGcdP4fHptCruSrzQsDXELCPl5UUvMpA
|
||||
YUcGisdXYPN/EeOoqb9wKWxoW5mREsyyeWWS89fYN5qU/d0QpbSvEWghqLbL/ZS2
|
||||
hOlXT9LufOeA+vHiV1/T/h5xC7ecIH02YDQw1EnqxbPmkLPcWThztLS9FiufNDRM
|
||||
Rhcoaj2b9VDHvDwdbeA0T5v5qNdG34LaapYOelxzQMOtM0f9Dgqehodyxl2qm9mR
|
||||
lq432dlOEzDnVCPNHwECAwEAAaOCAQkwggEFMB0GA1UdDgQWBBTTPKfNMnKOykhv
|
||||
+vKS7vql5JsMyzCB1QYDVR0jBIHNMIHKgBTTPKfNMnKOykhv+vKS7vql5JsMy6GB
|
||||
pqSBozCBoDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQH
|
||||
EwdDaGljYWdvMRgwFgYDVQQKEw9aYXBob3lkIFN0dWRpb3MxFDASBgNVBAsTC1dl
|
||||
YlNvY2tldCsrMRYwFAYDVQQDEw1QZXRlciBUaG9yc29uMSQwIgYJKoZIhvcNAQkB
|
||||
FhV3ZWJtYXN0ZXJAemFwaG95ZC5jb22CCQDOTLiiXs16tDAMBgNVHRMEBTADAQH/
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQB+SH0s/hrv5VYqgX6SNLzxdSLvCVsUkCdTpxwY
|
||||
wOJ84XmYcXDMhKDtZqLtOtN6pfEwVusFlC9mkieuunztCnWNmsSG83RuljJPjFSi
|
||||
1d4Id4bKEQkQ4cfnjoHKivRrViWLnxuNnLzC6tpyGH/35kKWhhr6T58AXerFgVw3
|
||||
mHvLPTr1DuhdAZA0ZuvuseVAFFAjI3RetSySwHJE3ak8KswDVfLi6E3XxMVsIWTS
|
||||
/iFsC2WwoZQlljya2V/kRYIhu+uCdqJ01wunn2BvmURPSgr4GTBF0FQ9JGpNbXxM
|
||||
TAU7oQJgyFc5sCcuEgPTO0dWVQTvdZVgay4tkmduKDRkmJBF
|
||||
-----END CERTIFICATE-----
|
15
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/CMakeLists.txt
vendored
Normal file
15
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
|
||||
init_target (echo_server_tls)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
link_openssl()
|
||||
final_target ()
|
||||
endif()
|
24
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/SConscript
vendored
Normal file
24
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/SConscript
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
## Main development example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
Import('tls_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env_cpp11.Program('echo_server_tls', ["echo_server_tls.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
|
||||
prgs += env.Program('echo_server_tls', ["echo_server_tls.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
73
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/echo_server_tls.cpp
vendored
Normal file
73
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/echo_server_tls.cpp
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include <websocketpp/config/asio.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio_tls> server;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef websocketpp::config::asio::message_type::ptr message_ptr;
|
||||
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
|
||||
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
std::cout << "on_message called with hdl: " << hdl.lock().get()
|
||||
<< " and message: " << msg->get_payload()
|
||||
<< std::endl;
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
std::cout << "Echo failed because: " << e
|
||||
<< "(" << e.message() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_password() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
|
||||
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
|
||||
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
|
||||
|
||||
try {
|
||||
ctx->set_options(boost::asio::ssl::context::default_workarounds |
|
||||
boost::asio::ssl::context::no_sslv2 |
|
||||
boost::asio::ssl::context::no_sslv3 |
|
||||
boost::asio::ssl::context::single_dh_use);
|
||||
ctx->set_password_callback(bind(&get_password));
|
||||
ctx->use_certificate_chain_file("server.pem");
|
||||
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
|
||||
} catch (std::exception& e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Create a server endpoint
|
||||
server echo_server;
|
||||
|
||||
// Initialize ASIO
|
||||
echo_server.init_asio();
|
||||
|
||||
// Register our message handler
|
||||
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
|
||||
echo_server.set_tls_init_handler(bind(&on_tls_init,::_1));
|
||||
|
||||
|
||||
// Listen on port 9002
|
||||
echo_server.listen(9002);
|
||||
|
||||
// Start the server accept loop
|
||||
echo_server.start_accept();
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
echo_server.run();
|
||||
|
||||
}
|
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/server.pem
vendored
Normal file
58
3rdparty/cpprestsdk/libs/websocketpp/examples/echo_server_tls/server.pem
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,A0ED66EF872A48A9
|
||||
|
||||
gXuvKojXzApVhhPVNdRliiajbC4PtwQG5c8TA7JADLgwOR7o9t6KtXEr37bDRpvB
|
||||
9aO9P+SJaK5OOp3XKPGthOdqv+tvCRTlmzmC8GjPLBX389DWT2xoGu7JkGwDtdSm
|
||||
rnF49Rlp5bfjpACk5xKNiKeDo1CWfeEJzw9Kto0g+5eMaEdors64oPzjXs3geA2g
|
||||
TxCJSHv9qSX6++pCLKKCUTbyzidAxV/Zb0AAubt5V40QKqX4HhSwwstFnTaX3tlb
|
||||
3QOdY+y04VIkM6d7qN5W8M7NzRkMpZ1qBpQcUMpkhQcRzWP2wub5AAff9D2GntRd
|
||||
4Dz1vn3u41U3Okdr0CNj+iH7byCzuokoAhk6ZQEN6WB+GTpGgfBXdtUZrfpb0MKm
|
||||
UNYP5AF2AmUqJRXhViTDVtu/V2tHF3LGuNT+W2Dz+spFZEq0byEO0N858eR0dikc
|
||||
6jOASvNQbSwD0+mkgBC1gXKKU3ngj2gpJUwljeACdWFd8N2egrZfyI05CmX7vPNC
|
||||
NXbs7k2buWNdjP4/D8IM+HDVidWzQa/kG/qokXKqllem9Egg37lUucwnP3cX2/Hw
|
||||
U2mfaBWzeZtqc+GqRp08rYIql+Reai3sUYlQMnNk01prVY47UQb+dxuqjaxGV5Xx
|
||||
Xkx0s2mfQnNRjL4S7Hjhqelufi6GpkCQ2EGsPpA+6K1ztZ0ame9Q2BE1SXeM/6vU
|
||||
rxT5nRrCxueyXAyQSGcqMX9//gSeK8WWBqG/c1IAMVDa0NWrJeOJhSziE+ta3B0m
|
||||
bHAPBY6vh0iB3lLdRlbUOPbC6R1TpxMOs+6Vbs2+OTifFpvOVymEoZq/nroyg68P
|
||||
vn5uCKogwWA7o8EArf/UTlIwWJmH9bgILdZKld4wMel2HQg16RDzm+mEXAJi52a/
|
||||
FC+fgfphdxltmUJ+rqOyR4AHULjaTWUQqTIB6sdlzgmES1nXAiE71zX//KFqomar
|
||||
O60SPPk3C1bs0x5DsvmGJa8SIfDhyd+D7NPyqwEKqrZsaotYGklNkfqxa6pa8mrc
|
||||
ejxquW1PK4FvBk26+osu5a90Jih0PcQM7DUMMr2WHdTiMSXWAiK2ToYF8Itt25Qv
|
||||
Cd0CsSYw9CJkXNr1u1+mObheaY9QYOmztnSJLy4ZO2JsMhqNwuAueIcwmhXOREq7
|
||||
kzlnGMgJcuSeAS/OBNj8Zgx0c7QQ0kzc+YmnOCsqoMtPsu/CsXJ4iJiM3Tki/2jT
|
||||
bywrTiQwE6R3a/87GREOREX+WLicZBWX3k9/4tBL5XSe1p5wPpuIRQUDvAGNfNHP
|
||||
JN7kujDF4SehilF1qtvCygAwvxHFDj+EwhXKNDKJzoZZIM15rAk3k92n2j6nz1qH
|
||||
a3xOU05yydOlO6F6w51I1QoDddmkzCRNB0TeO3D6rekHsCK1aDWmC+qRcm2ZFtVz
|
||||
sY6fdZN2NEmMQokIh9Opi1f8CSYSizPESMzdu2SF0xVO9n/IGIkn1ksK04O2BZo0
|
||||
X3LBPHLfCRsQNY1eF17bj07fYU2oPZKs/XzJiwxkqK6LFvpeAVaYrtg9fqRO/UVe
|
||||
QhUIj3BL550ocEpa15xLehLrmwzYiW5zwGjSHQ4EgZluGLCwyKGTh4QswEJRA9Rt
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE0DCCA7igAwIBAgIJAM5MuKJezXq0MA0GCSqGSIb3DQEBBQUAMIGgMQswCQYD
|
||||
VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xGDAW
|
||||
BgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0KysxFjAU
|
||||
BgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3RlckB6
|
||||
YXBob3lkLmNvbTAeFw0xMTExMTUyMTIwMDZaFw0xMjExMTQyMTIwMDZaMIGgMQsw
|
||||
CQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28x
|
||||
GDAWBgNVBAoTD1phcGhveWQgU3R1ZGlvczEUMBIGA1UECxMLV2ViU29ja2V0Kysx
|
||||
FjAUBgNVBAMTDVBldGVyIFRob3Jzb24xJDAiBgkqhkiG9w0BCQEWFXdlYm1hc3Rl
|
||||
ckB6YXBob3lkLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANR0
|
||||
tdwAnIB8I9qRZ7QbzEWY95RpM7GIn0u/9oH90PzdHiE0rXSkKT+yw3XUzH0iw5t0
|
||||
5dEwSC+srSP5Vm4cA6kXc94agVVaPW89tGcdP4fHptCruSrzQsDXELCPl5UUvMpA
|
||||
YUcGisdXYPN/EeOoqb9wKWxoW5mREsyyeWWS89fYN5qU/d0QpbSvEWghqLbL/ZS2
|
||||
hOlXT9LufOeA+vHiV1/T/h5xC7ecIH02YDQw1EnqxbPmkLPcWThztLS9FiufNDRM
|
||||
Rhcoaj2b9VDHvDwdbeA0T5v5qNdG34LaapYOelxzQMOtM0f9Dgqehodyxl2qm9mR
|
||||
lq432dlOEzDnVCPNHwECAwEAAaOCAQkwggEFMB0GA1UdDgQWBBTTPKfNMnKOykhv
|
||||
+vKS7vql5JsMyzCB1QYDVR0jBIHNMIHKgBTTPKfNMnKOykhv+vKS7vql5JsMy6GB
|
||||
pqSBozCBoDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQH
|
||||
EwdDaGljYWdvMRgwFgYDVQQKEw9aYXBob3lkIFN0dWRpb3MxFDASBgNVBAsTC1dl
|
||||
YlNvY2tldCsrMRYwFAYDVQQDEw1QZXRlciBUaG9yc29uMSQwIgYJKoZIhvcNAQkB
|
||||
FhV3ZWJtYXN0ZXJAemFwaG95ZC5jb22CCQDOTLiiXs16tDAMBgNVHRMEBTADAQH/
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQB+SH0s/hrv5VYqgX6SNLzxdSLvCVsUkCdTpxwY
|
||||
wOJ84XmYcXDMhKDtZqLtOtN6pfEwVusFlC9mkieuunztCnWNmsSG83RuljJPjFSi
|
||||
1d4Id4bKEQkQ4cfnjoHKivRrViWLnxuNnLzC6tpyGH/35kKWhhr6T58AXerFgVw3
|
||||
mHvLPTr1DuhdAZA0ZuvuseVAFFAjI3RetSySwHJE3ak8KswDVfLi6E3XxMVsIWTS
|
||||
/iFsC2WwoZQlljya2V/kRYIhu+uCdqJ01wunn2BvmURPSgr4GTBF0FQ9JGpNbXxM
|
||||
TAU7oQJgyFc5sCcuEgPTO0dWVQTvdZVgay4tkmduKDRkmJBF
|
||||
-----END CERTIFICATE-----
|
87
3rdparty/cpprestsdk/libs/websocketpp/examples/enriched_storage/enriched_storage.cpp
vendored
Normal file
87
3rdparty/cpprestsdk/libs/websocketpp/examples/enriched_storage/enriched_storage.cpp
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
#include <iostream>
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
struct connection_data {
|
||||
int sessionid;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct custom_config : public websocketpp::config::asio {
|
||||
// pull default settings from our core config
|
||||
typedef websocketpp::config::asio core;
|
||||
|
||||
typedef core::concurrency_type concurrency_type;
|
||||
typedef core::request_type request_type;
|
||||
typedef core::response_type response_type;
|
||||
typedef core::message_type message_type;
|
||||
typedef core::con_msg_manager_type con_msg_manager_type;
|
||||
typedef core::endpoint_msg_manager_type endpoint_msg_manager_type;
|
||||
typedef core::alog_type alog_type;
|
||||
typedef core::elog_type elog_type;
|
||||
typedef core::rng_type rng_type;
|
||||
typedef core::transport_type transport_type;
|
||||
typedef core::endpoint_base endpoint_base;
|
||||
|
||||
// Set a custom connection_base class
|
||||
typedef connection_data connection_base;
|
||||
};
|
||||
|
||||
typedef websocketpp::server<custom_config> server;
|
||||
typedef server::connection_ptr connection_ptr;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
class print_server {
|
||||
public:
|
||||
print_server() : m_next_sessionid(1) {
|
||||
m_server.init_asio();
|
||||
|
||||
m_server.set_open_handler(bind(&print_server::on_open,this,::_1));
|
||||
m_server.set_close_handler(bind(&print_server::on_close,this,::_1));
|
||||
m_server.set_message_handler(bind(&print_server::on_message,this,::_1,::_2));
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
connection_ptr con = m_server.get_con_from_hdl(hdl);
|
||||
|
||||
con->sessionid = m_next_sessionid++;
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
connection_ptr con = m_server.get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Closing connection " << con->name
|
||||
<< " with sessionid " << con->sessionid << std::endl;
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
connection_ptr con = m_server.get_con_from_hdl(hdl);
|
||||
|
||||
if (con->name == "") {
|
||||
con->name = msg->get_payload();
|
||||
std::cout << "Setting name of connection with sessionid "
|
||||
<< con->sessionid << " to " << con->name << std::endl;
|
||||
} else {
|
||||
std::cout << "Got a message from connection " << con->name
|
||||
<< " with sessionid " << con->sessionid << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
int m_next_sessionid;
|
||||
server m_server;
|
||||
};
|
||||
|
||||
int main() {
|
||||
print_server server;
|
||||
server.run(9002);
|
||||
}
|
42
3rdparty/cpprestsdk/libs/websocketpp/examples/handler_switch/handler_switch.cpp
vendored
Normal file
42
3rdparty/cpprestsdk/libs/websocketpp/examples/handler_switch/handler_switch.cpp
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
using websocketpp::lib::ref;
|
||||
|
||||
void custom_on_msg(server & s, connection_hdl hdl, server::message_ptr msg) {
|
||||
std::cout << "Message sent to custom handler" << std::endl;
|
||||
}
|
||||
|
||||
void default_on_msg(server & s, connection_hdl hdl, server::message_ptr msg) {
|
||||
std::cout << "Message sent to default handler" << std::endl;
|
||||
|
||||
if (msg->get_payload() == "upgrade") {
|
||||
// Upgrade our connection_hdl to a full connection_ptr
|
||||
server::connection_ptr con = s.get_con_from_hdl(hdl);
|
||||
|
||||
// Change the on message handler for this connection only to
|
||||
// custom_on_mesage
|
||||
con->set_message_handler(bind(&custom_on_msg,ref(s),::_1,::_2));
|
||||
std::cout << "Upgrading connection to custom handler" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
server s;
|
||||
|
||||
s.set_message_handler(bind(&default_on_msg,ref(s),::_1,::_2));
|
||||
|
||||
s.init_asio();
|
||||
s.listen(9002);
|
||||
s.start_accept();
|
||||
|
||||
s.run();
|
||||
}
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/iostream_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/iostream_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## iostream server example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('iostream_server', ["iostream_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('iostream_server', ["iostream_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
89
3rdparty/cpprestsdk/libs/websocketpp/examples/iostream_server/iostream_server.cpp
vendored
Normal file
89
3rdparty/cpprestsdk/libs/websocketpp/examples/iostream_server/iostream_server.cpp
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <websocketpp/config/core.hpp>
|
||||
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::core> server;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef server::message_ptr message_ptr;
|
||||
|
||||
// Define a callback to handle incoming messages
|
||||
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
if (msg->get_opcode() == websocketpp::frame::opcode::text) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Text Message Received: "+msg->get_payload());
|
||||
} else {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Binary Message Received: "+websocketpp::utility::to_hex(msg->get_payload()));
|
||||
}
|
||||
|
||||
try {
|
||||
s->send(hdl, msg->get_payload(), msg->get_opcode());
|
||||
} catch (const websocketpp::lib::error_code& e) {
|
||||
s->get_alog().write(websocketpp::log::alevel::app,
|
||||
"Echo Failed: "+e.message());
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
server s;
|
||||
std::ofstream log;
|
||||
|
||||
try {
|
||||
// set up access channels to only log interesting things
|
||||
s.clear_access_channels(websocketpp::log::alevel::all);
|
||||
s.set_access_channels(websocketpp::log::alevel::connect);
|
||||
s.set_access_channels(websocketpp::log::alevel::disconnect);
|
||||
s.set_access_channels(websocketpp::log::alevel::app);
|
||||
|
||||
// Log to a file rather than stdout, as we are using stdout for real
|
||||
// output
|
||||
log.open("output.log");
|
||||
s.get_alog().set_ostream(&log);
|
||||
s.get_elog().set_ostream(&log);
|
||||
|
||||
// print all output to stdout
|
||||
s.register_ostream(&std::cout);
|
||||
|
||||
// Register our message handler
|
||||
s.set_message_handler(bind(&on_message,&s,::_1,::_2));
|
||||
|
||||
server::connection_ptr con = s.get_connection();
|
||||
|
||||
con->start();
|
||||
|
||||
// C++ iostream's don't support the idea of asynchronous i/o. As such
|
||||
// there are two input strategies demonstrated here. Buffered I/O will
|
||||
// read from stdin in chunks until EOF. This works very well for
|
||||
// replaying canned connections as would be done in automated testing.
|
||||
//
|
||||
// If the server is being used live however, assuming input is being
|
||||
// piped from elsewhere in realtime, this strategy will result in small
|
||||
// messages being buffered forever. The non-buffered strategy below
|
||||
// reads characters from stdin one at a time. This is inefficient and
|
||||
// for more serious uses should be replaced with a platform specific
|
||||
// asyncronous i/o technique like select, poll, IOCP, etc
|
||||
bool buffered_io = false;
|
||||
|
||||
if (buffered_io) {
|
||||
std::cin >> *con;
|
||||
con->eof();
|
||||
} else {
|
||||
char a;
|
||||
while(std::cin.get(a)) {
|
||||
con->read_some(&a,1);
|
||||
}
|
||||
con->eof();
|
||||
}
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
log.close();
|
||||
}
|
10
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/CMakeLists.txt
vendored
Normal file
10
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (print_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Print server example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
22
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/print_server.cpp
vendored
Normal file
22
3rdparty/cpprestsdk/libs/websocketpp/examples/print_server/print_server.cpp
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
void on_message(websocketpp::connection_hdl, server::message_ptr msg) {
|
||||
std::cout << msg->get_payload() << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
server print_server;
|
||||
|
||||
print_server.set_message_handler(&on_message);
|
||||
|
||||
print_server.init_asio();
|
||||
print_server.listen(9002);
|
||||
print_server.start_accept();
|
||||
|
||||
print_server.run();
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#include <set>
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
class broadcast_server {
|
||||
public:
|
||||
broadcast_server() {
|
||||
m_server.init_asio();
|
||||
|
||||
m_server.set_open_handler(bind(&broadcast_server::on_open,this,::_1));
|
||||
m_server.set_close_handler(bind(&broadcast_server::on_close,this,::_1));
|
||||
m_server.set_message_handler(bind(&broadcast_server::on_message,this,::_1,::_2));
|
||||
}
|
||||
|
||||
void on_open(connection_hdl hdl) {
|
||||
m_connections.insert(hdl);
|
||||
}
|
||||
|
||||
void on_close(connection_hdl hdl) {
|
||||
m_connections.erase(hdl);
|
||||
}
|
||||
|
||||
void on_message(connection_hdl hdl, server::message_ptr msg) {
|
||||
for (auto it : m_connections) {
|
||||
m_server.send(it,msg);
|
||||
}
|
||||
}
|
||||
|
||||
void run(uint16_t port) {
|
||||
m_server.listen(port);
|
||||
m_server.start_accept();
|
||||
m_server.run();
|
||||
}
|
||||
private:
|
||||
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
|
||||
|
||||
server m_server;
|
||||
con_list m_connections;
|
||||
};
|
||||
|
||||
int main() {
|
||||
broadcast_server server;
|
||||
server.run(9002);
|
||||
}
|
11
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/CMakeLists.txt
vendored
Normal file
11
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (sip_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
||||
|
22
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/README.txt
vendored
Normal file
22
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/README.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
|
||||
Checkout the project from git
|
||||
|
||||
At the top level, run cmake:
|
||||
|
||||
cmake -G 'Unix Makefiles' \
|
||||
-D BUILD_EXAMPLES=ON \
|
||||
-D WEBSOCKETPP_ROOT=/tmp/cm1 \
|
||||
-D ENABLE_CPP11=OFF .
|
||||
|
||||
and then make the example:
|
||||
|
||||
make -C examples/sip_client
|
||||
|
||||
Now run it:
|
||||
|
||||
bin/sip_client ws://ws-server:80
|
||||
|
||||
It has been tested against the repro SIP proxy from reSIProcate
|
||||
|
||||
http://www.resiprocate.org/WebRTC_and_SIP_Over_WebSockets
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## SIP client example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is avaliable build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
84
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/sip_client.cpp
vendored
Normal file
84
3rdparty/cpprestsdk/libs/websocketpp/examples/sip_client/sip_client.cpp
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
#include <condition_variable>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
|
||||
// pull out the type of messages sent by our config
|
||||
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
|
||||
|
||||
// Create a server endpoint
|
||||
client sip_client;
|
||||
|
||||
|
||||
bool received;
|
||||
|
||||
void on_open(client* c, websocketpp::connection_hdl hdl) {
|
||||
// now it is safe to use the connection
|
||||
std::cout << "connection ready" << std::endl;
|
||||
|
||||
received=false;
|
||||
// Send a SIP OPTIONS message to the server:
|
||||
std::string SIP_msg="OPTIONS sip:carol@chicago.com SIP/2.0\r\nVia: SIP/2.0/WS df7jal23ls0d.invalid;rport;branch=z9hG4bKhjhs8ass877\r\nMax-Forwards: 70\r\nTo: <sip:carol@chicago.com>\r\nFrom: Alice <sip:alice@atlanta.com>;tag=1928301774\r\nCall-ID: a84b4c76e66710\r\nCSeq: 63104 OPTIONS\r\nContact: <sip:alice@pc33.atlanta.com>\r\nAccept: application/sdp\r\nContent-Length: 0\r\n\r\n";
|
||||
sip_client.send(hdl, SIP_msg.c_str(), websocketpp::frame::opcode::text);
|
||||
}
|
||||
|
||||
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
|
||||
client::connection_ptr con = sip_client.get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Received a reply:" << std::endl;
|
||||
fwrite(msg->get_payload().c_str(), msg->get_payload().size(), 1, stdout);
|
||||
received=true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
std::string uri = "ws://localhost:9001";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
try {
|
||||
// We expect there to be a lot of errors, so suppress them
|
||||
sip_client.clear_access_channels(websocketpp::log::alevel::all);
|
||||
sip_client.clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// Initialize ASIO
|
||||
sip_client.init_asio();
|
||||
|
||||
// Register our handlers
|
||||
sip_client.set_open_handler(bind(&on_open,&sip_client,::_1));
|
||||
sip_client.set_message_handler(bind(&on_message,&sip_client,::_1,::_2));
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = sip_client.get_connection(uri, ec);
|
||||
|
||||
// Specify the SIP subprotocol:
|
||||
con->add_subprotocol("sip");
|
||||
|
||||
sip_client.connect(con);
|
||||
|
||||
// Start the ASIO io_service run loop
|
||||
sip_client.run();
|
||||
|
||||
while(!received) {
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
|
||||
}
|
||||
|
||||
std::cout << "done" << std::endl;
|
||||
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/subprotocol_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/subprotocol_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Main development example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('subprotocol_server', ["subprotocol_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('subprotocol_server', ["subprotocol_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
48
3rdparty/cpprestsdk/libs/websocketpp/examples/subprotocol_server/subprotocol_server.cpp
vendored
Normal file
48
3rdparty/cpprestsdk/libs/websocketpp/examples/subprotocol_server/subprotocol_server.cpp
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
typedef websocketpp::server<websocketpp::config::asio> server;
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::placeholders::_2;
|
||||
using websocketpp::lib::bind;
|
||||
using websocketpp::lib::ref;
|
||||
|
||||
|
||||
bool validate(server & s, connection_hdl hdl) {
|
||||
server::connection_ptr con = s.get_con_from_hdl(hdl);
|
||||
|
||||
std::cout << "Cache-Control: " << con->get_request_header("Cache-Control") << std::endl;
|
||||
|
||||
const std::vector<std::string> & subp_requests = con->get_requested_subprotocols();
|
||||
std::vector<std::string>::const_iterator it;
|
||||
|
||||
for (it = subp_requests.begin(); it != subp_requests.end(); ++it) {
|
||||
std::cout << "Requested: " << *it << std::endl;
|
||||
}
|
||||
|
||||
if (subp_requests.size() > 0) {
|
||||
con->select_subprotocol(subp_requests[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
server s;
|
||||
|
||||
s.set_validate_handler(bind(&validate,ref(s),::_1));
|
||||
|
||||
s.init_asio();
|
||||
s.listen(9005);
|
||||
s.start_accept();
|
||||
|
||||
s.run();
|
||||
} catch (websocketpp::exception const & e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
10
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/CMakeLists.txt
vendored
Normal file
10
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (telemetry_client)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Telemetry client example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('telemetry_client', ["telemetry_client.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('telemetry_client', ["telemetry_client.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
156
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/telemetry_client.cpp
vendored
Normal file
156
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_client/telemetry_client.cpp
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
#include <websocketpp/config/asio_no_tls_client.hpp>
|
||||
#include <websocketpp/client.hpp>
|
||||
|
||||
// This header pulls in the WebSocket++ abstracted thread support that will
|
||||
// select between boost::thread and std::thread based on how the build system
|
||||
// is configured.
|
||||
#include <websocketpp/common/thread.hpp>
|
||||
|
||||
/**
|
||||
* The telemetry client connects to a WebSocket server and sends a message every
|
||||
* second containing an integer count. This example can be used as the basis for
|
||||
* programs where a client connects and pushes data for logging, stress/load
|
||||
* testing, etc.
|
||||
*/
|
||||
class telemetry_client {
|
||||
public:
|
||||
typedef websocketpp::client<websocketpp::config::asio_client> client;
|
||||
typedef websocketpp::lib::lock_guard<websocketpp::lib::mutex> scoped_lock;
|
||||
|
||||
telemetry_client() : m_open(false),m_done(false) {
|
||||
// set up access channels to only log interesting things
|
||||
m_client.clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_client.set_access_channels(websocketpp::log::alevel::connect);
|
||||
m_client.set_access_channels(websocketpp::log::alevel::disconnect);
|
||||
m_client.set_access_channels(websocketpp::log::alevel::app);
|
||||
|
||||
// Initialize the Asio transport policy
|
||||
m_client.init_asio();
|
||||
|
||||
// Bind the handlers we are using
|
||||
using websocketpp::lib::placeholders::_1;
|
||||
using websocketpp::lib::bind;
|
||||
m_client.set_open_handler(bind(&telemetry_client::on_open,this,::_1));
|
||||
m_client.set_close_handler(bind(&telemetry_client::on_close,this,::_1));
|
||||
m_client.set_fail_handler(bind(&telemetry_client::on_fail,this,::_1));
|
||||
}
|
||||
|
||||
// This method will block until the connection is complete
|
||||
void run(const std::string & uri) {
|
||||
// Create a new connection to the given URI
|
||||
websocketpp::lib::error_code ec;
|
||||
client::connection_ptr con = m_client.get_connection(uri, ec);
|
||||
if (ec) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Get Connection Error: "+ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab a handle for this connection so we can talk to it in a thread
|
||||
// safe manor after the event loop starts.
|
||||
m_hdl = con->get_handle();
|
||||
|
||||
// Queue the connection. No DNS queries or network connections will be
|
||||
// made until the io_service event loop is run.
|
||||
m_client.connect(con);
|
||||
|
||||
// Create a thread to run the ASIO io_service event loop
|
||||
websocketpp::lib::thread asio_thread(&client::run, &m_client);
|
||||
|
||||
// Create a thread to run the telemetry loop
|
||||
websocketpp::lib::thread telemetry_thread(&telemetry_client::telemetry_loop,this);
|
||||
|
||||
asio_thread.join();
|
||||
telemetry_thread.join();
|
||||
}
|
||||
|
||||
// The open handler will signal that we are ready to start sending telemetry
|
||||
void on_open(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection opened, starting telemetry!");
|
||||
|
||||
scoped_lock guard(m_lock);
|
||||
m_open = true;
|
||||
}
|
||||
|
||||
// The close handler will signal that we should stop sending telemetry
|
||||
void on_close(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection closed, stopping telemetry!");
|
||||
|
||||
scoped_lock guard(m_lock);
|
||||
m_done = true;
|
||||
}
|
||||
|
||||
// The fail handler will signal that we should stop sending telemetry
|
||||
void on_fail(websocketpp::connection_hdl) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Connection failed, stopping telemetry!");
|
||||
|
||||
scoped_lock guard(m_lock);
|
||||
m_done = true;
|
||||
}
|
||||
|
||||
void telemetry_loop() {
|
||||
uint64_t count = 0;
|
||||
std::stringstream val;
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
while(1) {
|
||||
bool wait = false;
|
||||
|
||||
{
|
||||
scoped_lock guard(m_lock);
|
||||
// If the connection has been closed, stop generating telemetry
|
||||
if (m_done) {break;}
|
||||
|
||||
// If the connection hasn't been opened yet wait a bit and retry
|
||||
if (!m_open) {
|
||||
wait = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
val.str("");
|
||||
val << "count is " << count++;
|
||||
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app, val.str());
|
||||
m_client.send(m_hdl,val.str(),websocketpp::frame::opcode::text,ec);
|
||||
|
||||
// The most likely error that we will get is that the connection is
|
||||
// not in the right state. Usually this means we tried to send a
|
||||
// message to a connection that was closed or in the process of
|
||||
// closing. While many errors here can be easily recovered from,
|
||||
// in this simple example, we'll stop the telemetry loop.
|
||||
if (ec) {
|
||||
m_client.get_alog().write(websocketpp::log::alevel::app,
|
||||
"Send Error: "+ec.message());
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
private:
|
||||
client m_client;
|
||||
websocketpp::connection_hdl m_hdl;
|
||||
websocketpp::lib::mutex m_lock;
|
||||
bool m_open;
|
||||
bool m_done;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
telemetry_client c;
|
||||
|
||||
std::string uri = "ws://localhost:9002";
|
||||
|
||||
if (argc == 2) {
|
||||
uri = argv[1];
|
||||
}
|
||||
|
||||
c.run(uri);
|
||||
}
|
10
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/CMakeLists.txt
vendored
Normal file
10
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
file (GLOB SOURCE_FILES *.cpp)
|
||||
file (GLOB HEADER_FILES *.hpp)
|
||||
|
||||
init_target (telemetry_server)
|
||||
|
||||
build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES})
|
||||
|
||||
link_boost ()
|
||||
final_target ()
|
23
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/SConscript
vendored
Normal file
23
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/SConscript
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
## Main development example
|
||||
##
|
||||
|
||||
Import('env')
|
||||
Import('env_cpp11')
|
||||
Import('boostlibs')
|
||||
Import('platform_libs')
|
||||
Import('polyfill_libs')
|
||||
|
||||
env = env.Clone ()
|
||||
env_cpp11 = env_cpp11.Clone ()
|
||||
|
||||
prgs = []
|
||||
|
||||
# if a C++11 environment is available build using that, otherwise use boost
|
||||
if env_cpp11.has_key('WSPP_CPP11_ENABLED'):
|
||||
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env_cpp11.Program('telemetry_server', ["telemetry_server.cpp"], LIBS = ALL_LIBS)
|
||||
else:
|
||||
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
|
||||
prgs += env.Program('telemetry_server', ["telemetry_server.cpp"], LIBS = ALL_LIBS)
|
||||
|
||||
Return('prgs')
|
85
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/index.html
vendored
Normal file
85
3rdparty/cpprestsdk/libs/websocketpp/examples/telemetry_server/index.html
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebSocket++ Telemetry Client</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var ws;
|
||||
var url;
|
||||
|
||||
function connect() {
|
||||
url = document.getElementById("server_url").value;
|
||||
|
||||
if ("WebSocket" in window) {
|
||||
ws = new WebSocket(url);
|
||||
} else if ("MozWebSocket" in window) {
|
||||
ws = new MozWebSocket(url);
|
||||
} else {
|
||||
document.getElementById("messages").innerHTML += "This Browser does not support WebSockets<br />";
|
||||
return;
|
||||
}
|
||||
ws.onopen = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: A connection to "+ws.url+" has been opened.<br />";
|
||||
|
||||
document.getElementById("server_url").disabled = true;
|
||||
document.getElementById("toggle_connect").innerHTML = "Disconnect";
|
||||
};
|
||||
|
||||
ws.onerror = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: An error occured, see console log for more details.<br />";
|
||||
console.log(e);
|
||||
};
|
||||
|
||||
ws.onclose = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Client: The connection to "+url+" was closed. ["+e.code+(e.reason != "" ? ","+e.reason : "")+"]<br />";
|
||||
cleanup_disconnect();
|
||||
};
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
document.getElementById("messages").innerHTML += "Server: "+e.data+"<br />";
|
||||
};
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
ws.close();
|
||||
cleanup_disconnect();
|
||||
}
|
||||
|
||||
function cleanup_disconnect() {
|
||||
document.getElementById("server_url").disabled = false;
|
||||
document.getElementById("toggle_connect").innerHTML = "Connect";
|
||||
}
|
||||
|
||||
function toggle_connect() {
|
||||
if (document.getElementById("server_url").disabled === false) {
|
||||
connect();
|
||||
} else {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body,html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
#controls {
|
||||
float:right;
|
||||
background-color: #999;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="controls">
|
||||
<div id="server">
|
||||
<input type="text" name="server_url" id="server_url" value="ws://localhost:9002" /><br />
|
||||
<button id="toggle_connect" onclick="toggle_connect();">Connect</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="messages"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue