28 #define BOOST_TEST_MODULE hybi_13_processor 29 #include <boost/test/unit_test.hpp> 97 , p(false,server,msg_manager,rng) {}
99 websocketpp::lib::error_code ec;
110 , p(false,server,msg_manager,rng) {}
112 websocketpp::lib::error_code
ec;
123 std::string handshake =
"GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
125 env.
req.consume(handshake.c_str(),handshake.size());
133 BOOST_CHECK_NO_THROW( u = env.
p.
get_uri(env.
req) );
135 BOOST_CHECK_EQUAL(u->get_secure(),
false);
136 BOOST_CHECK_EQUAL(u->get_host(),
"www.example.com");
137 BOOST_CHECK_EQUAL(u->get_resource(),
"/");
142 BOOST_CHECK_EQUAL(env.
res.get_header(
"Connection"),
"upgrade");
143 BOOST_CHECK_EQUAL(env.
res.get_header(
"Upgrade"),
"websocket");
144 BOOST_CHECK_EQUAL(env.
res.get_header(
"Sec-WebSocket-Accept"),
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=");
150 std::string handshake =
"POST / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
152 env.
req.consume(handshake.c_str(),handshake.size());
162 std::string handshake =
"GET / HTTP/1.0\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
164 env.
req.consume(handshake.c_str(),handshake.size());
174 std::string handshake =
"GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
176 env.
req.consume(handshake.c_str(),handshake.size());
186 std::string handshake =
"GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\n\r\n";
188 env.
req.consume(handshake.c_str(),handshake.size());
198 std::string handshake =
"GET / HTTP/1.1\r\nHost: www.example.com:70000\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: foo\r\n\r\n";
200 env.
req.consume(handshake.c_str(),handshake.size());
205 BOOST_CHECK( !env.
p.
get_uri(env.
req)->get_valid() );
223 uint8_t frame[2] = {0x82, 0x00};
228 size_t ret1 = env1.
p.
consume(frame,2,env1.
ec);
230 BOOST_CHECK_EQUAL( ret1, 2 );
231 BOOST_CHECK( !env1.
ec );
232 BOOST_CHECK_EQUAL( env1.
p.
ready(), true );
237 BOOST_CHECK_EQUAL( env2.p.consume(frame,1,env2.ec), 1 );
238 BOOST_CHECK( !env2.ec );
239 BOOST_CHECK_EQUAL( env2.p.ready(), false );
241 BOOST_CHECK_EQUAL( env2.p.consume(frame+1,1,env2.ec), 1 );
242 BOOST_CHECK( !env2.ec );
243 BOOST_CHECK_EQUAL( env2.p.ready(), true );
249 uint8_t frame[4] = {0x82, 0x02, 0x2A, 0x2A};
252 BOOST_CHECK_EQUAL( env.
p.
consume(frame,4,env.
ec), 4 );
253 BOOST_CHECK( !env.
ec );
254 BOOST_CHECK_EQUAL( env.
p.
ready(), true );
259 BOOST_CHECK_EQUAL( foo->get_payload(),
"**" );
266 uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
271 std::fill_n(frame+4,126,0x2A);
274 BOOST_CHECK_EQUAL( env.
p.
consume(frame,130,env.
ec), 130 );
275 BOOST_CHECK( !env.
ec );
276 BOOST_CHECK_EQUAL( env.
p.
ready(), true );
281 BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
287 uint8_t frame[130] = {0x82, 0x7E, 0x00, 0x7E};
288 std::fill_n(frame+4,126,0x2A);
291 BOOST_CHECK_EQUAL( env.
p.
consume(frame,130,env.
ec), 130 );
292 BOOST_CHECK( !env.
ec );
293 BOOST_CHECK_EQUAL( env.
p.
ready(), true );
298 BOOST_CHECK_EQUAL( foo->get_payload().size(), 126 );
304 uint8_t frame[130] = {0x88, 0x7E, 0x00, 0x7E};
305 std::fill_n(frame+4,126,0x2A);
308 BOOST_CHECK_GT( env.
p.
consume(frame,130,env.
ec), 0 );
310 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
314 uint8_t frame[3][2] = {{0x90, 0x00},
318 for (
int i = 0; i < 3; i++) {
322 BOOST_CHECK_GT( env.
p.
consume(frame[i],2,env.
ec), 0 );
324 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
330 uint8_t frame[10][2] = {{0x83, 0x00},
341 for (
int i = 0; i < 10; i++) {
345 BOOST_CHECK_GT( env.
p.
consume(frame[i],2,env.
ec), 0 );
347 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
354 uint8_t frame[2] = {0x08, 0x00};
357 BOOST_CHECK_GT( env.
p.
consume(frame,2,env.
ec), 0 );
359 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
366 uint8_t frame0[6] = {0x02, 0x01, 0x2A, 0x80, 0x01, 0x2A};
367 uint8_t frame1[8] = {0x02, 0x01, 0x2A, 0x89, 0x00, 0x80, 0x01, 0x2A};
371 BOOST_CHECK_EQUAL( env0.
p.
consume(frame0,6,env0.
ec), 6 );
372 BOOST_CHECK( !env0.
ec );
373 BOOST_CHECK_EQUAL( env0.
p.
ready(), true );
374 BOOST_CHECK_EQUAL( env0.
p.
get_message()->get_payload(),
"**" );
378 BOOST_CHECK_EQUAL( env0.
p.
consume(frame0,3,env0.
ec), 3 );
379 BOOST_CHECK( !env0.
ec );
380 BOOST_CHECK_EQUAL( env0.
p.
ready(), false );
381 BOOST_CHECK_EQUAL( env0.
p.
consume(frame0+3,3,env0.
ec), 3 );
382 BOOST_CHECK( !env0.
ec );
383 BOOST_CHECK_EQUAL( env0.
p.
ready(), true );
384 BOOST_CHECK_EQUAL( env0.
p.
get_message()->get_payload(),
"**" );
388 BOOST_CHECK_EQUAL( env0.
p.
consume(frame1,8,env0.
ec), 5 );
389 BOOST_CHECK( !env0.
ec );
390 BOOST_CHECK_EQUAL( env0.
p.
ready(), true );
392 BOOST_CHECK_EQUAL( env0.
p.
consume(frame1+5,3,env0.
ec), 3 );
393 BOOST_CHECK( !env0.
ec );
394 BOOST_CHECK_EQUAL( env0.
p.
ready(), true );
395 BOOST_CHECK_EQUAL( env0.
p.
get_message()->get_payload(),
"**" );
399 BOOST_CHECK_GT( env0.
p.
consume(frame0+3,3,env0.
ec), 0);
404 BOOST_CHECK_EQUAL( env1.
p.
consume(frame0,3,env1.
ec), 3);
405 BOOST_CHECK( !env1.
ec );
406 BOOST_CHECK_GT( env1.
p.
consume(frame0,3,env1.
ec), 0);
413 uint8_t frame[2] = {0x82, 0x00};
416 BOOST_CHECK_GT( env.
p.
consume(frame,2,env.
ec), 0 );
418 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
424 uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
427 BOOST_CHECK_GT( env.
p.
consume(frame,8,env.
ec), 0 );
429 BOOST_CHECK_EQUAL( env.
p.
ready(), false );
435 uint8_t frame[8] = {0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xD5};
438 BOOST_CHECK_EQUAL( env.
p.
consume(frame,8,env.
ec), 8 );
439 BOOST_CHECK( !env.
ec );
440 BOOST_CHECK_EQUAL( env.
p.
ready(), true );
441 BOOST_CHECK_EQUAL( env.
p.
get_message()->get_payload(),
"**" );
447 uint8_t frame0[14] = {0x02, 0x81, 0xAB, 0x23, 0x98, 0x45, 0x81,
448 0x80, 0x81, 0xB8, 0x34, 0x12, 0xFF, 0x92};
452 BOOST_CHECK_EQUAL( env.
p.
consume(frame0,14,env.
ec), 14 );
453 BOOST_CHECK( !env.
ec );
454 BOOST_CHECK_EQUAL( env.
p.
ready(), true );
455 BOOST_CHECK_EQUAL( env.
p.
get_message()->get_payload(),
"**" );
474 for (
int i = 0; i < 0xF; i++) {
499 uint8_t frame0[10] = {0x82, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
502 BOOST_CHECK_EQUAL( env.
p.
consume(frame0,10,env.
ec), 6 );
511 uint8_t frame0[8] = {0x02, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
512 uint8_t frame1[9] = {0x80, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
515 BOOST_CHECK_EQUAL( env.
p.
consume(frame0,8,env.
ec), 8 );
516 BOOST_CHECK( !env.
ec );
519 BOOST_CHECK_EQUAL( env.
p.
consume(frame1,9,env.
ec), 6 );
532 BOOST_CHECK_EQUAL( env.
req.get_method(),
"GET" );
533 BOOST_CHECK_EQUAL( env.
req.get_version(),
"HTTP/1.1");
534 BOOST_CHECK_EQUAL( env.
req.get_uri(),
"/");
536 BOOST_CHECK_EQUAL( env.
req.get_header(
"Host"),
"localhost");
537 BOOST_CHECK_EQUAL( env.
req.get_header(
"Sec-WebSocket-Version"),
"13");
538 BOOST_CHECK_EQUAL( env.
req.get_header(
"Connection"),
"Upgrade");
539 BOOST_CHECK_EQUAL( env.
req.get_header(
"Upgrade"),
"websocket");
560 std::string res =
"HTTP/1.1 404 Not Found\r\n\r\n";
561 env.
res.consume(res.data(),res.size());
569 std::string res =
"HTTP/1.1 101 Switching Protocols\r\n\r\n";
570 env.
res.consume(res.data(),res.size());
578 std::string res =
"HTTP/1.1 101 Switching Protocols\r\nUpgrade: foo, wEbsOckEt\r\n\r\n";
579 env.
res.consume(res.data(),res.size());
587 std::string res =
"HTTP/1.1 101 Switching Protocols\r\nUpgrade: foo, wEbsOckEt\r\nConnection: bar, UpGrAdE\r\n\r\n";
588 env.
res.consume(res.data(),res.size());
596 env.
req.append_header(
"Sec-WebSocket-Key",
"dGhlIHNhbXBsZSBub25jZQ==");
598 std::string res =
"HTTP/1.1 101 Switching Protocols\r\nUpgrade: foo, wEbsOckEt\r\nConnection: bar, UpGrAdE\r\nSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n";
599 env.
res.consume(res.data(),res.size());
607 env.
req.replace_header(
"Sec-WebSocket-Extensions",
"");
609 std::pair<websocketpp::lib::error_code,std::string> neg_results;
613 BOOST_CHECK_EQUAL( neg_results.second,
"" );
619 env.
req.replace_header(
"Sec-WebSocket-Extensions",
"");
621 std::pair<websocketpp::lib::error_code,std::string> neg_results;
624 BOOST_CHECK( !neg_results.first );
625 BOOST_CHECK_EQUAL( neg_results.second,
"" );
631 env.
req.replace_header(
"Sec-WebSocket-Extensions",
"foo");
633 std::pair<websocketpp::lib::error_code,std::string> neg_results;
636 BOOST_CHECK( !neg_results.first );
637 BOOST_CHECK_EQUAL( neg_results.second,
"" );
642 std::vector<std::string> subps;
645 BOOST_CHECK_EQUAL( subps.size(), 0 );
650 std::vector<std::string> subps;
652 env.
req.replace_header(
"Sec-WebSocket-Protocol",
"foo");
655 BOOST_REQUIRE_EQUAL( subps.size(), 1 );
656 BOOST_CHECK_EQUAL( subps[0],
"foo" );
661 std::vector<std::string> subps;
663 env.
req.replace_header(
"Sec-WebSocket-Protocol",
"foo,bar");
666 BOOST_REQUIRE_EQUAL( subps.size(), 2 );
667 BOOST_CHECK_EQUAL( subps[0],
"foo" );
668 BOOST_CHECK_EQUAL( subps[1],
"bar" );
673 std::vector<std::string> subps;
675 env.
req.replace_header(
"Sec-WebSocket-Protocol",
"foo,bar,,,,");
678 BOOST_CHECK_EQUAL( subps.size(), 0 );
684 env.
req.replace_header(
"Sec-WebSocket-Extensions",
685 "permessage-deflate; client_max_window_bits");
687 std::pair<websocketpp::lib::error_code,std::string> neg_results;
690 BOOST_CHECK( !neg_results.first );
691 BOOST_CHECK_EQUAL( neg_results.second,
"permessage-deflate" );
bool is_control(value v)
Check if an opcode is for a control frame.
bool ready() const
Checks if there is a message ready.
int get_version() const
Get the protocol version of this processor.
websocketpp::config::asio_tls_client::message_type::ptr message_ptr
stub_config::request_type req
websocketpp::extensions::permessage_deflate::enabled< permessage_deflate_config > permessage_deflate_type
lib::error_code validate_handshake(request_type const &r) const
validate a WebSocket handshake request for this version
stub_config::message_type::ptr message_ptr
bool is_websocket_handshake(request_type &r)
Determine whether or not a generic HTTP request is a WebSocket handshake.
Clients may not send unmasked frames.
void set_max_message_size(size_t new_value)
Set maximum message size.
core::con_msg_manager_type con_msg_manager_type
con_msg_manager_type::ptr msg_manager
websocketpp::processor::hybi13< stub_config > p
websocketpp::http::parser::response response_type
websocketpp::random::none::int_generator< uint32_t > rng_type
lib::error_code process_handshake(request_type const &req, std::string const &subprotocol, response_type &res) const
Calculate the appropriate response for this websocket request.
websocketpp::message_buffer::message< websocketpp::message_buffer::alloc::con_msg_manager > message_type
int get_websocket_version(request_type &r)
Extract the version from a WebSocket handshake request.
stub_config::request_type req
Illegal use of reserved bit.
lib::error_code extract_subprotocols(request_type const &req, std::vector< std::string > &subprotocol_list)
Extracts requested subprotocols from a handshake request.
stub_config::response_type res
stub_config::con_msg_manager_type con_msg_manager_type
websocketpp::processor::hybi13< stub_config_ext > p
websocketpp::message_buffer::alloc::con_msg_manager< message_type > con_msg_manager_type
bool invalid(value code)
Test whether a close code is invalid on the wire.
websocketpp::extensions::permessage_deflate::disabled< permessage_deflate_config > permessage_deflate_type
websocketpp::random::none::int_generator< uint32_t > rng_type
Continuation without message.
Stores, parses, and manipulates HTTP responses.
Stub class for use when disabling permessage_deflate extension.
stub_config::con_msg_manager_type::ptr msg_manager
processor_setup_ext(bool server)
uri_ptr get_uri(request_type const &request) const
Extracts client uri from a handshake request.
Extension related operation was ignored because extensions are disabled.
err_str_pair negotiate_extensions(request_type const &request)
Initializes extensions based on the Sec-WebSocket-Extensions header.
websocketpp::http::parser::response response_type
message_ptr get_message()
Retrieves the most recently processed message.
lib::error_code make_error_code(error::processor_errors e)
Create an error code with the given value and the processor category.
stub_config::rng_type rng
size_t consume(uint8_t *buf, size_t len, lib::error_code &ec)
Process new websocket connection bytes.
websocketpp::lib::error_code ec
Thread safe stub "random" integer generator.
Error parsing subprotocols.
virtual err_str_pair negotiate_extensions(request_type const &)
Initializes extensions based on the Sec-WebSocket-Extensions header.
Represents a buffer for a single WebSocket message.
stub_config::response_type res
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
stub_config::request_type request_type
websocketpp::http::parser::request request_type
Servers may not send masked frames.
Fragmented control message.
Processor encountered a message that was too large.
websocketpp::processor::hybi00< stub_config > p
stub_config_ext::request_type request_type
core::request_type request_type
Extension specific config.
BOOST_AUTO_TEST_CASE(exact_match)
static const size_t max_message_size
Stores, parses, and manipulates HTTP requests.
virtual lib::error_code prepare_data_frame(message_ptr in, message_ptr out)
Prepare a message for writing.
stub_config::rng_type rng
Opcode was invalid for requested operation.
websocketpp::lib::error_code ec
core::response_type response_type
websocketpp::message_buffer::alloc::con_msg_manager< message_type > con_msg_manager_type
lib::error_code client_handshake_request(request_type &, uri_ptr, std::vector< std::string > const &) const
Fill in a set of request headers for a client connection request.
con_msg_manager_type::ptr msg_manager
static const bool enable_extensions
Extension related config.
websocketpp::http::parser::request request_type
static uint16_t const uri_default_port
Default port for ws://.
lib::error_code validate_server_handshake_response(request_type const &, response_type &) const
Validate the server's response to an outgoing handshake request.
A connection message manager that allocates a new message for each request.
processor_setup(bool server)
The processor method was called with invalid arguments.
websocketpp::message_buffer::message< websocketpp::message_buffer::alloc::con_msg_manager > message_type