mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Various fixes, warnings:
* Fix sig_wait
* Fix websocket strict aliasing warning
* Fix invokable strict aliasing
* Silence fread warning in examples
* Silence integer conversion warnings
* Build parser-bench as test
* Disable unused variable warning for asio:
Caused by static variables declared in <boost/asio/error.hpp>
No known workaround.
This commit is contained in:
1
Jamroot
1
Jamroot
@@ -62,6 +62,7 @@ project beast
|
||||
<runtime-link>shared
|
||||
<debug-symbols>on
|
||||
<toolset>gcc:<cxxflags>-std=c++11
|
||||
<toolset>gcc:<cxxflags>-Wno-unused-variable
|
||||
<toolset>clang:<cxxflags>-std=c++11
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
|
||||
|
||||
@@ -80,7 +80,8 @@ struct file_body
|
||||
operator()(resume_context&&, error_code&, Write&& write)
|
||||
{
|
||||
buf_len_ = std::min(size_ - offset_, sizeof(buf_));
|
||||
fread(buf_, 1, sizeof(buf_), file_);
|
||||
auto const nread = fread(buf_, 1, sizeof(buf_), file_);
|
||||
(void)nread;
|
||||
offset_ += buf_len_;
|
||||
write(boost::asio::buffer(buf_, buf_len_));
|
||||
return offset_ >= size_;
|
||||
|
||||
@@ -32,18 +32,11 @@ sig_wait()
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::signal_set signals(
|
||||
ios, SIGINT, SIGTERM);
|
||||
std::mutex m;
|
||||
bool stop = false;
|
||||
std::condition_variable cv;
|
||||
signals.async_wait(
|
||||
[&](boost::system::error_code const&, int)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
stop = true;
|
||||
cv.notify_one();
|
||||
});
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
cv.wait(lock, [&]{ return stop; });
|
||||
ios.run();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -408,6 +408,191 @@ private:
|
||||
bool
|
||||
needs_eof(std::false_type) const;
|
||||
|
||||
template<class C>
|
||||
class has_on_method_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_method(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_method =
|
||||
std::integral_constant<bool, has_on_method_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_uri_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_uri =
|
||||
std::integral_constant<bool, has_on_uri_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_reason_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_reason(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_reason =
|
||||
std::integral_constant<bool, has_on_reason_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_request_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_request(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_request =
|
||||
std::integral_constant<bool, has_on_request_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_response_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_response(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_response =
|
||||
std::integral_constant<bool, has_on_response_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_field_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_field =
|
||||
std::integral_constant<bool, has_on_field_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_value_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_value =
|
||||
std::integral_constant<bool, has_on_value_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_headers_t
|
||||
{
|
||||
template<class T, class R = std::is_same<int,
|
||||
decltype(std::declval<T>().on_headers(
|
||||
std::declval<error_code&>()))>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_headers =
|
||||
std::integral_constant<bool, has_on_headers_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_body_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_body(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_body =
|
||||
std::integral_constant<bool, has_on_body_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_complete_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_complete(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_complete =
|
||||
std::integral_constant<bool, has_on_complete_t<C>::value>;
|
||||
|
||||
void call_on_method(error_code& ec,
|
||||
boost::string_ref const& s, std::true_type)
|
||||
{
|
||||
@@ -423,7 +608,7 @@ private:
|
||||
boost::string_ref const& s)
|
||||
{
|
||||
call_on_method(ec, s, std::integral_constant<bool,
|
||||
isRequest && detail::has_on_method<Derived>::value>{});
|
||||
isRequest && has_on_method<Derived>::value>{});
|
||||
}
|
||||
|
||||
void call_on_uri(error_code& ec,
|
||||
@@ -440,7 +625,7 @@ private:
|
||||
void call_on_uri(error_code& ec, boost::string_ref const& s)
|
||||
{
|
||||
call_on_uri(ec, s, std::integral_constant<bool,
|
||||
isRequest && detail::has_on_uri<Derived>::value>{});
|
||||
isRequest && has_on_uri<Derived>::value>{});
|
||||
}
|
||||
|
||||
void call_on_reason(error_code& ec,
|
||||
@@ -457,7 +642,7 @@ private:
|
||||
void call_on_reason(error_code& ec, boost::string_ref const& s)
|
||||
{
|
||||
call_on_reason(ec, s, std::integral_constant<bool,
|
||||
! isRequest && detail::has_on_reason<Derived>::value>{});
|
||||
! isRequest && has_on_reason<Derived>::value>{});
|
||||
}
|
||||
|
||||
void call_on_request(error_code& ec, std::true_type)
|
||||
@@ -471,7 +656,8 @@ private:
|
||||
|
||||
void call_on_request(error_code& ec)
|
||||
{
|
||||
call_on_request(ec, detail::has_on_request<Derived>{});
|
||||
call_on_request(ec, std::integral_constant<bool,
|
||||
isRequest && has_on_request<Derived>::value>{});
|
||||
}
|
||||
|
||||
void call_on_response(error_code& ec, std::true_type)
|
||||
@@ -485,7 +671,8 @@ private:
|
||||
|
||||
void call_on_response(error_code& ec)
|
||||
{
|
||||
call_on_response(ec, detail::has_on_response<Derived>{});
|
||||
call_on_response(ec, std::integral_constant<bool,
|
||||
! isRequest && has_on_response<Derived>::value>{});
|
||||
}
|
||||
|
||||
void call_on_field(error_code& ec,
|
||||
@@ -501,7 +688,7 @@ private:
|
||||
|
||||
void call_on_field(error_code& ec, boost::string_ref const& s)
|
||||
{
|
||||
call_on_field(ec, s, detail::has_on_field<Derived>{});
|
||||
call_on_field(ec, s, has_on_field<Derived>{});
|
||||
}
|
||||
|
||||
void call_on_value(error_code& ec,
|
||||
@@ -517,7 +704,7 @@ private:
|
||||
|
||||
void call_on_value(error_code& ec, boost::string_ref const& s)
|
||||
{
|
||||
call_on_value(ec, s, detail::has_on_value<Derived>{});
|
||||
call_on_value(ec, s, has_on_value<Derived>{});
|
||||
}
|
||||
|
||||
int call_on_headers(error_code& ec, std::true_type)
|
||||
@@ -532,7 +719,7 @@ private:
|
||||
|
||||
int call_on_headers(error_code& ec)
|
||||
{
|
||||
return call_on_headers(ec, detail::has_on_headers<Derived>{});
|
||||
return call_on_headers(ec, has_on_headers<Derived>{});
|
||||
}
|
||||
|
||||
void call_on_body(error_code& ec,
|
||||
@@ -548,7 +735,7 @@ private:
|
||||
|
||||
void call_on_body(error_code& ec, boost::string_ref const& s)
|
||||
{
|
||||
call_on_body(ec, s, detail::has_on_body<Derived>{});
|
||||
call_on_body(ec, s, has_on_body<Derived>{});
|
||||
}
|
||||
|
||||
void call_on_complete(error_code& ec, std::true_type)
|
||||
@@ -562,7 +749,7 @@ private:
|
||||
|
||||
void call_on_complete(error_code& ec)
|
||||
{
|
||||
call_on_complete(ec, detail::has_on_complete<Derived>{});
|
||||
call_on_complete(ec, has_on_complete<Derived>{});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -196,191 +196,6 @@ parser_str_t<_>::transfer_encoding[18];
|
||||
|
||||
using parser_str = parser_str_t<>;
|
||||
|
||||
template<class C>
|
||||
class has_on_method_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_method(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_method =
|
||||
std::integral_constant<bool, has_on_method_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_uri_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_uri =
|
||||
std::integral_constant<bool, has_on_uri_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_reason_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_reason(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_reason =
|
||||
std::integral_constant<bool, has_on_reason_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_request_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_request(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_request =
|
||||
std::integral_constant<bool, has_on_request_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_response_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_response(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_response =
|
||||
std::integral_constant<bool, has_on_response_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_field_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_field =
|
||||
std::integral_constant<bool, has_on_field_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_value_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_uri(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_value =
|
||||
std::integral_constant<bool, has_on_value_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_headers_t
|
||||
{
|
||||
template<class T, class R = std::is_same<int,
|
||||
decltype(std::declval<T>().on_headers(
|
||||
std::declval<error_code&>()))>>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_headers =
|
||||
std::integral_constant<bool, has_on_headers_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_body_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_body(
|
||||
std::declval<boost::string_ref const&>(),
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_body =
|
||||
std::integral_constant<bool, has_on_body_t<C>::value>;
|
||||
|
||||
template<class C>
|
||||
class has_on_complete_t
|
||||
{
|
||||
template<class T, class R =
|
||||
decltype(std::declval<T>().on_complete(
|
||||
std::declval<error_code&>()),
|
||||
std::true_type{})>
|
||||
static R check(int);
|
||||
template <class>
|
||||
static std::false_type check(...);
|
||||
using type = decltype(check<C>(0));
|
||||
public:
|
||||
static bool const value = type::value;
|
||||
};
|
||||
template<class C>
|
||||
using has_on_complete =
|
||||
std::integral_constant<bool, has_on_complete_t<C>::value>;
|
||||
|
||||
} // detail
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
@@ -43,6 +43,9 @@ write(void const* data, std::size_t size, error_code& ec)
|
||||
using beast::http::detail::to_value_char;
|
||||
using beast::http::detail::unhex;
|
||||
|
||||
if(size == 0 && s_ != s_closed)
|
||||
return 0;
|
||||
|
||||
auto begin =
|
||||
reinterpret_cast<char const*>(data);
|
||||
auto const end = begin + size;
|
||||
@@ -338,6 +341,7 @@ write(void const* data, std::size_t size, error_code& ec)
|
||||
if(cb(&self::call_on_reason))
|
||||
return used();
|
||||
pos_ = 0;
|
||||
s_ = s_res_status;
|
||||
break;
|
||||
|
||||
case s_res_status:
|
||||
|
||||
@@ -118,7 +118,7 @@ private:
|
||||
}
|
||||
return false;
|
||||
};
|
||||
while(false)
|
||||
do
|
||||
{
|
||||
if(m("DELETE", method_t::http_delete))
|
||||
break;
|
||||
@@ -187,6 +187,7 @@ private:
|
||||
if(m("UNLINK", method_t::http_unlink))
|
||||
break;
|
||||
}
|
||||
while(false);
|
||||
|
||||
m_.url = std::move(this->uri_);
|
||||
|
||||
|
||||
60
include/beast/websocket/detail/endian.hpp
Normal file
60
include/beast/websocket/detail/endian.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_WEBSOCKET_DETAIL_ENDIAN_HPP
|
||||
#define BEAST_WEBSOCKET_DETAIL_ENDIAN_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
std::uint16_t
|
||||
big_uint16_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return (p[0]<<8) + p[1];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
big_uint64_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
(static_cast<std::uint64_t>(p[0])<<56) +
|
||||
(static_cast<std::uint64_t>(p[1])<<48) +
|
||||
(static_cast<std::uint64_t>(p[2])<<40) +
|
||||
(static_cast<std::uint64_t>(p[3])<<32) +
|
||||
(static_cast<std::uint64_t>(p[4])<<24) +
|
||||
(static_cast<std::uint64_t>(p[5])<<16) +
|
||||
(static_cast<std::uint64_t>(p[6])<< 8) +
|
||||
p[7];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint32_t
|
||||
little_uint32_to_native(void const* buf)
|
||||
{
|
||||
auto const p = reinterpret_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
p[0] +
|
||||
(static_cast<std::uint64_t>(p[1])<< 8) +
|
||||
(static_cast<std::uint64_t>(p[2])<<16) +
|
||||
(static_cast<std::uint64_t>(p[3])<<24);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // websocket
|
||||
} // beast
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <beast/websocket/rfc6455.hpp>
|
||||
#include <beast/websocket/static_string.hpp>
|
||||
#include <beast/websocket/detail/endian.hpp>
|
||||
#include <beast/websocket/detail/utf8_checker.hpp>
|
||||
#include <beast/consuming_buffers.hpp>
|
||||
#include <beast/static_streambuf.hpp>
|
||||
@@ -244,8 +245,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[2];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.len = reinterpret_cast<
|
||||
big_uint16_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.len = big_uint16_to_native(&b[0]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 126)
|
||||
{
|
||||
@@ -259,8 +265,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[8];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.len = reinterpret_cast<
|
||||
big_uint64_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.len = big_uint64_to_native(&b[0]);
|
||||
#endif
|
||||
// length not canonical
|
||||
if(fh.len < 65536)
|
||||
{
|
||||
@@ -275,8 +286,13 @@ read_fh2(frame_header& fh, Streambuf& sb,
|
||||
std::uint8_t b[4];
|
||||
assert(buffer_size(sb.data()) >= sizeof(b));
|
||||
sb.consume(buffer_copy(buffer(b), sb.data()));
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
fh.key = reinterpret_cast<
|
||||
little_uint32_buf_t const*>(&b[0])->value();
|
||||
#else
|
||||
fh.key = little_uint32_to_native(&b[0]);
|
||||
#endif
|
||||
}
|
||||
code = close_code::none;
|
||||
}
|
||||
@@ -327,9 +343,15 @@ read(close_reason& cr,
|
||||
{
|
||||
std::uint8_t b[2];
|
||||
buffer_copy(buffer(b), cb);
|
||||
#if 0
|
||||
// Causes strict-aliasing warning in gcc
|
||||
cr.code = static_cast<close_code>(
|
||||
reinterpret_cast<
|
||||
big_uint16_buf_t const*>(&b[0])->value());
|
||||
#else
|
||||
cr.code = static_cast<close_code>(
|
||||
big_uint16_to_native(&b[0]));
|
||||
#endif
|
||||
cb.consume(2);
|
||||
n -= 2;
|
||||
if(! is_valid(cr.code))
|
||||
|
||||
@@ -68,10 +68,9 @@ class invokable
|
||||
void operator()(){}
|
||||
};
|
||||
|
||||
using buf_type = std::uint8_t[
|
||||
sizeof(holder<exemplar>)];
|
||||
using buf_type = char[sizeof(holder<exemplar>)];
|
||||
|
||||
bool b_ = false;
|
||||
base* base_ = nullptr;
|
||||
alignas(holder<exemplar>) buf_type buf_;
|
||||
|
||||
public:
|
||||
@@ -81,7 +80,7 @@ public:
|
||||
// Engaged invokables must be invoked before
|
||||
// destruction otherwise the io_service
|
||||
// invariants are broken w.r.t completions.
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -90,12 +89,12 @@ public:
|
||||
invokable& operator=(invokable const&) = delete;
|
||||
|
||||
invokable(invokable&& other)
|
||||
: b_(other.b_)
|
||||
{
|
||||
if(other.b_)
|
||||
if(other.base_)
|
||||
{
|
||||
other.get().move(buf_);
|
||||
other.b_ = false;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
other.base_->move(buf_);
|
||||
other.base_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,13 +104,13 @@ public:
|
||||
// Engaged invokables must be invoked before
|
||||
// assignment otherwise the io_service
|
||||
// invariants are broken w.r.t completions.
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
|
||||
if(other.b_)
|
||||
if(other.base_)
|
||||
{
|
||||
b_ = true;
|
||||
other.get().move(buf_);
|
||||
other.b_ = false;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
other.base_->move(buf_);
|
||||
other.base_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -123,19 +122,13 @@ public:
|
||||
void
|
||||
maybe_invoke()
|
||||
{
|
||||
if(b_)
|
||||
if(base_)
|
||||
{
|
||||
b_ = false;
|
||||
get()();
|
||||
auto const basep = base_;
|
||||
base_ = nullptr;
|
||||
(*basep)();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base&
|
||||
get()
|
||||
{
|
||||
return *reinterpret_cast<base*>(&buf_[0]);
|
||||
}
|
||||
};
|
||||
|
||||
template<class F>
|
||||
@@ -144,9 +137,9 @@ invokable::emplace(F&& f)
|
||||
{
|
||||
static_assert(sizeof(buf_type) >= sizeof(holder<F>),
|
||||
"buffer too small");
|
||||
assert(! b_);
|
||||
assert(! base_);
|
||||
::new(buf_) holder<F>(std::forward<F>(f));
|
||||
b_ = true;
|
||||
base_ = reinterpret_cast<base*>(&buf_[0]);
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
@@ -58,7 +58,7 @@ unit-test websocket-tests :
|
||||
websocket/teardown.cpp
|
||||
;
|
||||
|
||||
exe parser-bench :
|
||||
unit-test parser-bench :
|
||||
main.cpp
|
||||
http/nodejs_parser.cpp
|
||||
http/parser_bench.cpp
|
||||
|
||||
@@ -33,6 +33,80 @@ class basic_parser_test : public beast::detail::unit_test::suite
|
||||
std::mt19937 rng_;
|
||||
|
||||
public:
|
||||
struct cb_req_checker
|
||||
{
|
||||
bool method = false;
|
||||
bool uri = false;
|
||||
bool request = false;
|
||||
};
|
||||
|
||||
struct cb_res_checker
|
||||
{
|
||||
bool reason = false;
|
||||
bool response = false;
|
||||
};
|
||||
|
||||
template<bool isRequest>
|
||||
struct cb_checker
|
||||
: public basic_parser<isRequest, cb_checker<isRequest>>
|
||||
, std::conditional<isRequest,
|
||||
cb_req_checker, cb_res_checker>::type
|
||||
|
||||
{
|
||||
bool field = false;
|
||||
bool value = false;
|
||||
bool headers = false;
|
||||
bool body = false;
|
||||
bool complete = false;
|
||||
|
||||
private:
|
||||
friend class basic_parser<isRequest, cb_checker<isRequest>>;
|
||||
|
||||
void on_method(boost::string_ref const&, error_code&)
|
||||
{
|
||||
this->method = true;
|
||||
}
|
||||
void on_uri(boost::string_ref const&, error_code&)
|
||||
{
|
||||
this->uri = true;
|
||||
}
|
||||
void on_reason(boost::string_ref const&, error_code&)
|
||||
{
|
||||
this->reason = true;
|
||||
}
|
||||
void on_request(error_code&)
|
||||
{
|
||||
this->request = true;
|
||||
}
|
||||
void on_response(error_code&)
|
||||
{
|
||||
this->response = true;
|
||||
}
|
||||
void on_field(boost::string_ref const&, error_code&)
|
||||
{
|
||||
field = true;
|
||||
}
|
||||
void on_value(boost::string_ref const&, error_code&)
|
||||
{
|
||||
value = true;
|
||||
}
|
||||
int on_headers(error_code&)
|
||||
{
|
||||
headers = true;
|
||||
return 0;
|
||||
}
|
||||
void on_body(boost::string_ref const&, error_code&)
|
||||
{
|
||||
body = true;
|
||||
}
|
||||
void on_complete(error_code&)
|
||||
{
|
||||
complete = true;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static
|
||||
std::string
|
||||
escaped_string(boost::string_ref const& s)
|
||||
@@ -106,6 +180,54 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testCallbacks()
|
||||
{
|
||||
{
|
||||
cb_checker<true> p;
|
||||
error_code ec;
|
||||
std::string const s =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
if( expect(! ec))
|
||||
{
|
||||
expect(p.method);
|
||||
expect(p.uri);
|
||||
expect(p.request);
|
||||
expect(p.field);
|
||||
expect(p.value);
|
||||
expect(p.headers);
|
||||
expect(p.body);
|
||||
expect(p.complete);
|
||||
}
|
||||
}
|
||||
{
|
||||
cb_checker<false> p;
|
||||
error_code ec;
|
||||
std::string const s =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
if( expect(! ec))
|
||||
{
|
||||
expect(p.reason);
|
||||
expect(p.response);
|
||||
expect(p.field);
|
||||
expect(p.value);
|
||||
expect(p.headers);
|
||||
expect(p.body);
|
||||
expect(p.complete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the entire input buffer as a valid message,
|
||||
// then parse in two pieces of all possible lengths.
|
||||
//
|
||||
@@ -497,6 +619,7 @@ public:
|
||||
|
||||
void run() override
|
||||
{
|
||||
testCallbacks();
|
||||
testVersion();
|
||||
testFlags();
|
||||
testUpgrade();
|
||||
|
||||
@@ -7,3 +7,63 @@
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <beast/http/parser.hpp>
|
||||
|
||||
#include <beast/http/headers.hpp>
|
||||
#include <beast/http/string_body.hpp>
|
||||
#include <beast/detail/unit_test/suite.hpp>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
class parser_test : public beast::detail::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void run() override
|
||||
{
|
||||
{
|
||||
error_code ec;
|
||||
parser<true, string_body,
|
||||
basic_headers<std::allocator<char>>> p;
|
||||
std::string const s =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"User-Agent: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
expect(! ec);
|
||||
expect(p.complete());
|
||||
auto m = p.release();
|
||||
expect(m.method == method_t::http_get);
|
||||
expect(m.url == "/");
|
||||
expect(m.version == 11);
|
||||
expect(m.headers["User-Agent"] == "test");
|
||||
expect(m.body == "*");
|
||||
}
|
||||
{
|
||||
error_code ec;
|
||||
parser<false, string_body,
|
||||
basic_headers<std::allocator<char>>> p;
|
||||
std::string const s =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Server: test\r\n"
|
||||
"Content-Length: 1\r\n"
|
||||
"\r\n"
|
||||
"*";
|
||||
p.write(s.data(), s.size(), ec);
|
||||
expect(! ec);
|
||||
expect(p.complete());
|
||||
auto m = p.release();
|
||||
expect(m.status == 200);
|
||||
expect(m.reason == "OK");
|
||||
expect(m.version == 11);
|
||||
expect(m.headers["Server"] == "test");
|
||||
expect(m.body == "*");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(parser,http,beast);
|
||||
|
||||
} // http
|
||||
} // beast
|
||||
|
||||
@@ -36,30 +36,28 @@ public:
|
||||
}
|
||||
|
||||
corpus
|
||||
build_corpus(std::size_t N, std::true_type)
|
||||
build_corpus(std::size_t n, std::true_type)
|
||||
{
|
||||
corpus v;
|
||||
v.resize(N);
|
||||
message_fuzz mg;
|
||||
for(std::size_t i = 0; i < N; ++i)
|
||||
for(std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
mg.request(v[i]);
|
||||
//log << debug::buffers_to_string(v[i].data()) << "\r";
|
||||
size_ += v[i].size();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
corpus
|
||||
build_corpus(std::size_t N, std::false_type)
|
||||
build_corpus(std::size_t n, std::false_type)
|
||||
{
|
||||
corpus v;
|
||||
v.resize(N);
|
||||
message_fuzz mg;
|
||||
for(std::size_t i = 0; i < N; ++i)
|
||||
for(std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
mg.response(v[i]);
|
||||
//log << debug::buffers_to_string(v[i].data()) << "\r";
|
||||
size_ += v[i].size();
|
||||
}
|
||||
return v;
|
||||
|
||||
Reference in New Issue
Block a user