void read_fh2(frame_header& fh, DynamicBuffer& db, role_type role, close_code::value& code) { using boost::asio::buffer; using boost::asio::buffer_copy; using boost::asio::buffer_size; using namespace boost::endian; switch(fh.len) { case 126: { std::uint8_t b[2]; assert(buffer_size(db.data()) >= sizeof(b)); db.consume(buffer_copy(buffer(b), db.data())); fh.len = big_uint16_to_native(&b[0]); // length not canonical if(fh.len < 126) { code = close_code::protocol_error; return; } break; } case 127: { std::uint8_t b[8]; assert(buffer_size(db.data()) >= sizeof(b)); db.consume(buffer_copy(buffer(b), db.data())); fh.len = big_uint64_to_native(&b[0]); // length not canonical if(fh.len < 65536) { code = close_code::protocol_error; return; } break; } } if(fh.mask) { std::uint8_t b[4]; assert(buffer_size(db.data()) >= sizeof(b)); db.consume(buffer_copy(buffer(b), db.data())); fh.key = little_uint32_to_native(&b[0]); } else { // initialize this otherwise operator== breaks fh.key = 0; } code = close_code::none; }
void testNeedMore() { error_code ec; std::size_t used; { DynamicBuffer b; parser_type<true> p; ostream(b) << "GET / HTTP/1.1\r\n"; used = p.put(b.data(), ec); BEAST_EXPECTS(ec == error::need_more, ec.message()); b.consume(used); ec.assign(0, ec.category()); ostream(b) << "User-Agent: test\r\n" "\r\n"; used = p.put(b.data(), ec); BEAST_EXPECTS(! ec, ec.message()); b.consume(used); BEAST_EXPECT(p.is_done()); BEAST_EXPECT(p.is_header_done()); } }
static bool match(DynamicBuffer& db, char const(&s)[N]) { using boost::asio::buffer; using boost::asio::buffer_copy; if(db.size() < N-1) return false; static_string<N-1> t; t.resize(N-1); buffer_copy(buffer(t.data(), t.size()), db.data()); if(t != s) return false; db.consume(N-1); return true; }
std::size_t read_fh1(frame_header& fh, DynamicBuffer& db, role_type role, close_code::value& code) { using boost::asio::buffer; using boost::asio::buffer_copy; using boost::asio::buffer_size; std::uint8_t b[2]; assert(buffer_size(db.data()) >= sizeof(b)); db.consume(buffer_copy(buffer(b), db.data())); std::size_t need; fh.len = b[1] & 0x7f; switch(fh.len) { case 126: need = 2; break; case 127: need = 8; break; default: need = 0; } fh.mask = (b[1] & 0x80) != 0; if(fh.mask) need += 4; fh.op = static_cast<opcode>(b[0] & 0x0f); fh.fin = (b[0] & 0x80) != 0; fh.rsv1 = (b[0] & 0x40) != 0; fh.rsv2 = (b[0] & 0x20) != 0; fh.rsv3 = (b[0] & 0x10) != 0; // invalid length for control message if(is_control(fh.op) && fh.len > 125) { code = close_code::protocol_error; return 0; } // reserved bits not cleared if(fh.rsv1 || fh.rsv2 || fh.rsv3) { code = close_code::protocol_error; return 0; } // reserved opcode if(is_reserved(fh.op)) { code = close_code::protocol_error; return 0; } // fragmented control message if(is_control(fh.op) && ! fh.fin) { code = close_code::protocol_error; return 0; } // unmasked frame from client if(role == role_type::server && ! fh.mask) { code = close_code::protocol_error; return 0; } // masked frame from server if(role == role_type::client && fh.mask) { code = close_code::protocol_error; return 0; } code = close_code::none; return need; }