mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 14:54:32 +02:00
websocket ping tests
This commit is contained in:
@@ -5,6 +5,7 @@ WebSocket:
|
|||||||
* Fix async_read_some handler signature
|
* Fix async_read_some handler signature
|
||||||
* websocket close fixes and tests
|
* websocket close fixes and tests
|
||||||
* websocket handshake uses coroutine
|
* websocket handshake uses coroutine
|
||||||
|
* websocket ping tests
|
||||||
|
|
||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ template<class... Args>
|
|||||||
stream<NextLayer>::
|
stream<NextLayer>::
|
||||||
stream(Args&&... args)
|
stream(Args&&... args)
|
||||||
: stream_(std::forward<Args>(args)...)
|
: stream_(std::forward<Args>(args)...)
|
||||||
|
, t_(1)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(rd_.buf.max_size() >=
|
BOOST_ASSERT(rd_.buf.max_size() >=
|
||||||
max_control_frame_size);
|
max_control_frame_size);
|
||||||
|
@@ -131,11 +131,11 @@ class stream
|
|||||||
// tokens are used to order reads and writes
|
// tokens are used to order reads and writes
|
||||||
class token
|
class token
|
||||||
{
|
{
|
||||||
unsigned char id_ = 1;
|
unsigned char id_ = 0;
|
||||||
explicit token(unsigned char id) : id_(id) {}
|
|
||||||
public:
|
public:
|
||||||
token() = default;
|
token() = default;
|
||||||
token(token const&) = default;
|
token(token const&) = default;
|
||||||
|
explicit token(unsigned char id) : id_(id) {}
|
||||||
operator bool() const { return id_ != 0; }
|
operator bool() const { return id_ != 0; }
|
||||||
bool operator==(token const& t) { return id_ == t.id_; }
|
bool operator==(token const& t) { return id_ == t.id_; }
|
||||||
bool operator!=(token const& t) { return id_ != t.id_; }
|
bool operator!=(token const& t) { return id_ != t.id_; }
|
||||||
@@ -225,7 +225,7 @@ class stream
|
|||||||
detail::opcode::text; // outgoing message type
|
detail::opcode::text; // outgoing message type
|
||||||
control_cb_type ctrl_cb_; // control callback
|
control_cb_type ctrl_cb_; // control callback
|
||||||
role_type role_; // server or client
|
role_type role_; // server or client
|
||||||
bool failed_; // the connection failed
|
bool failed_ = true; // the connection failed
|
||||||
|
|
||||||
bool rd_close_; // read close frame
|
bool rd_close_; // read close frame
|
||||||
bool wr_close_; // sent close frame
|
bool wr_close_; // sent close frame
|
||||||
|
@@ -860,6 +860,10 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Accept
|
||||||
|
//
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Client>
|
template<class Client>
|
||||||
@@ -1269,8 +1273,139 @@ public:
|
|||||||
{
|
{
|
||||||
doTestAccept(AsyncClient{yield});
|
doTestAccept(AsyncClient{yield});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Bad requests
|
||||||
|
//
|
||||||
|
|
||||||
|
auto const check =
|
||||||
|
[&](error_code const& ev, std::string const& s)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
std::size_t n;
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
|
n = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
n = s.size() / 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
n = s.size() - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream<test::stream> ws{ios_};
|
||||||
|
ws.next_layer().str(
|
||||||
|
s.substr(n, s.size() - n));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ws.accept(
|
||||||
|
boost::asio::buffer(s.data(), n));
|
||||||
|
BEAST_EXPECTS(! ev, ev.message());
|
||||||
|
}
|
||||||
|
catch(system_error const& se)
|
||||||
|
{
|
||||||
|
BEAST_EXPECTS(se.code() == ev, se.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// wrong version
|
||||||
|
check(http::error::end_of_stream,
|
||||||
|
"GET / HTTP/1.0\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// wrong method
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"POST / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// missing Host
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// missing Sec-WebSocket-Key
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// missing Sec-WebSocket-Version
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// wrong Sec-WebSocket-Version
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive,upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 1\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// missing upgrade token
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: HTTP/2\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// missing connection token
|
||||||
|
check(error::handshake_failed,
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
|
// valid request
|
||||||
|
check({},
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: localhost:80\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Connection: upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
||||||
|
"Sec-WebSocket-Version: 13\r\n"
|
||||||
|
"\r\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Close
|
||||||
|
//
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Wrap>
|
template<class Wrap>
|
||||||
@@ -1392,8 +1527,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
doTestCloseAsync()
|
testClose()
|
||||||
{
|
{
|
||||||
|
doTestClose(SyncClient{});
|
||||||
|
|
||||||
|
yield_to([&](yield_context yield)
|
||||||
|
{
|
||||||
|
doTestClose(AsyncClient{yield});
|
||||||
|
});
|
||||||
|
|
||||||
auto const launch =
|
auto const launch =
|
||||||
[&](test::stream stream)
|
[&](test::stream stream)
|
||||||
{
|
{
|
||||||
@@ -1459,58 +1601,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
testClose()
|
|
||||||
{
|
|
||||||
doTestClose(SyncClient{});
|
|
||||||
|
|
||||||
yield_to([&](yield_context yield)
|
|
||||||
{
|
|
||||||
doTestClose(AsyncClient{yield});
|
|
||||||
});
|
|
||||||
|
|
||||||
doTestCloseAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void
|
|
||||||
testRead()
|
|
||||||
{
|
|
||||||
// Read close frames
|
|
||||||
{
|
|
||||||
auto const check =
|
|
||||||
[&](error_code ev, string_view s)
|
|
||||||
{
|
|
||||||
test::stream ts{ios_};
|
|
||||||
stream<test::stream&> ws{ts};
|
|
||||||
launchEchoServerAsync(ts.remote());
|
|
||||||
ws.handshake("localhost", "/");
|
|
||||||
ts.str(s);
|
|
||||||
static_buffer<1> b;
|
|
||||||
error_code ec;
|
|
||||||
ws.read(b, ec);
|
|
||||||
BEAST_EXPECTS(ec == ev, ec.message());
|
|
||||||
};
|
|
||||||
|
|
||||||
// payload length 1
|
|
||||||
check(error::failed,
|
|
||||||
"\x88\x01\x01");
|
|
||||||
|
|
||||||
// invalid close code 1005
|
|
||||||
check(error::failed,
|
|
||||||
"\x88\x02\x03\xed");
|
|
||||||
|
|
||||||
// invalid utf8
|
|
||||||
check(error::failed,
|
|
||||||
"\x88\x06\xfc\x15\x0f\xd7\x73\x43");
|
|
||||||
|
|
||||||
// good utf8
|
|
||||||
check(error::closed,
|
|
||||||
"\x88\x06\xfc\x15utf8");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Client, class Launch>
|
template<class Client, class Launch>
|
||||||
@@ -1597,153 +1687,23 @@ public:
|
|||||||
launchEchoServerAsync(std::move(stream));
|
launchEchoServerAsync(std::move(stream));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void testBadHandshakes()
|
|
||||||
{
|
|
||||||
auto const check =
|
auto const check =
|
||||||
[&](error_code const& ev, std::string const& s)
|
[&](std::string const& s)
|
||||||
|
{
|
||||||
|
stream<test::stream> ws{ios_};
|
||||||
|
ws.next_layer().str(s);
|
||||||
|
ws.next_layer().remote().close();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
for(int i = 0; i < 3; ++i)
|
ws.handshake("localhost:80", "/");
|
||||||
{
|
fail();
|
||||||
std::size_t n;
|
}
|
||||||
switch(i)
|
catch(system_error const& se)
|
||||||
{
|
|
||||||
default:
|
|
||||||
case 0:
|
|
||||||
n = 1;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
n = s.size() / 2;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
n = s.size() - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stream<test::stream> ws{ios_};
|
|
||||||
ws.next_layer().str(
|
|
||||||
s.substr(n, s.size() - n));
|
|
||||||
try
|
|
||||||
{
|
|
||||||
ws.accept(
|
|
||||||
boost::asio::buffer(s.data(), n));
|
|
||||||
BEAST_EXPECTS(! ev, ev.message());
|
|
||||||
}
|
|
||||||
catch(system_error const& se)
|
|
||||||
{
|
|
||||||
BEAST_EXPECTS(se.code() == ev, se.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// wrong version
|
|
||||||
check(http::error::end_of_stream,
|
|
||||||
"GET / HTTP/1.0\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// wrong method
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"POST / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// missing Host
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// missing Sec-WebSocket-Key
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// missing Sec-WebSocket-Version
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// wrong Sec-WebSocket-Version
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive,upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 1\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// missing upgrade token
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: HTTP/2\r\n"
|
|
||||||
"Connection: upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// missing connection token
|
|
||||||
check(error::handshake_failed,
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: keep-alive\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
// valid request
|
|
||||||
check({},
|
|
||||||
"GET / HTTP/1.1\r\n"
|
|
||||||
"Host: localhost:80\r\n"
|
|
||||||
"Upgrade: WebSocket\r\n"
|
|
||||||
"Connection: upgrade\r\n"
|
|
||||||
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
|
|
||||||
"Sec-WebSocket-Version: 13\r\n"
|
|
||||||
"\r\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void testBadResponses()
|
|
||||||
{
|
|
||||||
auto const check =
|
|
||||||
[&](std::string const& s)
|
|
||||||
{
|
{
|
||||||
stream<test::stream> ws{ios_};
|
BEAST_EXPECT(se.code() == error::handshake_failed);
|
||||||
ws.next_layer().str(s);
|
}
|
||||||
ws.next_layer().remote().close();
|
};
|
||||||
try
|
|
||||||
{
|
|
||||||
ws.handshake("localhost:80", "/");
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
catch(system_error const& se)
|
|
||||||
{
|
|
||||||
BEAST_EXPECT(se.code() == error::handshake_failed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// wrong HTTP version
|
// wrong HTTP version
|
||||||
check(
|
check(
|
||||||
"HTTP/1.0 101 Switching Protocols\r\n"
|
"HTTP/1.0 101 Switching Protocols\r\n"
|
||||||
@@ -1805,6 +1765,180 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Ping
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Wrap>
|
||||||
|
void
|
||||||
|
doTestPing(Wrap const& w)
|
||||||
|
{
|
||||||
|
auto const launch =
|
||||||
|
[&](test::stream stream)
|
||||||
|
{
|
||||||
|
launchEchoServer(std::move(stream));
|
||||||
|
//launchEchoServerAsync(std::move(stream));
|
||||||
|
};
|
||||||
|
|
||||||
|
permessage_deflate pmd;
|
||||||
|
pmd.client_enable = false;
|
||||||
|
pmd.server_enable = false;
|
||||||
|
|
||||||
|
// ping
|
||||||
|
doTest(w, pmd, launch, [&](ws_stream_type& ws)
|
||||||
|
{
|
||||||
|
w.ping(ws, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
// pong
|
||||||
|
doTest(w, pmd, launch, [&](ws_stream_type& ws)
|
||||||
|
{
|
||||||
|
w.pong(ws, {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testPing()
|
||||||
|
{
|
||||||
|
doTestPing(SyncClient{});
|
||||||
|
|
||||||
|
yield_to([&](yield_context yield)
|
||||||
|
{
|
||||||
|
doTestPing(AsyncClient{yield});
|
||||||
|
});
|
||||||
|
|
||||||
|
auto const launch =
|
||||||
|
[&](test::stream stream)
|
||||||
|
{
|
||||||
|
launchEchoServer(std::move(stream));
|
||||||
|
//launchEchoServerAsync(std::move(stream));
|
||||||
|
};
|
||||||
|
|
||||||
|
// ping, already closed
|
||||||
|
{
|
||||||
|
stream<test::stream> ws{ios_};
|
||||||
|
error_code ec;
|
||||||
|
ws.ping({}, ec);
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == boost::asio::error::operation_aborted,
|
||||||
|
ec.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
// async_ping, already closed
|
||||||
|
{
|
||||||
|
boost::asio::io_service ios;
|
||||||
|
stream<test::stream> ws{ios};
|
||||||
|
ws.async_ping({},
|
||||||
|
[&](error_code ec)
|
||||||
|
{
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == boost::asio::error::operation_aborted,
|
||||||
|
ec.message());
|
||||||
|
});
|
||||||
|
ios.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// pong, already closed
|
||||||
|
{
|
||||||
|
stream<test::stream> ws{ios_};
|
||||||
|
error_code ec;
|
||||||
|
ws.pong({}, ec);
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == boost::asio::error::operation_aborted,
|
||||||
|
ec.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
// async_pong, already closed
|
||||||
|
{
|
||||||
|
boost::asio::io_service ios;
|
||||||
|
stream<test::stream> ws{ios};
|
||||||
|
ws.async_pong({},
|
||||||
|
[&](error_code ec)
|
||||||
|
{
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == boost::asio::error::operation_aborted,
|
||||||
|
ec.message());
|
||||||
|
});
|
||||||
|
ios.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// suspend on write
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
boost::asio::io_service ios;
|
||||||
|
stream<test::stream> ws{ios, ios_};
|
||||||
|
launch(ws.next_layer().remote());
|
||||||
|
ws.handshake("localhost", "/", ec);
|
||||||
|
BEAST_EXPECTS(! ec, ec.message());
|
||||||
|
std::size_t count = 0;
|
||||||
|
ws.async_write(sbuf("*"),
|
||||||
|
[&](error_code ec)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
BEAST_EXPECTS(! ec, ec.message());
|
||||||
|
});
|
||||||
|
BEAST_EXPECT(ws.wr_block_);
|
||||||
|
ws.async_ping("",
|
||||||
|
[&](error_code ec)
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == boost::asio::error::operation_aborted,
|
||||||
|
ec.message());
|
||||||
|
});
|
||||||
|
ws.async_close({}, [&](error_code){});
|
||||||
|
ios.run();
|
||||||
|
BEAST_EXPECT(count == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Read
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
testRead()
|
||||||
|
{
|
||||||
|
// Read close frames
|
||||||
|
{
|
||||||
|
auto const check =
|
||||||
|
[&](error_code ev, string_view s)
|
||||||
|
{
|
||||||
|
test::stream ts{ios_};
|
||||||
|
stream<test::stream&> ws{ts};
|
||||||
|
launchEchoServerAsync(ts.remote());
|
||||||
|
ws.handshake("localhost", "/");
|
||||||
|
ts.str(s);
|
||||||
|
static_buffer<1> b;
|
||||||
|
error_code ec;
|
||||||
|
ws.read(b, ec);
|
||||||
|
BEAST_EXPECTS(ec == ev, ec.message());
|
||||||
|
};
|
||||||
|
|
||||||
|
// payload length 1
|
||||||
|
check(error::failed,
|
||||||
|
"\x88\x01\x01");
|
||||||
|
|
||||||
|
// invalid close code 1005
|
||||||
|
check(error::failed,
|
||||||
|
"\x88\x02\x03\xed");
|
||||||
|
|
||||||
|
// invalid utf8
|
||||||
|
check(error::failed,
|
||||||
|
"\x88\x06\xfc\x15\x0f\xd7\x73\x43");
|
||||||
|
|
||||||
|
// good utf8
|
||||||
|
check(error::closed,
|
||||||
|
"\x88\x06\xfc\x15utf8");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
testMask(endpoint_type const& ep,
|
testMask(endpoint_type const& ep,
|
||||||
yield_context do_yield)
|
yield_context do_yield)
|
||||||
@@ -2366,6 +2500,8 @@ public:
|
|||||||
|
|
||||||
testAccept();
|
testAccept();
|
||||||
testClose();
|
testClose();
|
||||||
|
testHandshake();
|
||||||
|
testPing();
|
||||||
testRead();
|
testRead();
|
||||||
|
|
||||||
permessage_deflate pmd;
|
permessage_deflate pmd;
|
||||||
@@ -2373,10 +2509,6 @@ public:
|
|||||||
pmd.server_enable = false;
|
pmd.server_enable = false;
|
||||||
|
|
||||||
testOptions();
|
testOptions();
|
||||||
testHandshake();
|
|
||||||
testBadHandshakes();
|
|
||||||
testBadResponses();
|
|
||||||
testClose();
|
|
||||||
testPausation1();
|
testPausation1();
|
||||||
testWriteFrames();
|
testWriteFrames();
|
||||||
testAsyncWriteFrame();
|
testAsyncWriteFrame();
|
||||||
|
Reference in New Issue
Block a user