summaryrefslogtreecommitdiff
path: root/boost/beast/websocket/detail/mask.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/websocket/detail/mask.hpp')
-rw-r--r--boost/beast/websocket/detail/mask.hpp177
1 files changed, 29 insertions, 148 deletions
diff --git a/boost/beast/websocket/detail/mask.hpp b/boost/beast/websocket/detail/mask.hpp
index 92ea0a4238..8958d793b8 100644
--- a/boost/beast/websocket/detail/mask.hpp
+++ b/boost/beast/websocket/detail/mask.hpp
@@ -11,6 +11,7 @@
#define BOOST_BEAST_WEBSOCKET_DETAIL_MASK_HPP
#include <boost/beast/core/detail/config.hpp>
+#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/asio/buffer.hpp>
#include <array>
#include <climits>
@@ -83,179 +84,59 @@ using maskgen = maskgen_t<std::minstd_rand>;
//------------------------------------------------------------------------------
-using prepared_key =
- std::conditional<sizeof(void*) == 8,
- std::uint64_t, std::uint32_t>::type;
+using prepared_key = std::array<unsigned char, 4>;
inline
void
-prepare_key(std::uint32_t& prepared, std::uint32_t key)
+prepare_key(prepared_key& prepared, std::uint32_t key)
{
- prepared = key;
+ prepared[0] = (key >> 0) & 0xff;
+ prepared[1] = (key >> 8) & 0xff;
+ prepared[2] = (key >> 16) & 0xff;
+ prepared[3] = (key >> 24) & 0xff;
}
-inline
+template<std::size_t N>
void
-prepare_key(std::uint64_t& prepared, std::uint32_t key)
-{
- prepared =
- (static_cast<std::uint64_t>(key) << 32) | key;
-}
-
-template<class T>
-inline
-typename std::enable_if<std::is_integral<T>::value, T>::type
-ror(T t, unsigned n = 1)
+rol(std::array<unsigned char, N>& v, std::size_t n)
{
- auto constexpr bits =
- static_cast<unsigned>(
- sizeof(T) * CHAR_BIT);
- n &= bits-1;
- return static_cast<T>((t << (bits - n)) | (
- static_cast<typename std::make_unsigned<T>::type>(t) >> n));
+ auto v0 = v;
+ for(std::size_t i = 0; i < v.size(); ++i )
+ v[i] = v0[(i + n) % v.size()];
}
-// 32-bit optimized
-//
-template<class = void>
-void
-mask_inplace_fast(
- boost::asio::mutable_buffer const& b,
- std::uint32_t& key)
-{
- auto n = b.size();
- auto p = reinterpret_cast<std::uint8_t*>(b.data());
- if(n >= sizeof(key))
- {
- // Bring p to 4-byte alignment
- auto const i = reinterpret_cast<
- std::uintptr_t>(p) & (sizeof(key)-1);
- switch(i)
- {
- case 1: p[2] ^= static_cast<std::uint8_t>(key >> 16); BOOST_BEAST_FALLTHROUGH;
- case 2: p[1] ^= static_cast<std::uint8_t>(key >> 8); BOOST_BEAST_FALLTHROUGH;
- case 3: p[0] ^= static_cast<std::uint8_t>(key);
- {
- auto const d = static_cast<unsigned>(sizeof(key) - i);
- key = ror(key, 8*d);
- n -= d;
- p += d;
- BOOST_BEAST_FALLTHROUGH;
- }
- default:
- break;
- }
- }
-
- // Mask 4 bytes at a time
- for(auto i = n / sizeof(key); i; --i)
- {
- *reinterpret_cast<
- std::uint32_t*>(p) ^= key;
- p += sizeof(key);
- }
-
- // Leftovers
- n &= sizeof(key)-1;
- switch(n)
- {
- case 3: p[2] ^= static_cast<std::uint8_t>(key >> 16); BOOST_BEAST_FALLTHROUGH;
- case 2: p[1] ^= static_cast<std::uint8_t>(key >> 8); BOOST_BEAST_FALLTHROUGH;
- case 1: p[0] ^= static_cast<std::uint8_t>(key);
- key = ror(key, static_cast<unsigned>(8*n));
- BOOST_BEAST_FALLTHROUGH;
- default:
- break;
- }
-}
-
-// 64-bit optimized
+// Apply mask in place
//
-template<class = void>
+inline
void
-mask_inplace_fast(
- boost::asio::mutable_buffer const& b,
- std::uint64_t& key)
+mask_inplace(boost::asio::mutable_buffer& b, prepared_key& key)
{
auto n = b.size();
- auto p = reinterpret_cast<std::uint8_t*>(b.data());
- if(n >= sizeof(key))
+ auto mask = key; // avoid aliasing
+ auto p = reinterpret_cast<unsigned char*>(b.data());
+ while(n >= 4)
{
- // Bring p to 8-byte alignment
- auto const i = reinterpret_cast<
- std::uintptr_t>(p) & (sizeof(key)-1);
- switch(i)
- {
- case 1: p[6] ^= static_cast<std::uint8_t>(key >> 48);
- case 2: p[5] ^= static_cast<std::uint8_t>(key >> 40);
- case 3: p[4] ^= static_cast<std::uint8_t>(key >> 32);
- case 4: p[3] ^= static_cast<std::uint8_t>(key >> 24);
- case 5: p[2] ^= static_cast<std::uint8_t>(key >> 16);
- case 6: p[1] ^= static_cast<std::uint8_t>(key >> 8);
- case 7: p[0] ^= static_cast<std::uint8_t>(key);
- {
- auto const d = static_cast<
- unsigned>(sizeof(key) - i);
- key = ror(key, 8*d);
- n -= d;
- p += d;
- }
- default:
- break;
- }
+ for(int i = 0; i < 4; ++i)
+ p[i] ^= mask[i];
+ p += 4;
+ n -= 4;
}
-
- // Mask 8 bytes at a time
- for(auto i = n / sizeof(key); i; --i)
+ if(n > 0)
{
- *reinterpret_cast<
- std::uint64_t*>(p) ^= key;
- p += sizeof(key);
+ for(std::size_t i = 0; i < n; ++i)
+ p[i] ^= mask[i];
+ rol(key, n);
}
-
- // Leftovers
- n &= sizeof(key)-1;
- switch(n)
- {
- case 7: p[6] ^= static_cast<std::uint8_t>(key >> 48);
- case 6: p[5] ^= static_cast<std::uint8_t>(key >> 40);
- case 5: p[4] ^= static_cast<std::uint8_t>(key >> 32);
- case 4: p[3] ^= static_cast<std::uint8_t>(key >> 24);
- case 3: p[2] ^= static_cast<std::uint8_t>(key >> 16);
- case 2: p[1] ^= static_cast<std::uint8_t>(key >> 8);
- case 1: p[0] ^= static_cast<std::uint8_t>(key);
- key = ror(key, static_cast<unsigned>(8*n));
- default:
- break;
- }
-}
-
-inline
-void
-mask_inplace(
- boost::asio::mutable_buffer const& b,
- std::uint32_t& key)
-{
- mask_inplace_fast(b, key);
-}
-
-inline
-void
-mask_inplace(
- boost::asio::mutable_buffer const& b,
- std::uint64_t& key)
-{
- mask_inplace_fast(b, key);
}
// Apply mask in place
//
template<class MutableBuffers, class KeyType>
void
-mask_inplace(
- MutableBuffers const& bs, KeyType& key)
+mask_inplace(MutableBuffers const& bs, KeyType& key)
{
- for(boost::asio::mutable_buffer b : bs)
+ for(boost::asio::mutable_buffer b :
+ beast::detail::buffers_range(bs))
mask_inplace(b, key);
}