Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:32

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_FRAME_HPP
0011 #define BOOST_BEAST_WEBSOCKET_DETAIL_FRAME_HPP
0012 
0013 #include <boost/beast/core/buffer_traits.hpp>
0014 #include <boost/beast/websocket/error.hpp>
0015 #include <boost/beast/websocket/rfc6455.hpp>
0016 #include <boost/beast/websocket/detail/utf8_checker.hpp>
0017 #include <boost/beast/core/flat_static_buffer.hpp>
0018 #include <boost/asio/buffer.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/endian/conversion.hpp>
0021 #include <cstdint>
0022 
0023 namespace boost {
0024 namespace beast {
0025 namespace websocket {
0026 namespace detail {
0027 
0028 // frame header opcodes
0029 enum class opcode : std::uint8_t
0030 {
0031     cont    = 0,
0032     text    = 1,
0033     binary  = 2,
0034     rsv3    = 3,
0035     rsv4    = 4,
0036     rsv5    = 5,
0037     rsv6    = 6,
0038     rsv7    = 7,
0039     close   = 8,
0040     ping    = 9,
0041     pong    = 10,
0042     crsvb   = 11,
0043     crsvc   = 12,
0044     crsvd   = 13,
0045     crsve   = 14,
0046     crsvf   = 15
0047 };
0048 
0049 // Contents of a WebSocket frame header
0050 struct frame_header
0051 {
0052     std::uint64_t len;
0053     std::uint32_t key;
0054     opcode op;
0055     bool fin  : 1;
0056     bool mask : 1;
0057     bool rsv1 : 1;
0058     bool rsv2 : 1;
0059     bool rsv3 : 1;
0060 };
0061 
0062 // holds the largest possible frame header
0063 using fh_buffer = flat_static_buffer<14>;
0064 
0065 // holds the largest possible control frame
0066 using frame_buffer =
0067     flat_static_buffer< 2 + 8 + 4 + 125 >;
0068 
0069 inline
0070 bool constexpr
0071 is_reserved(opcode op)
0072 {
0073     return
0074         (op >= opcode::rsv3  && op <= opcode::rsv7) ||
0075         (op >= opcode::crsvb && op <= opcode::crsvf);
0076 }
0077 
0078 inline
0079 bool constexpr
0080 is_valid(opcode op)
0081 {
0082     return op <= opcode::crsvf;
0083 }
0084 
0085 inline
0086 bool constexpr
0087 is_control(opcode op)
0088 {
0089     return op >= opcode::close;
0090 }
0091 
0092 inline
0093 bool
0094 is_valid_close_code(std::uint16_t v)
0095 {
0096     switch(v)
0097     {
0098     case close_code::normal:            // 1000
0099     case close_code::going_away:        // 1001
0100     case close_code::protocol_error:    // 1002
0101     case close_code::unknown_data:      // 1003
0102     case close_code::bad_payload:       // 1007
0103     case close_code::policy_error:      // 1008
0104     case close_code::too_big:           // 1009
0105     case close_code::needs_extension:   // 1010
0106     case close_code::internal_error:    // 1011
0107     case close_code::service_restart:   // 1012
0108     case close_code::try_again_later:   // 1013
0109         return true;
0110 
0111     // explicitly reserved
0112     case close_code::reserved1:         // 1004
0113     case close_code::no_status:         // 1005
0114     case close_code::abnormal:          // 1006
0115     case close_code::reserved2:         // 1014
0116     case close_code::reserved3:         // 1015
0117         return false;
0118     }
0119     // reserved
0120     if(v >= 1016 && v <= 2999)
0121         return false;
0122     // not used
0123     if(v <= 999)
0124         return false;
0125     return true;
0126 }
0127 
0128 //------------------------------------------------------------------------------
0129 
0130 // Write frame header to dynamic buffer
0131 //
0132 template<class DynamicBuffer>
0133 void
0134 write(DynamicBuffer& db, frame_header const& fh)
0135 {
0136     std::size_t n;
0137     std::uint8_t b[14];
0138     b[0] = (fh.fin ? 0x80 : 0x00) | static_cast<std::uint8_t>(fh.op);
0139     if(fh.rsv1)
0140         b[0] |= 0x40;
0141     if(fh.rsv2)
0142         b[0] |= 0x20;
0143     if(fh.rsv3)
0144         b[0] |= 0x10;
0145     b[1] = fh.mask ? 0x80 : 0x00;
0146     if(fh.len <= 125)
0147     {
0148         b[1] |= fh.len;
0149         n = 2;
0150     }
0151     else if(fh.len <= 65535)
0152     {
0153         b[1] |= 126;
0154         auto len_be = endian::native_to_big(
0155             static_cast<std::uint16_t>(fh.len));
0156         std::memcpy(&b[2], &len_be, sizeof(len_be));
0157         n = 4;
0158     }
0159     else
0160     {
0161         b[1] |= 127;
0162         auto len_be = endian::native_to_big(
0163             static_cast<std::uint64_t>(fh.len));
0164         std::memcpy(&b[2], &len_be, sizeof(len_be));
0165         n = 10;
0166     }
0167     if(fh.mask)
0168     {
0169         auto key_le = endian::native_to_little(
0170             static_cast<std::uint32_t>(fh.key));
0171         std::memcpy(&b[n], &key_le, sizeof(key_le));
0172         n += 4;
0173     }
0174     db.commit(net::buffer_copy(
0175         db.prepare(n), net::buffer(b)));
0176 }
0177 
0178 // Read data from buffers
0179 // This is for ping and pong payloads
0180 //
0181 template<class Buffers>
0182 void
0183 read_ping(ping_data& data, Buffers const& bs)
0184 {
0185     BOOST_ASSERT(buffer_bytes(bs) <= data.max_size());
0186     data.resize(buffer_bytes(bs));
0187     net::buffer_copy(net::mutable_buffer{
0188         data.data(), data.size()}, bs);
0189 }
0190 
0191 // Read close_reason, return true on success
0192 // This is for the close payload
0193 //
0194 template<class Buffers>
0195 void
0196 read_close(
0197     close_reason& cr,
0198     Buffers const& bs,
0199     error_code& ec)
0200 {
0201     auto const n = buffer_bytes(bs);
0202     BOOST_ASSERT(n <= 125);
0203     if(n == 0)
0204     {
0205         cr = close_reason{};
0206         ec = {};
0207         return;
0208     }
0209     if(n == 1)
0210     {
0211         // invalid payload size == 1
0212         BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_size);
0213         return;
0214     }
0215 
0216     std::uint16_t code_be;
0217     cr.reason.resize(n - 2);
0218     std::array<net::mutable_buffer, 2> out_bufs{{
0219         net::mutable_buffer(&code_be, sizeof(code_be)),
0220         net::mutable_buffer(&cr.reason[0], n - 2)}};
0221 
0222     net::buffer_copy(out_bufs, bs);
0223 
0224     cr.code = endian::big_to_native(code_be);
0225     if(! is_valid_close_code(cr.code))
0226     {
0227         // invalid close code
0228         BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_code);
0229         return;
0230     }
0231 
0232     if(n > 2 && !check_utf8(
0233         cr.reason.data(), cr.reason.size()))
0234     {
0235         // not valid utf-8
0236         BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_payload);
0237         return;
0238     }
0239     ec = {};
0240 }
0241 
0242 } // detail
0243 } // websocket
0244 } // beast
0245 } // boost
0246 
0247 #endif