mirror of
https://github.com/tribufu/sdk-cpp
synced 2025-06-17 06:14:21 +00:00
Add boost and cpprestsdk
This commit is contained in:
1180
vendor/cpprestsdk/include/cpprest/astreambuf.h
vendored
Normal file
1180
vendor/cpprestsdk/include/cpprest/astreambuf.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
736
vendor/cpprestsdk/include/cpprest/asyncrt_utils.h
vendored
Normal file
736
vendor/cpprestsdk/include/cpprest/asyncrt_utils.h
vendored
Normal file
@ -0,0 +1,736 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Various common utilities.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#if !defined(ANDROID) && !defined(__ANDROID__) && defined(HAVE_XLOCALE_H) // CodePlex 269
|
||||
/* Systems using glibc: xlocale.h has been removed from glibc 2.26
|
||||
The above include of locale.h is sufficient
|
||||
Further details: https://sourceware.org/git/?p=glibc.git;a=commit;h=f0be25b6336db7492e47d2e8e72eb8af53b5506d */
|
||||
#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& timespanString);
|
||||
} // namespace timespan
|
||||
|
||||
/// 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>
|
||||
#ifdef _UTF16_STRINGS
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string&& s);
|
||||
#else
|
||||
inline utility::string_t&& to_string_t(std::string&& s) { return std::move(s); }
|
||||
#endif
|
||||
|
||||
/// <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>
|
||||
#ifdef _UTF16_STRINGS
|
||||
inline utility::string_t&& to_string_t(utf16string&& s) { return std::move(s); }
|
||||
#else
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(utf16string&& s);
|
||||
#endif
|
||||
/// <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>
|
||||
#ifdef _UTF16_STRINGS
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const std::string& s);
|
||||
#else
|
||||
inline const utility::string_t& to_string_t(const std::string& s) { return s; }
|
||||
#endif
|
||||
|
||||
/// <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>
|
||||
#ifdef _UTF16_STRINGS
|
||||
inline const utility::string_t& to_string_t(const utf16string& s) { return s; }
|
||||
#else
|
||||
_ASYNCRTIMP utility::string_t __cdecl to_string_t(const utf16string& s);
|
||||
#endif
|
||||
|
||||
/// <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>
|
||||
inline const utf16string& to_utf16string(const utf16string& value) { return 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>
|
||||
inline utf16string&& to_utf16string(utf16string&& value) { return std::move(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>
|
||||
inline std::string&& to_utf8string(std::string&& value) { return std::move(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>
|
||||
inline const std::string& to_utf8string(const std::string& value) { return 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>
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
utility::string_t print_string(const Source& val, const std::locale& loc = std::locale())
|
||||
{
|
||||
utility::ostringstream_t oss;
|
||||
oss.imbue(loc);
|
||||
oss << val;
|
||||
if (oss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
inline utility::string_t print_string(const utility::string_t& val) { return val; }
|
||||
|
||||
namespace details
|
||||
{
|
||||
#if defined(__ANDROID__)
|
||||
template<class T>
|
||||
inline std::string to_string(const T t)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os.imbue(std::locale::classic());
|
||||
os << t;
|
||||
return os.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
inline utility::string_t to_string_t(const T t)
|
||||
{
|
||||
#ifdef _UTF16_STRINGS
|
||||
using std::to_wstring;
|
||||
return to_wstring(t);
|
||||
#else
|
||||
#if !defined(__ANDROID__)
|
||||
using std::to_string;
|
||||
#endif
|
||||
return to_string(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Source>
|
||||
utility::string_t print_string(const Source& val)
|
||||
{
|
||||
utility::ostringstream_t oss;
|
||||
oss.imbue(std::locale::classic());
|
||||
oss << val;
|
||||
if (oss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
inline const utility::string_t& print_string(const utility::string_t& val) { return val; }
|
||||
|
||||
template<typename Source>
|
||||
utf8string print_utf8string(const Source& val)
|
||||
{
|
||||
return conversions::to_utf8string(print_string(val));
|
||||
}
|
||||
inline const utf8string& print_utf8string(const utf8string& val) { return val; }
|
||||
|
||||
template<typename Target>
|
||||
Target scan_string(const utility::string_t& str)
|
||||
{
|
||||
Target t;
|
||||
utility::istringstream_t iss(str);
|
||||
iss.imbue(std::locale::classic());
|
||||
iss >> t;
|
||||
if (iss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
inline const utility::string_t& scan_string(const utility::string_t& str) { return str; }
|
||||
} // namespace details
|
||||
|
||||
template<typename Target>
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
Target scan_string(const utility::string_t& str, const std::locale& loc = std::locale())
|
||||
{
|
||||
Target t;
|
||||
utility::istringstream_t iss(str);
|
||||
iss.imbue(loc);
|
||||
iss >> t;
|
||||
if (iss.bad())
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
CASABLANCA_DEPRECATED("All locale-sensitive APIs will be removed in a future update. Use stringstreams directly if "
|
||||
"locale support is required.")
|
||||
inline utility::string_t scan_string(const utility::string_t& str) { return str; }
|
||||
} // namespace conversions
|
||||
|
||||
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(const unsigned char uch) CPPREST_NOEXCEPT
|
||||
{ // test if uch is an alnum character
|
||||
// special casing char to avoid branches
|
||||
// clang-format off
|
||||
static CPPREST_CONSTEXPR bool is_alnum_table[UCHAR_MAX + 1] = {
|
||||
/* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */
|
||||
/* 0X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 1X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 2X */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0-9 */
|
||||
/* 4X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A-Z */
|
||||
/* 5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
||||
/* 6X */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a-z */
|
||||
/* 7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
|
||||
/* non-ASCII values initialized to 0 */
|
||||
};
|
||||
// clang-format on
|
||||
return (is_alnum_table[uch]);
|
||||
}
|
||||
|
||||
/// <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(const char ch) CPPREST_NOEXCEPT { return (is_alnum(static_cast<unsigned char>(ch))); }
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of alpha numeric instead of std::isalnum to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// </summary>
|
||||
template<class Elem>
|
||||
inline bool __cdecl is_alnum(Elem ch) CPPREST_NOEXCEPT
|
||||
{
|
||||
// assumes 'x' == L'x' for the ASCII range
|
||||
typedef typename std::make_unsigned<Elem>::type UElem;
|
||||
const auto uch = static_cast<UElem>(ch);
|
||||
return (uch <= static_cast<UElem>('z') && is_alnum(static_cast<unsigned char>(uch)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our own implementation of whitespace test instead of std::isspace to avoid
|
||||
/// taking global lock for performance reasons.
|
||||
/// The following characters are considered whitespace:
|
||||
/// 0x09 == Horizontal Tab
|
||||
/// 0x0A == Line Feed
|
||||
/// 0x0B == Vertical Tab
|
||||
/// 0x0C == Form Feed
|
||||
/// 0x0D == Carrage Return
|
||||
/// 0x20 == Space
|
||||
/// </summary>
|
||||
template<class Elem>
|
||||
inline bool __cdecl is_space(Elem ch) CPPREST_NOEXCEPT
|
||||
{
|
||||
// assumes 'x' == L'x' for the ASCII range
|
||||
typedef typename std::make_unsigned<Elem>::type UElem;
|
||||
const auto uch = static_cast<UElem>(ch);
|
||||
return uch == 0x20u || (uch >= 0x09u && uch <= 0x0Du);
|
||||
}
|
||||
|
||||
/// <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)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(
|
||||
std::forward<_Arg1>(arg1), std::forward<_Arg2>(arg2), std::forward<_Arg3>(arg3), std::forward<_Arg4>(arg4)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
|
||||
std::forward<_Arg2>(arg2),
|
||||
std::forward<_Arg3>(arg3),
|
||||
std::forward<_Arg4>(arg4),
|
||||
std::forward<_Arg5>(arg5)));
|
||||
}
|
||||
|
||||
template<typename _Type, typename _Arg1, typename _Arg2, typename _Arg3, typename _Arg4, typename _Arg5, typename _Arg6>
|
||||
std::unique_ptr<_Type> make_unique(_Arg1&& arg1, _Arg2&& arg2, _Arg3&& arg3, _Arg4&& arg4, _Arg5&& arg5, _Arg6&& arg6)
|
||||
{
|
||||
return std::unique_ptr<_Type>(new _Type(std::forward<_Arg1>(arg1),
|
||||
std::forward<_Arg2>(arg2),
|
||||
std::forward<_Arg3>(arg3),
|
||||
std::forward<_Arg4>(arg4),
|
||||
std::forward<_Arg5>(arg5),
|
||||
std::forward<_Arg6>(arg6)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string equality comparison.
|
||||
/// </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>
|
||||
_ASYNCRTIMP bool __cdecl str_iequal(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string equality comparison.
|
||||
/// </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>
|
||||
_ASYNCRTIMP bool __cdecl str_iequal(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string less-than comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
|
||||
/// false.</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iless(const std::string& left, const std::string& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Cross platform utility function for performing case insensitive string less-than comparison.
|
||||
/// </summary>
|
||||
/// <param name="left">First string to compare.</param>
|
||||
/// <param name="right">Second strong to compare.</param>
|
||||
/// <returns>true if a lowercase view of left is lexicographically less than a lowercase view of right; otherwise,
|
||||
/// false.</returns>
|
||||
_ASYNCRTIMP bool __cdecl str_iless(const std::wstring& left, const std::wstring& right) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string to lowercase in place.
|
||||
/// </summary>
|
||||
/// <param name="target">The string to convert to lowercase.</param>
|
||||
_ASYNCRTIMP void __cdecl inplace_tolower(std::string& target) CPPREST_NOEXCEPT;
|
||||
|
||||
/// <summary>
|
||||
/// Convert a string to lowercase in place.
|
||||
/// </summary>
|
||||
/// <param name="target">The string to convert to lowercase.</param>
|
||||
_ASYNCRTIMP void __cdecl inplace_tolower(std::wstring& target) CPPREST_NOEXCEPT;
|
||||
|
||||
#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"; }
|
||||
|
||||
virtual std::string message(int errorCode) const CPPREST_NOEXCEPT;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
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 or ISO 8601 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>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 or ISO 8601 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>datetime::maximum()</c> if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string_maximum_error(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; }
|
||||
|
||||
static datetime from_interval(interval_type interval) { return datetime(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); }
|
||||
|
||||
bool operator>(const datetime& dt) const { return this->m_interval > dt.m_interval; }
|
||||
|
||||
bool operator<(const datetime& dt) const { return this->m_interval < dt.m_interval; }
|
||||
|
||||
bool operator>=(const datetime& dt) const { return this->m_interval >= dt.m_interval; }
|
||||
|
||||
bool operator<=(const datetime& dt) const { return this->m_interval <= dt.m_interval; }
|
||||
|
||||
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; }
|
||||
|
||||
static datetime maximum() { return datetime(static_cast<interval_type>(-1)); }
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
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:
|
||||
std::mt19937 m_random;
|
||||
int m_length;
|
||||
};
|
||||
|
||||
} // namespace utility
|
392
vendor/cpprestsdk/include/cpprest/base_uri.h
vendored
Normal file
392
vendor/cpprestsdk/include/cpprest/base_uri.h
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
struct uri_components
|
||||
{
|
||||
uri_components() : m_path(_XPLATSTR("/")), m_port(-1) {}
|
||||
|
||||
uri_components(const uri_components&) = default;
|
||||
uri_components& operator=(const uri_components&) = default;
|
||||
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
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;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
/// <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 empty 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>
|
||||
/// <returns>The encoded string.</returns>
|
||||
_ASYNCRTIMP static utility::string_t __cdecl encode_data_string(const utility::string_t& data);
|
||||
|
||||
/// <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>
|
||||
/// <remarks>
|
||||
/// This function accepts both uris ('http://msn.com') and uri relative-references ('path1/path2?query').
|
||||
/// </remarks>
|
||||
/// <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&) = default;
|
||||
|
||||
/// <summary>
|
||||
/// Copy assignment operator.
|
||||
/// </summary>
|
||||
uri& operator=(const uri&) = default;
|
||||
|
||||
/// <summary>
|
||||
/// Move constructor.
|
||||
/// </summary>
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
uri(uri&& other) CPPREST_NOEXCEPT : m_uri(std::move(other.m_uri)), m_components(std::move(other.m_components)) {}
|
||||
|
||||
/// <summary>
|
||||
/// Move assignment operator
|
||||
/// </summary>
|
||||
// This is for VS2013 compatibility -- replace with '= default' when VS2013 is completely dropped.
|
||||
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 "localhost", or "127.0.0.1". The only URIs for which this method returns true are "127.0.0.1", and "localhost",
|
||||
/// all other URIs return false
|
||||
/// </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() == _XPLATSTR("127.0.0.1")));
|
||||
}
|
||||
|
||||
/// <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; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an URI resolved against <c>this</c> as the base URI
|
||||
/// according to RFC3986, Section 5 (https://tools.ietf.org/html/rfc3986#section-5).
|
||||
/// </summary>
|
||||
/// <param name="relativeUri">The relative URI to be resolved against <c>this</c> as base.</param>
|
||||
/// <returns>The new resolved URI string.</returns>
|
||||
_ASYNCRTIMP utility::string_t resolve_uri(const utility::string_t& relativeUri) const;
|
||||
|
||||
_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;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a URI from the given URI components.
|
||||
/// </summary>
|
||||
/// <param name="components">A URI components object to create the URI instance.</param>
|
||||
_ASYNCRTIMP uri(const details::uri_components& components);
|
||||
|
||||
// Used by uri_builder
|
||||
static utility::string_t __cdecl encode_query_impl(const utf8string& raw);
|
||||
|
||||
utility::string_t m_uri;
|
||||
details::uri_components m_components;
|
||||
};
|
||||
|
||||
} // namespace web
|
590
vendor/cpprestsdk/include/cpprest/containerstream.h
vendored
Normal file
590
vendor/cpprestsdk/include/cpprest/containerstream.h
vendored
Normal file
@ -0,0 +1,590 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
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 = std::begin(m_data) + m_current_position;
|
||||
auto readEnd = std::begin(m_data) + newPos;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// 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, std::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>());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
7484
vendor/cpprestsdk/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
7484
vendor/cpprestsdk/include/cpprest/details/SafeInt3.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
131
vendor/cpprestsdk/include/cpprest/details/basic_types.h
vendored
Normal file
131
vendor/cpprestsdk/include/cpprest/details/basic_types.h
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Platform-dependent type definitions
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/cpprest_compat.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#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
|
||||
// The 'U' macro can be used to create a string or character literal of the platform type, i.e. utility::char_t.
|
||||
// If you are using a library causing conflicts with 'U' macro, it can be turned off by defining the macro
|
||||
// '_TURN_OFF_PLATFORM_STRING' before including the C++ REST SDK header files, and e.g. use '_XPLATSTR' instead.
|
||||
#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
|
101
vendor/cpprestsdk/include/cpprest/details/cpprest_compat.h
vendored
Normal file
101
vendor/cpprestsdk/include/cpprest/details/cpprest_compat.h
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
#define CPPREST_CONSTEXPR constexpr
|
||||
#else
|
||||
#define CPPREST_NOEXCEPT
|
||||
#define CPPREST_CONSTEXPR const
|
||||
#endif // _MSC_VER >= 1900
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv
|
||||
|
||||
#define __declspec(x) __attribute__((x))
|
||||
#define novtable /* no novtable equivalent */
|
||||
#define __assume(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) __builtin_unreachable(); \
|
||||
} while (false)
|
||||
#define CPPREST_NOEXCEPT noexcept
|
||||
#define CPPREST_CONSTEXPR constexpr
|
||||
|
||||
#include <assert.h>
|
||||
#define _ASSERTE(x) assert(x)
|
||||
|
||||
// No SAL on non Windows platforms
|
||||
#include "cpprest/details/nosal.h"
|
||||
|
||||
#if !defined(__cdecl)
|
||||
#if defined(cdecl)
|
||||
#define __cdecl __attribute__((cdecl))
|
||||
#else // ^^^ defined cdecl ^^^ // vvv !defined cdecl vvv
|
||||
#define __cdecl
|
||||
#endif // defined cdecl
|
||||
#endif // not defined __cdecl
|
||||
|
||||
#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.
|
||||
#if not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#define BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#endif // not defined BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION
|
||||
#endif // defined(__ANDROID__)
|
||||
|
||||
#ifdef __clang__
|
||||
#include <cstdio>
|
||||
#endif // __clang__
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef _NO_ASYNCRTIMP
|
||||
#define _ASYNCRTIMP
|
||||
#define _ASYNCRTIMP_TYPEINFO
|
||||
#else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv
|
||||
#ifdef _ASYNCRT_EXPORT
|
||||
#ifdef _WIN32
|
||||
#define _ASYNCRTIMP __declspec(dllexport)
|
||||
#else
|
||||
#define _ASYNCRTIMP __attribute__((visibility("default")))
|
||||
#endif
|
||||
#else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv
|
||||
#ifdef _WIN32
|
||||
#define _ASYNCRTIMP __declspec(dllimport)
|
||||
#else
|
||||
#define _ASYNCRTIMP
|
||||
#endif
|
||||
#endif // _ASYNCRT_EXPORT
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define _ASYNCRTIMP_TYPEINFO
|
||||
#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv
|
||||
#define _ASYNCRTIMP_TYPEINFO __attribute__((visibility("default")))
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // _NO_ASYNCRTIMP
|
||||
|
||||
#ifdef CASABLANCA_DEPRECATION_NO_WARNINGS
|
||||
#define CASABLANCA_DEPRECATED(x)
|
||||
#else
|
||||
#define CASABLANCA_DEPRECATED(x) __declspec(deprecated(x))
|
||||
#endif // CASABLANCA_DEPRECATION_NO_WARNINGS
|
220
vendor/cpprestsdk/include/cpprest/details/fileio.h
vendored
Normal file
220
vendor/cpprestsdk/include/cpprest/details/fileio.h
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "pplx/pplxtasks.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() {}
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
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);
|
||||
}
|
199
vendor/cpprestsdk/include/cpprest/details/http_constants.dat
vendored
Normal file
199
vendor/cpprestsdk/include/cpprest/details/http_constants.dat
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
#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(MultiStatus, 207, _XPLATSTR("Multi-Status"))
|
||||
DAT(AlreadyReported, 208, _XPLATSTR("Already Reported"))
|
||||
DAT(IMUsed, 226, _XPLATSTR("IM Used"))
|
||||
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(PermanentRedirect, 308, _XPLATSTR("Permanent 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(MisdirectedRequest, 421, _XPLATSTR("Misdirected Request"))
|
||||
DAT(UnprocessableEntity, 422, _XPLATSTR("Unprocessable Entity"))
|
||||
DAT(Locked, 423, _XPLATSTR("Locked"))
|
||||
DAT(FailedDependency, 424, _XPLATSTR("Failed Dependency"))
|
||||
DAT(UpgradeRequired, 426, _XPLATSTR("Upgrade Required"))
|
||||
DAT(PreconditionRequired, 428, _XPLATSTR("Precondition Required"))
|
||||
DAT(TooManyRequests, 429, _XPLATSTR("Too Many Requests"))
|
||||
DAT(RequestHeaderFieldsTooLarge, 431, _XPLATSTR("Request Header Fields Too Large"))
|
||||
DAT(UnavailableForLegalReasons, 451, _XPLATSTR("Unavailable For Legal Reasons"))
|
||||
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"))
|
||||
DAT(VariantAlsoNegotiates, 506, _XPLATSTR("Variant Also Negotiates"))
|
||||
DAT(InsufficientStorage, 507, _XPLATSTR("Insufficient Storage"))
|
||||
DAT(LoopDetected, 508, _XPLATSTR("Loop Detected"))
|
||||
DAT(NotExtended, 510, _XPLATSTR("Not Extended"))
|
||||
DAT(NetworkAuthenticationRequired, 511, _XPLATSTR("Network Authentication Required"))
|
||||
#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(access_control_allow_origin, "Access-Control-Allow-Origin")
|
||||
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(client_credentials, "client_credentials")
|
||||
DAT(response_type, "response_type")
|
||||
DAT(scope, "scope")
|
||||
DAT(state, "state")
|
||||
DAT(token, "token")
|
||||
DAT(token_type, "token_type")
|
||||
#endif // _OAUTH2_STRINGS
|
48
vendor/cpprestsdk/include/cpprest/details/http_helpers.h
vendored
Normal file
48
vendor/cpprestsdk/include/cpprest/details/http_helpers.h
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
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);
|
||||
} // namespace chunked_encoding
|
||||
|
||||
} // namespace details
|
||||
} // namespace http
|
||||
} // namespace web
|
72
vendor/cpprestsdk/include/cpprest/details/http_server.h
vendored
Normal file
72
vendor/cpprestsdk/include/cpprest/details/http_server.h
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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 http
|
||||
} // namespace web
|
93
vendor/cpprestsdk/include/cpprest/details/http_server_api.h
vendored
Normal file
93
vendor/cpprestsdk/include/cpprest/details/http_server_api.h
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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 "cpprest/http_listener.h"
|
||||
#include <memory>
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace experimental
|
||||
} // namespace http
|
||||
} // namespace web
|
77
vendor/cpprestsdk/include/cpprest/details/nosal.h
vendored
Normal file
77
vendor/cpprestsdk/include/cpprest/details/nosal.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
***/
|
||||
|
||||
#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
vendor/cpprestsdk/include/cpprest/details/resource.h
vendored
Normal file
14
vendor/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
|
225
vendor/cpprestsdk/include/cpprest/details/web_utilities.h
vendored
Normal file
225
vendor/cpprestsdk/include/cpprest/details/web_utilities.h
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* utility classes used by the different web:: clients
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/uri.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
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;
|
||||
|
||||
#ifdef _WIN32
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#ifdef __cplusplus_winrt
|
||||
class winrt_encryption
|
||||
{
|
||||
public:
|
||||
winrt_encryption() = default;
|
||||
_ASYNCRTIMP winrt_encryption(const std::wstring& data);
|
||||
_ASYNCRTIMP plaintext_string decrypt() const;
|
||||
|
||||
private:
|
||||
::pplx::task<Windows::Storage::Streams::IBuffer ^> m_buffer;
|
||||
};
|
||||
#else // ^^^ __cplusplus_winrt ^^^ // vvv !__cplusplus_winrt vvv
|
||||
class win32_encryption
|
||||
{
|
||||
public:
|
||||
win32_encryption() = default;
|
||||
_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 // __cplusplus_winrt
|
||||
#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#endif // _WIN32
|
||||
} // namespace details
|
||||
|
||||
/// <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) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return utility::string_t(*m_password.decrypt());
|
||||
#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(); }
|
||||
|
||||
details::plaintext_string _internal_decrypt() const
|
||||
{
|
||||
// Encryption APIs not supported on XP
|
||||
#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return m_password.decrypt();
|
||||
#else
|
||||
return details::plaintext_string(new ::utility::string_t(m_password));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
::utility::string_t m_username;
|
||||
|
||||
#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#if defined(__cplusplus_winrt)
|
||||
details::winrt_encryption m_password;
|
||||
#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(), 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(), 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;
|
||||
};
|
||||
|
||||
} // namespace web
|
1094
vendor/cpprestsdk/include/cpprest/filestream.h
vendored
Normal file
1094
vendor/cpprestsdk/include/cpprest/filestream.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
766
vendor/cpprestsdk/include/cpprest/http_client.h
vendored
Normal file
766
vendor/cpprestsdk/include/cpprest/http_client.h
vendored
Normal file
@ -0,0 +1,766 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Client-side APIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#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 <msxml6.h>
|
||||
#include <wrl.h>
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
typedef IXMLHTTPRequest2* native_handle;
|
||||
}
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
#else
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
typedef void* native_handle;
|
||||
}
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
#endif // __cplusplus_winrt
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/basic_types.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
#include "cpprest/json.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#include "cpprest/oauth1.h"
|
||||
#endif
|
||||
|
||||
#include "cpprest/oauth2.h"
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include "boost/asio/ssl.hpp"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// 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(std::chrono::seconds(30))
|
||||
, m_chunksize(0)
|
||||
, m_request_compressed(false)
|
||||
#if !defined(__cplusplus_winrt)
|
||||
, m_validate_certificates(true)
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
, m_tlsext_sni_enabled(true)
|
||||
#endif
|
||||
#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL)
|
||||
, m_buffer_request(false)
|
||||
#endif
|
||||
, m_max_redirects(10)
|
||||
, m_https_to_http_redirects(false)
|
||||
{
|
||||
}
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/// <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 std::chrono::duration_cast<utility::seconds>(m_timeout); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the timeout
|
||||
/// </summary>
|
||||
/// <returns>The timeout (in whatever duration) used for each send and receive operation on the client.</returns>
|
||||
template<class T>
|
||||
T timeout() const
|
||||
{
|
||||
return std::chrono::duration_cast<T>(m_timeout);
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the timeout
|
||||
/// </summary>
|
||||
/// <param name="timeout">The timeout (duration from microseconds range and up) used for each send and receive
|
||||
/// operation on the client.</param>
|
||||
template<class T>
|
||||
void set_timeout(const T& timeout)
|
||||
{
|
||||
m_timeout = std::chrono::duration_cast<std::chrono::microseconds>(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; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if requesting a compressed response using Content-Encoding is turned on, the default is off.
|
||||
/// </summary>
|
||||
/// <returns>True if a content-encoded compressed response is allowed, false otherwise</returns>
|
||||
bool request_compressed_response() const { return m_request_compressed; }
|
||||
|
||||
/// <summary>
|
||||
/// Request that the server respond with a compressed body using Content-Encoding; to use Transfer-Encoding, do not
|
||||
/// set this, and specify a vector of <see cref="web::http::details::compression::decompress_factory" /> pointers
|
||||
/// to the set_decompress_factories method of the <see cref="web::http::http_request" /> object for the request.
|
||||
/// If true and the server does not support compression, this will have no effect.
|
||||
/// The response body is internally decompressed before the consumer receives the data.
|
||||
/// </summary>
|
||||
/// <param name="request_compressed">True to turn on content-encoded response body compression, false
|
||||
/// otherwise.</param> <remarks>Please note there is a performance cost due to copying the request data. Currently
|
||||
/// only supported on Windows and OSX.</remarks>
|
||||
void set_request_compressed_response(bool request_compressed) { m_request_compressed = request_compressed; }
|
||||
|
||||
#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
|
||||
|
||||
#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL)
|
||||
/// <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
|
||||
|
||||
/// <summary>
|
||||
/// Get the maximum number of redirects to follow automatically.
|
||||
/// A value of 0 indicates that no automatic redirection is performed.
|
||||
/// </summary>
|
||||
/// <returns>The maximum number of redirects to follow automatically.</returns>
|
||||
/// <remarks>This is a hint -- an implementation may enforce a lower value.</remarks>
|
||||
size_t max_redirects() const { return m_max_redirects; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the maximum number of redirects to follow automatically.
|
||||
/// A value of 0 indicates that no automatic redirection is performed.
|
||||
/// </summary>
|
||||
/// <param name="max_redirects">The maximum number of redirects to follow automatically.</param>
|
||||
/// <remarks>This is a hint -- an implementation may enforce a lower value.</remarks>
|
||||
void set_max_redirects(size_t max_redirects) { m_max_redirects = max_redirects; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if HTTPS to HTTP redirects are automatically followed.
|
||||
/// </summary>
|
||||
/// <returns>True if HTTPS to HTTP redirects are automatically followed, false otherwise.</returns>
|
||||
bool https_to_http_redirects() const { return m_https_to_http_redirects; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets if HTTPS to HTTP redirects are automatically followed.
|
||||
/// </summary>
|
||||
/// <param name="https_to_http_redirects">True if HTTPS to HTTP redirects are to be automatically
|
||||
/// followed, false otherwise.</param>
|
||||
void set_https_to_http_redirects(bool https_to_http_redirects)
|
||||
{
|
||||
m_https_to_http_redirects = https_to_http_redirects;
|
||||
}
|
||||
|
||||
/// <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 (session)
|
||||
/// </remarks>
|
||||
/// <param name="callback">A user callback allowing for customization of the session</param>
|
||||
void set_nativesessionhandle_options(const std::function<void(native_handle)>& callback)
|
||||
{
|
||||
m_set_user_nativesessionhandle_options = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes a user's callback to allow for customization of the session.
|
||||
/// </summary>
|
||||
/// <remarks>Internal Use Only</remarks>
|
||||
/// <param name="handle">A internal implementation handle.</param>
|
||||
void _invoke_nativesessionhandle_options(native_handle handle) const
|
||||
{
|
||||
if (m_set_user_nativesessionhandle_options) m_set_user_nativesessionhandle_options(handle);
|
||||
}
|
||||
|
||||
/// <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
|
||||
{
|
||||
if (m_set_user_nativehandle_options) m_set_user_nativehandle_options(handle);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of the ssl context, at construction time.
|
||||
/// </summary>
|
||||
/// <param name="callback">A user callback allowing for customization of the ssl context at construction
|
||||
/// time.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
|
||||
{
|
||||
m_ssl_context_callback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user's callback to allow for customization of the ssl context.
|
||||
/// </summary>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TLS extension server name indication (SNI) status.
|
||||
/// </summary>
|
||||
/// <returns>True if TLS server name indication is enabled, false otherwise.</returns>
|
||||
bool is_tlsext_sni_enabled() const { return m_tlsext_sni_enabled; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the TLS extension server name indication (SNI) status.
|
||||
/// </summary>
|
||||
/// <param name="tlsext_sni_enabled">False to disable the TLS (ClientHello) extension for server name indication,
|
||||
/// true otherwise.</param> <remarks>Note: This setting is enabled by default as it is required in most virtual
|
||||
/// hosting scenarios.</remarks>
|
||||
void set_tlsext_sni_enabled(bool tlsext_sni_enabled) { m_tlsext_sni_enabled = tlsext_sni_enabled; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
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;
|
||||
|
||||
std::chrono::microseconds m_timeout;
|
||||
size_t m_chunksize;
|
||||
bool m_request_compressed;
|
||||
|
||||
#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;
|
||||
std::function<void(native_handle)> m_set_user_nativesessionhandle_options;
|
||||
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
bool m_tlsext_sni_enabled;
|
||||
#endif
|
||||
#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL)
|
||||
bool m_buffer_request;
|
||||
#endif
|
||||
|
||||
size_t m_max_redirects;
|
||||
bool m_https_to_http_redirects;
|
||||
};
|
||||
|
||||
class http_pipeline;
|
||||
|
||||
/// <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>
|
||||
_ASYNCRTIMP ~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>
|
||||
_ASYNCRTIMP void add_handler(const std::function<pplx::task<http_response> __cdecl(
|
||||
http_request, std::shared_ptr<http::http_pipeline_stage>)>& handler);
|
||||
|
||||
/// <summary>
|
||||
/// Adds an HTTP pipeline stage to the client.
|
||||
/// </summary>
|
||||
/// <param name="stage">A shared pointer to a pipeline stage.</param>
|
||||
_ASYNCRTIMP void add_handler(const std::shared_ptr<http::http_pipeline_stage>& 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:
|
||||
std::shared_ptr<::web::http::client::http_pipeline> m_pipeline;
|
||||
};
|
||||
|
||||
namespace details
|
||||
{
|
||||
#if defined(_WIN32) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL)
|
||||
extern const utility::char_t* get_with_body_err_msg;
|
||||
#endif
|
||||
|
||||
} // namespace details
|
||||
|
||||
} // namespace client
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
326
vendor/cpprestsdk/include/cpprest/http_compression.h
vendored
Normal file
326
vendor/cpprestsdk/include/cpprest/http_compression.h
vendored
Normal file
@ -0,0 +1,326 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Compression and decompression interfaces
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace compression
|
||||
{
|
||||
/// <summary>
|
||||
/// Hint as to whether a compress or decompress call is meant to be the last for a particular HTTP request or reply
|
||||
/// </summary>
|
||||
enum operation_hint
|
||||
{
|
||||
is_last, // Used for the expected last compress() call, or for an expected single decompress() call
|
||||
has_more // Used when further compress() calls will be made, or when multiple decompress() calls may be required
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Result structure for asynchronous compression and decompression operations
|
||||
/// </summary>
|
||||
struct operation_result
|
||||
{
|
||||
size_t input_bytes_processed; // From the input buffer
|
||||
size_t output_bytes_produced; // To the output buffer
|
||||
bool done; // For compress, set when 'last' is true and there was enough space to complete compression;
|
||||
// for decompress, set if the end of the decompression stream has been reached
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Compression interface for use with HTTP requests
|
||||
/// </summary>
|
||||
class compress_provider
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual size_t compress(const uint8_t* input,
|
||||
size_t input_size,
|
||||
uint8_t* output,
|
||||
size_t output_size,
|
||||
operation_hint hint,
|
||||
size_t& input_bytes_processed,
|
||||
bool& done) = 0;
|
||||
virtual pplx::task<operation_result> compress(
|
||||
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual ~compress_provider() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Decompression interface for use with HTTP requests
|
||||
/// </summary>
|
||||
class decompress_provider
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual size_t decompress(const uint8_t* input,
|
||||
size_t input_size,
|
||||
uint8_t* output,
|
||||
size_t output_size,
|
||||
operation_hint hint,
|
||||
size_t& input_bytes_processed,
|
||||
bool& done) = 0;
|
||||
virtual pplx::task<operation_result> decompress(
|
||||
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size, operation_hint hint) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual ~decompress_provider() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory interface for compressors for use with received HTTP requests
|
||||
/// </summary>
|
||||
class compress_factory
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual std::unique_ptr<compress_provider> make_compressor() const = 0;
|
||||
virtual ~compress_factory() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory interface for decompressors for use with HTTP requests
|
||||
/// </summary>
|
||||
class decompress_factory
|
||||
{
|
||||
public:
|
||||
virtual const utility::string_t& algorithm() const = 0;
|
||||
virtual uint16_t weight() const = 0;
|
||||
virtual std::unique_ptr<decompress_provider> make_decompressor() const = 0;
|
||||
virtual ~decompress_factory() = default;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Built-in compression support
|
||||
/// </summary>
|
||||
namespace builtin
|
||||
{
|
||||
/// <summary>
|
||||
/// Test whether cpprestsdk was built with built-in compression support
|
||||
/// <returns>True if cpprestsdk was built with built-in compression support, and false if not.</returns>
|
||||
/// </summary>
|
||||
_ASYNCRTIMP bool supported();
|
||||
|
||||
/// <summary>
|
||||
// String constants for each built-in compression algorithm, for convenient use with the factory functions
|
||||
/// </summary>
|
||||
namespace algorithm
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
const utility::char_t* const GZIP = _XPLATSTR("gzip");
|
||||
const utility::char_t* const DEFLATE = _XPLATSTR("deflate");
|
||||
const utility::char_t* const BROTLI = _XPLATSTR("br");
|
||||
#else // ^^^ VS2013 and before ^^^ // vvv VS2015+, and everything else vvv
|
||||
constexpr const utility::char_t* const GZIP = _XPLATSTR("gzip");
|
||||
constexpr const utility::char_t* const DEFLATE = _XPLATSTR("deflate");
|
||||
constexpr const utility::char_t* const BROTLI = _XPLATSTR("br");
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Test whether cpprestsdk was built with built-in compression support and
|
||||
/// the supplied string matches a supported built-in algorithm
|
||||
/// <param name="algorithm">The name of the algorithm to test for built-in support.</param>
|
||||
/// <returns>True if cpprestsdk was built with built-in compression support and
|
||||
/// the supplied string matches a supported built-in algorithm, and false if not.</returns>
|
||||
/// <summary>
|
||||
_ASYNCRTIMP bool supported(const utility::string_t& algorithm);
|
||||
} // namespace algorithm
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a built-in compression provider with default parameters by compression algorithm
|
||||
/// name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to instantiate a provider.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_compressor(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a built-in decompression provider with default parameters by compression algorithm
|
||||
/// name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to instantiate a provider.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<decompress_provider> make_decompressor(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to obtain a pointer to a built-in compression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to find a factory.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::shared_ptr<compress_factory> get_compress_factory(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to obtain a pointer to a built-in decompression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm for which to find a factory.</param>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a provider of the requested-type, or to nullptr if no such built-in type exists.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::shared_ptr<decompress_factory> get_decompress_factory(const utility::string_t& algorithm);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in gzip compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a gzip compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_gzip_compressor(int compressionLevel,
|
||||
int method,
|
||||
int strategy,
|
||||
int memLevel);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in deflate compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a deflate compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support..
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_deflate_compressor(int compressionLevel,
|
||||
int method,
|
||||
int strategy,
|
||||
int memLevel);
|
||||
|
||||
/// <summary>
|
||||
// Factory function to instantiate a built-in Brotli compression provider with caller-selected parameters.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A caller-owned pointer to a Brotli compression provider, or to nullptr if the library was built without built-in
|
||||
/// compression support.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> make_brotli_compressor(
|
||||
uint32_t window, uint32_t quality, uint32_t mode, uint32_t block, uint32_t nomodel, uint32_t hint);
|
||||
} // namespace builtin
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a compression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm supported by the factory. Must match that returned by the
|
||||
/// <c>web::http::compression::compress_provider</c> type instantiated by the factory's make_compressor function.
|
||||
/// The supplied string is copied, and thus need not remain valid once the call returns.</param>
|
||||
/// <param name="make_compressor">A factory function to be used to instantiate a compressor matching the factory's
|
||||
/// reported algorithm.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a generic provider factory implementation configured with the supplied parameters.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method may be used to conveniently instantiate a factory object for a caller-selected <c>compress_provider</c>.
|
||||
/// That provider may be of the caller's own design, or it may be one of the built-in types. As such, this method may
|
||||
/// be helpful when a caller wishes to build vectors containing a mix of custom and built-in providers.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP std::shared_ptr<compress_factory> make_compress_factory(
|
||||
const utility::string_t& algorithm, std::function<std::unique_ptr<compress_provider>()> make_compressor);
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate a decompression provider factory by compression algorithm name.
|
||||
/// </summary>
|
||||
/// <param name="algorithm">The name of the algorithm supported by the factory. Must match that returned by the
|
||||
/// <c>web::http::compression::decompress_provider</c> type instantiated by the factory's make_decompressor function.
|
||||
/// The supplied string is copied, and thus need not remain valid once the call returns.</param>
|
||||
/// <param name="weight">A numeric weight for the compression algorithm, times 1000, for use as a "quality value" when
|
||||
/// requesting that the server send a compressed response. Valid values are between 0 and 1000, inclusive, where higher
|
||||
/// values indicate more preferred algorithms, and 0 indicates that the algorithm is not allowed; values greater than
|
||||
/// 1000 are treated as 1000.</param>
|
||||
/// <param name="make_decompressor">A factory function to be used to instantiate a decompressor matching the factory's
|
||||
/// reported algorithm.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a generic provider factory implementation configured with the supplied parameters.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method may be used to conveniently instantiate a factory object for a caller-selected
|
||||
/// <c>decompress_provider</c>. That provider may be of the caller's own design, or it may be one of the built-in
|
||||
/// types. As such, this method may be helpful when a caller wishes to change the weights of built-in provider types,
|
||||
/// to use custom providers without explicitly implementing a <c>decompress_factory</c>, or to build vectors containing
|
||||
/// a mix of custom and built-in providers.
|
||||
/// </remarks>
|
||||
_ASYNCRTIMP std::shared_ptr<decompress_factory> make_decompress_factory(
|
||||
const utility::string_t& algorithm,
|
||||
uint16_t weight,
|
||||
std::function<std::unique_ptr<decompress_provider>()> make_decompressor);
|
||||
|
||||
namespace details
|
||||
{
|
||||
/// <summary>
|
||||
/// Header type enum for use with compressor and decompressor header parsing and building functions
|
||||
/// </summary>
|
||||
enum header_types
|
||||
{
|
||||
transfer_encoding,
|
||||
content_encoding,
|
||||
te,
|
||||
accept_encoding
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate an appropriate compression provider, if any.
|
||||
/// </summary>
|
||||
/// <param name="encoding">A TE or Accept-Encoding header to interpret.</param>
|
||||
/// <param name="type">Specifies the type of header whose contents are in the encoding parameter; valid values are
|
||||
/// <c>header_type::te</c> and <c>header_type::accept_encoding</c>.</param>
|
||||
/// <param name="preferred">A compressor object of the caller's preferred (possibly custom) type, which is used if
|
||||
/// possible.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in construction of an appropriate compressor, if
|
||||
/// any. If empty or not supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a compressor object that is acceptable per the supplied header, or to nullptr if no matching
|
||||
/// algorithm is found.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<compress_provider> get_compressor_from_header(
|
||||
const utility::string_t& encoding,
|
||||
header_types type,
|
||||
const std::vector<std::shared_ptr<compress_factory>>& factories = std::vector<std::shared_ptr<compress_factory>>());
|
||||
|
||||
/// <summary>
|
||||
/// Factory function to instantiate an appropriate decompression provider, if any.
|
||||
/// </summary>
|
||||
/// <param name="encoding">A Transfer-Encoding or Content-Encoding header to interpret.</param>
|
||||
/// <param name="type">Specifies the type of header whose contents are in the encoding parameter; valid values are
|
||||
/// <c>header_type::transfer_encoding</c> and <c>header_type::content_encoding</c>.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in construction of an appropriate decompressor,
|
||||
/// if any. If empty or not supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A pointer to a decompressor object that is acceptable per the supplied header, or to nullptr if no matching
|
||||
/// algorithm is found.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP std::unique_ptr<decompress_provider> get_decompressor_from_header(
|
||||
const utility::string_t& encoding,
|
||||
header_types type,
|
||||
const std::vector<std::shared_ptr<decompress_factory>>& factories =
|
||||
std::vector<std::shared_ptr<decompress_factory>>());
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to compose a TE or Accept-Encoding header with supported, and possibly ranked, compression
|
||||
/// algorithms.
|
||||
/// </summary>
|
||||
/// <param name="type">Specifies the type of header to be built; valid values are <c>header_type::te</c> and
|
||||
/// <c>header_type::accept_encoding</c>.</param>
|
||||
/// <param name="factories">A collection of factory objects for use in header construction. If empty or not
|
||||
/// supplied, the set of supported built-in compressors is used.</param>
|
||||
/// <returns>
|
||||
/// A well-formed header, without the header name, specifying the acceptable ranked compression types.
|
||||
/// </returns>
|
||||
_ASYNCRTIMP utility::string_t build_supported_header(header_types type,
|
||||
const std::vector<std::shared_ptr<decompress_factory>>& factories =
|
||||
std::vector<std::shared_ptr<decompress_factory>>());
|
||||
} // namespace details
|
||||
} // namespace compression
|
||||
} // namespace http
|
||||
} // namespace web
|
322
vendor/cpprestsdk/include/cpprest/http_headers.h
vendored
Normal file
322
vendor/cpprestsdk/include/cpprest/http_headers.h
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
template<typename key_type, typename _t>
|
||||
bool bind_impl(const key_type& text, _t& ref)
|
||||
{
|
||||
utility::istringstream_t iss(text);
|
||||
iss.imbue(std::locale::classic());
|
||||
iss >> ref;
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename key_type>
|
||||
bool bind_impl(const key_type& text, utf16string& ref)
|
||||
{
|
||||
ref = utility::conversions::to_utf16string(text);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename key_type>
|
||||
bool bind_impl(const key_type& text, std::string& ref)
|
||||
{
|
||||
ref = utility::conversions::to_utf8string(text);
|
||||
return true;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
/// <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
|
||||
{
|
||||
return utility::details::str_iless(str1, str2);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp> inner_container;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// STL-style typedefs
|
||||
/// </summary>
|
||||
typedef inner_container::key_type key_type;
|
||||
typedef inner_container::key_compare key_compare;
|
||||
typedef inner_container::allocator_type allocator_type;
|
||||
typedef inner_container::size_type size_type;
|
||||
typedef inner_container::difference_type difference_type;
|
||||
typedef inner_container::pointer pointer;
|
||||
typedef inner_container::const_pointer const_pointer;
|
||||
typedef inner_container::reference reference;
|
||||
typedef inner_container::const_reference const_reference;
|
||||
typedef inner_container::iterator iterator;
|
||||
typedef inner_container::const_iterator const_iterator;
|
||||
typedef inner_container::reverse_iterator reverse_iterator;
|
||||
typedef inner_container::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)
|
||||
{
|
||||
auto printedValue = utility::conversions::details::print_string(value);
|
||||
auto& mapVal = m_headers[name];
|
||||
if (mapVal.empty())
|
||||
{
|
||||
mapVal = std::move(printedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapVal.append(_XPLATSTR(", ")).append(std::move(printedValue));
|
||||
}
|
||||
}
|
||||
|
||||
/// <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())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return web::http::details::bind_impl(iter->second, value) || iter->second.empty();
|
||||
}
|
||||
|
||||
/// <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:
|
||||
// Headers are stored in a map with case insensitive key.
|
||||
inner_container m_headers;
|
||||
};
|
||||
} // namespace http
|
||||
} // namespace web
|
342
vendor/cpprestsdk/include/cpprest/http_listener.h
vendored
Normal file
342
vendor/cpprestsdk/include/cpprest/http_listener.h
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: HTTP listener (server-side) APIs
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_HTTP_LISTENER_H
|
||||
#define CASA_HTTP_LISTENER_H
|
||||
|
||||
#include "cpprest/http_msg.h"
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || (_WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt)) || \
|
||||
defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
|
||||
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)), m_backlog(0) {}
|
||||
|
||||
/// <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)
|
||||
, m_backlog(other.m_backlog)
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
, m_ssl_context_callback(other.m_ssl_context_callback)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
/// <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))
|
||||
, m_backlog(std::move(other.m_backlog))
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
, m_ssl_context_callback(std::move(other.m_ssl_context_callback))
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
/// <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;
|
||||
m_backlog = rhs.m_backlog;
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
m_ssl_context_callback = rhs.m_ssl_context_callback;
|
||||
#endif
|
||||
}
|
||||
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);
|
||||
m_backlog = std::move(rhs.m_backlog);
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
m_ssl_context_callback = std::move(rhs.m_ssl_context_callback);
|
||||
#endif
|
||||
}
|
||||
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); }
|
||||
|
||||
/// <summary>
|
||||
/// Get the listen backlog
|
||||
/// </summary>
|
||||
/// <returns>The maximum length of the queue of pending connections, or zero for the implementation
|
||||
/// default.</returns> <remarks>The implementation may not honour this value.</remarks>
|
||||
int backlog() const { return m_backlog; }
|
||||
|
||||
/// <summary>
|
||||
/// Set the listen backlog
|
||||
/// </summary>
|
||||
/// <param name="backlog">The maximum length of the queue of pending connections, or zero for the implementation
|
||||
/// default.</param> <remarks>The implementation may not honour this value.</remarks>
|
||||
void set_backlog(int backlog) { m_backlog = backlog; }
|
||||
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
/// <summary>
|
||||
/// Get the callback of ssl context
|
||||
/// </summary>
|
||||
/// <returns>The function defined by the user of http_listener_config to configure a ssl context.</returns>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the callback of ssl context
|
||||
/// </summary>
|
||||
/// <param name="ssl_context_callback">The function to configure a ssl context which will setup https
|
||||
/// connections.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& ssl_context_callback)
|
||||
{
|
||||
m_ssl_context_callback = ssl_context_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
utility::seconds m_timeout;
|
||||
int m_backlog;
|
||||
#if !defined(_WIN32) || defined(CPPREST_FORCE_HTTP_LISTENER_ASIO)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
#endif
|
||||
};
|
||||
|
||||
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>
|
||||
~http_listener()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
// As a safe guard close the listener if not already done.
|
||||
// Users are required to call close, but this is just a safeguard.
|
||||
try
|
||||
{
|
||||
m_impl->close().wait();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
};
|
||||
|
||||
} // namespace listener
|
||||
} // namespace experimental
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
#endif
|
1632
vendor/cpprestsdk/include/cpprest/http_msg.h
vendored
Normal file
1632
vendor/cpprestsdk/include/cpprest/http_msg.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
554
vendor/cpprestsdk/include/cpprest/interopstream.h
vendored
Normal file
554
vendor/cpprestsdk/include/cpprest/interopstream.h
vendored
Normal file
@ -0,0 +1,554 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.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
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma warning(pop)
|
||||
#endif
|
1836
vendor/cpprestsdk/include/cpprest/json.h
vendored
Normal file
1836
vendor/cpprestsdk/include/cpprest/json.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
576
vendor/cpprestsdk/include/cpprest/oauth1.h
vendored
Normal file
576
vendor/cpprestsdk/include/cpprest/oauth1.h
vendored
Normal file
@ -0,0 +1,576 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 1.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_OAUTH1_H
|
||||
#define CASA_OAUTH1_H
|
||||
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
} // namespace client
|
||||
|
||||
/// 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 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 an initially empty invalid access token.
|
||||
/// </summary>
|
||||
oauth1_token() {}
|
||||
|
||||
/// <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&& paramName, utility::string_t&& paramValue)
|
||||
{
|
||||
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& paramName, const utility::string_t& paramValue)
|
||||
{
|
||||
m_additional_parameters[paramName] = paramValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all additional parameters.
|
||||
/// </summary>
|
||||
void clear_additional_parameters() { m_additional_parameters.clear(); }
|
||||
|
||||
private:
|
||||
friend class oauth1_config;
|
||||
|
||||
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>
|
||||
_ASYNCRTIMP const oauth1_token& token() const;
|
||||
|
||||
/// <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>& parameters)
|
||||
{
|
||||
m_parameters_to_sign.clear();
|
||||
m_parameters_to_sign = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all parameters.
|
||||
/// </summary>
|
||||
void clear_parameters() { m_parameters_to_sign.clear(); }
|
||||
|
||||
/// <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 that will be used by token_from_code and token_from_refresh
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(const web_proxy& proxy) { m_proxy = proxy; }
|
||||
|
||||
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::details::to_string_t(utility::datetime::utc_timestamp());
|
||||
}
|
||||
|
||||
_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;
|
||||
|
||||
web::web_proxy m_proxy;
|
||||
|
||||
utility::nonce_generator m_nonce_generator;
|
||||
bool m_is_authorization_completed;
|
||||
};
|
||||
|
||||
} // namespace 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;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace oauth1
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
555
vendor/cpprestsdk/include/cpprest/oauth2.h
vendored
Normal file
555
vendor/cpprestsdk/include/cpprest/oauth2.h
vendored
Normal file
@ -0,0 +1,555 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* HTTP Library: Oauth 2.0
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_OAUTH2_H
|
||||
#define CASA_OAUTH2_H
|
||||
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_msg.h"
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace http
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
// Forward declaration to avoid circular include dependency.
|
||||
class http_client_config;
|
||||
} // namespace client
|
||||
|
||||
/// 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 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(),
|
||||
utility::string_t user_agent = 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_user_agent(std::move(user_agent))
|
||||
, 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>
|
||||
/// Fetches an access token from the token endpoint using client credentials grant type.
|
||||
/// The task creates an HTTP request to the token_endpoint() using
|
||||
/// client authentication as the authorization grant.
|
||||
/// See: http://tools.ietf.org/html/rfc6749#section-4.4
|
||||
/// </summary>
|
||||
/// <returns>Task that fetches token(s) using client credentials.</returns>
|
||||
pplx::task<void> token_from_client_credentials()
|
||||
{
|
||||
uri_builder ub;
|
||||
ub.append_query(
|
||||
details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, 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); }
|
||||
|
||||
/// <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 that will be used by token_from_code and token_from_refresh
|
||||
/// </summary>
|
||||
/// <param name="proxy">A reference to the web proxy object.</param>
|
||||
void set_proxy(const web_proxy& proxy) { m_proxy = proxy; }
|
||||
|
||||
/// <summary>
|
||||
/// Get user agent to be used in oauth2 flows.
|
||||
/// </summary>
|
||||
/// <returns>User agent string.</returns>
|
||||
const utility::string_t& user_agent() const { return m_user_agent; }
|
||||
/// <summary>
|
||||
/// Set user agent to be used in oauth2 flows.
|
||||
/// If none is provided a default user agent is provided.
|
||||
/// </summary>
|
||||
void set_user_agent(utility::string_t user_agent) { m_user_agent = std::move(user_agent); }
|
||||
|
||||
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;
|
||||
utility::string_t m_user_agent;
|
||||
|
||||
web::web_proxy m_proxy;
|
||||
|
||||
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 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;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace oauth2
|
||||
} // namespace http
|
||||
} // namespace web
|
||||
|
||||
#endif
|
656
vendor/cpprestsdk/include/cpprest/producerconsumerstream.h
vendored
Normal file
656
vendor/cpprestsdk/include/cpprest/producerconsumerstream.h
vendored
Normal file
@ -0,0 +1,656 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
#define CASA_PRODUCER_CONSUMER_STREAMS_H
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
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_mode(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;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// 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;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// 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. Release 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))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#endif
|
598
vendor/cpprestsdk/include/cpprest/rawptrstream.h
vendored
Normal file
598
vendor/cpprestsdk/include/cpprest/rawptrstream.h
vendored
Normal file
@ -0,0 +1,598 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_RAWPTR_STREAMS_H
|
||||
#define CASA_RAWPTR_STREAMS_H
|
||||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
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;
|
||||
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// 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
|
||||
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL != 0
|
||||
// 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));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace streams
|
||||
} // namespace Concurrency
|
||||
|
||||
#endif
|
1761
vendor/cpprestsdk/include/cpprest/streams.h
vendored
Normal file
1761
vendor/cpprestsdk/include/cpprest/streams.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
vendor/cpprestsdk/include/cpprest/uri.h
vendored
Normal file
21
vendor/cpprestsdk/include/cpprest/uri.h
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Protocol independent support for URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#ifndef CASA_URI_H
|
||||
#define CASA_URI_H
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
#include "cpprest/uri_builder.h"
|
||||
|
||||
#endif
|
295
vendor/cpprestsdk/include/cpprest/uri_builder.h
vendored
Normal file
295
vendor/cpprestsdk/include/cpprest/uri_builder.h
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Builder style class for creating URIs.
|
||||
*
|
||||
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/base_uri.h"
|
||||
#include <string>
|
||||
|
||||
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() = default;
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_user_info = uri::encode_uri(user_info, uri::components::user_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_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)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_host = uri::encode_uri(host, uri::components::host);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_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>
|
||||
_ASYNCRTIMP uri_builder& set_port(const utility::string_t& port);
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_path = uri::encode_uri(path, uri::components::path);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_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)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_query = uri::encode_uri(query, uri::components::query);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_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)
|
||||
{
|
||||
if (do_encoding)
|
||||
{
|
||||
m_uri.m_fragment = uri::encode_uri(fragment, uri::components::fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_uri.m_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 the raw contents of the path argument to the path of this uri_builder with no separator de-duplication.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The path argument is appended after adding a '/' separator without regards to the contents of path. If an empty
|
||||
/// string is provided, this function will immediately return without changes to the stored path value. For example:
|
||||
/// if the current contents are "/abc" and path="/xyz", the result will be "/abc//xyz".
|
||||
/// </remarks>
|
||||
/// <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_raw(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(const utility::string_t& name, const T& value, bool do_encoding = true)
|
||||
{
|
||||
if (do_encoding)
|
||||
append_query_encode_impl(name, utility::conversions::details::print_utf8string(value));
|
||||
else
|
||||
append_query_no_encode_impl(name, utility::conversions::details::print_string(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <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() const;
|
||||
|
||||
/// <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() const;
|
||||
|
||||
/// <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:
|
||||
_ASYNCRTIMP void append_query_encode_impl(const utility::string_t& name, const utf8string& value);
|
||||
_ASYNCRTIMP void append_query_no_encode_impl(const utility::string_t& name, const utility::string_t& value);
|
||||
|
||||
details::uri_components m_uri;
|
||||
};
|
||||
} // namespace web
|
10
vendor/cpprestsdk/include/cpprest/version.h
vendored
Normal file
10
vendor/cpprestsdk/include/cpprest/version.h
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
*/
|
||||
#define CPPREST_VERSION_MINOR 10
|
||||
#define CPPREST_VERSION_MAJOR 2
|
||||
#define CPPREST_VERSION_REVISION 19
|
||||
|
||||
#define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION)
|
610
vendor/cpprestsdk/include/cpprest/ws_client.h
vendored
Normal file
610
vendor/cpprestsdk/include/cpprest/ws_client.h
vendored
Normal file
@ -0,0 +1,610 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* 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 "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/details/web_utilities.h"
|
||||
#include "cpprest/http_headers.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "cpprest/ws_msg.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <condition_variable>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#include "boost/asio/ssl.hpp"
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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), m_validate_certificates(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 use for TLS Server Name Indication (SNI).
|
||||
/// </summary>
|
||||
/// <returns>Host name as a string.</returns>
|
||||
const utf8string& server_name() const { return m_sni_hostname; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the User Agent to be used for the connection
|
||||
/// </summary>
|
||||
/// <param name="name">The User Agent to use, as a string.</param>
|
||||
_ASYNCRTIMP void set_user_agent(const utf8string& user_agent);
|
||||
|
||||
/// <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;
|
||||
|
||||
/// <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; }
|
||||
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Sets a callback to enable custom setting of the ssl context, at construction time.
|
||||
/// </summary>
|
||||
/// <param name="callback">A user callback allowing for customization of the ssl context at construction
|
||||
/// time.</param>
|
||||
void set_ssl_context_callback(const std::function<void(boost::asio::ssl::context&)>& callback)
|
||||
{
|
||||
m_ssl_context_callback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user's callback to allow for customization of the ssl context.
|
||||
/// </summary>
|
||||
const std::function<void(boost::asio::ssl::context&)>& get_ssl_context_callback() const
|
||||
{
|
||||
return m_ssl_context_callback;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
web::web_proxy m_proxy;
|
||||
web::credentials m_credentials;
|
||||
web::http::http_headers m_headers;
|
||||
bool m_sni_enabled;
|
||||
utf8string m_sni_hostname;
|
||||
bool m_validate_certificates;
|
||||
#if !defined(_WIN32) || !defined(__cplusplus_winrt)
|
||||
std::function<void(boost::asio::ssl::context&)> m_ssl_context_callback;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// <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 = {}) = 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;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
/// <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 = {})
|
||||
{
|
||||
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 = {})
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace websockets
|
||||
} // namespace web
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
249
vendor/cpprestsdk/include/cpprest/ws_msg.h
vendored
Normal file
249
vendor/cpprestsdk/include/cpprest/ws_msg.h
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
/***
|
||||
* Copyright (C) Microsoft. All rights reserved.
|
||||
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||||
*
|
||||
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*
|
||||
* Websocket incoming and outgoing message definitions.
|
||||
*
|
||||
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
****/
|
||||
#pragma once
|
||||
|
||||
#include "cpprest/details/basic_types.h"
|
||||
|
||||
#if !defined(CPPREST_EXCLUDE_WEBSOCKETS)
|
||||
|
||||
#include "cpprest/asyncrt_utils.h"
|
||||
#include "cpprest/containerstream.h"
|
||||
#include "cpprest/streams.h"
|
||||
#include "cpprest/uri.h"
|
||||
#include "pplx/pplxtasks.h"
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
namespace web
|
||||
{
|
||||
namespace websockets
|
||||
{
|
||||
namespace client
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class winrt_callback_client;
|
||||
class wspp_callback_client;
|
||||
#if defined(__cplusplus_winrt)
|
||||
ref class ReceiveContext;
|
||||
#endif
|
||||
} // namespace details
|
||||
|
||||
/// <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:
|
||||
#if !defined(__cplusplus_winrt)
|
||||
/// <summary>
|
||||
/// Sets the outgoing message to be a ping message.
|
||||
/// This is useful when the client side wants to check whether the server is alive.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing the optional ping message.</param>
|
||||
void set_ping_message(const std::string& data = {})
|
||||
{
|
||||
this->set_message_ping(concurrency::streams::container_buffer<std::string>(data));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the outgoing message to be an unsolicited pong message.
|
||||
/// </summary>
|
||||
/// <param name="data">UTF-8 String containing the optional pong message.</param>
|
||||
void set_pong_message(const std::string& data = {})
|
||||
{
|
||||
this->set_message_pong(concurrency::streams::container_buffer<std::string>(data));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <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; }
|
||||
|
||||
#if !defined(__cplusplus_winrt)
|
||||
void set_message_ping(const concurrency::streams::container_buffer<std::string>& buffer)
|
||||
{
|
||||
m_msg_type = websocket_message_type::ping;
|
||||
m_length = static_cast<size_t>(buffer.size());
|
||||
m_body = buffer;
|
||||
}
|
||||
void set_message_pong(const concurrency::streams::container_buffer<std::string>& buffer)
|
||||
{
|
||||
m_msg_type = websocket_message_type::pong;
|
||||
m_length = static_cast<size_t>(buffer.size());
|
||||
m_body = buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace websockets
|
||||
} // namespace web
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user