Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ping and pong to message handler #1143

Merged
merged 17 commits into from
Jun 13, 2019
26 changes: 22 additions & 4 deletions Release/include/cpprest/ws_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,23 @@ class websocket_outgoing_message
public:
#if !defined(__cplusplus_winrt)
/// <summary>
/// Sets a the outgoing message to be an unsolicited pong message.
/// Sets the outgoing message to be a ping message.
/// This is useful when the client side wants to check whether the server is alive.
AlexandreK38 marked this conversation as resolved.
Show resolved Hide resolved
AlexandreK38 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
void set_pong_message() { this->set_message_pong(); }
/// <param name="data">UTF-8 String containing the optional ping message.</param>
void set_ping_message(const std::string& data = {})
{
this->set_message_ping(concurrency::streams::container_buffer<std::string>(data));
}

AlexandreK38 marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>
/// Sets the outgoing message to be an unsolicited pong message.
/// </summary>
/// <param name="data">UTF-8 String containing the optional pong message.</param>
void set_pong_message(const std::string& data = {})
{
this->set_message_pong(concurrency::streams::container_buffer<std::string>(data));
}
#endif

/// <summary>
Expand Down Expand Up @@ -140,9 +153,14 @@ class websocket_outgoing_message
const pplx::task_completion_event<void>& body_sent() const { return m_body_sent; }

#if !defined(__cplusplus_winrt)
void set_message_pong()
void set_message_ping(const concurrency::streams::container_buffer<std::string>& buffer)
{
m_msg_type = websocket_message_type::ping;
m_length = static_cast<size_t>(buffer.size());
m_body = buffer;
}
void set_message_pong(const concurrency::streams::container_buffer<std::string>& buffer)
{
concurrency::streams::container_buffer<std::string> buffer("");
m_msg_type = websocket_message_type::pong;
m_length = static_cast<size_t>(buffer.size());
m_body = buffer;
Expand Down
45 changes: 43 additions & 2 deletions Release/src/websockets/client/ws_client_wspp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,35 @@ class wspp_callback_client : public websocket_client_callback_impl,
}
});

client.set_ping_handler(
[this](websocketpp::connection_hdl, const std::string& msg) {
if (m_external_message_handler)
{
_ASSERTE(m_state >= CONNECTED && m_state < CLOSED);
websocket_incoming_message incoming_msg;

incoming_msg.m_msg_type = websocket_message_type::ping;
incoming_msg.m_body = concurrency::streams::container_buffer<std::string>(msg);

m_external_message_handler(incoming_msg);
}
return true;
});

client.set_pong_handler(
[this](websocketpp::connection_hdl, const std::string& msg) {
if (m_external_message_handler)
{
_ASSERTE(m_state >= CONNECTED && m_state < CLOSED);
websocket_incoming_message incoming_msg;

incoming_msg.m_msg_type = websocket_message_type::pong;
incoming_msg.m_body = concurrency::streams::container_buffer<std::string>(msg);

m_external_message_handler(incoming_msg);
}
});

client.set_close_handler([this](websocketpp::connection_hdl con_hdl) {
_ASSERTE(m_state != CLOSED);
shutdown_wspp_impl<WebsocketConfigType>(con_hdl, false);
Expand Down Expand Up @@ -434,12 +463,13 @@ class wspp_callback_client : public websocket_client_callback_impl,
{
case websocket_message_type::text_message:
case websocket_message_type::binary_message:
case websocket_message_type::ping:
case websocket_message_type::pong: break;
default: return pplx::task_from_exception<void>(websocket_exception("Message Type not supported."));
}

const auto length = msg.m_length;
if (length == 0 && msg.m_msg_type != websocket_message_type::pong)
if (length == 0 && msg.m_msg_type != websocket_message_type::ping && msg.m_msg_type != websocket_message_type::pong)
{
return pplx::task_from_exception<void>(websocket_exception("Cannot send empty message."));
}
Expand Down Expand Up @@ -694,7 +724,18 @@ class wspp_callback_client : public websocket_client_callback_impl,
case websocket_message_type::binary_message:
client.send(this_client->m_con, sp_allocated.get(), length, websocketpp::frame::opcode::binary, ec);
break;
case websocket_message_type::pong: client.pong(this_client->m_con, "", ec); break;
case websocket_message_type::ping:
{
std::string s(reinterpret_cast<char*>(sp_allocated.get()), length);
client.ping(this_client->m_con, s, ec);
break;
}
case websocket_message_type::pong:
{
std::string s(reinterpret_cast<char*>(sp_allocated.get()), length);
client.pong(this_client->m_con, s, ec);
break;
}
default:
// This case should have already been filtered above.
std::abort();
Expand Down
51 changes: 47 additions & 4 deletions Release/tests/functional/websockets/client/send_msg_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,32 @@ SUITE(send_msg_tests)
}

template<class SocketClientClass>
pplx::task<void> send_pong_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server)
pplx::task<void> send_ping_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server,
const std::string& body = "")
{
server.next_message(
[](test_websocket_msg msg) // Handler to verify the message sent by the client.
{ websocket_asserts::assert_message_equals(msg, "", test_websocket_message_type::WEB_SOCKET_PONG_TYPE); });
[body](test_websocket_msg msg) // Handler to verify the message sent by the client.
{ websocket_asserts::assert_message_equals(msg, body, test_websocket_message_type::WEB_SOCKET_PING_TYPE); });

client.connect(uri).wait();

websocket_outgoing_message msg;
msg.set_pong_message();
msg.set_ping_message(body);
return client.send(msg);
}

template<class SocketClientClass>
pplx::task<void> send_pong_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server,
const std::string& body = "")
{
server.next_message(
[body](test_websocket_msg msg) // Handler to verify the message sent by the client.
{ websocket_asserts::assert_message_equals(msg, body, test_websocket_message_type::WEB_SOCKET_PONG_TYPE); });

client.connect(uri).wait();

websocket_outgoing_message msg;
msg.set_pong_message(body);
return client.send(msg);
}

Expand Down Expand Up @@ -493,6 +509,24 @@ SUITE(send_msg_tests)
}

#if !defined(__cplusplus_winrt)
// Send a ping message to the server
TEST_FIXTURE(uri_address, send_ping_msg)
{
test_websocket_server server;
websocket_client client;
send_ping_msg_helper(client, m_uri, server).wait();
client.close().wait();
}

// Send a ping message to the server with a body
TEST_FIXTURE(uri_address, send_ping_msg_body)
{
test_websocket_server server;
websocket_client client;
send_ping_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait();
client.close().wait();
}

// Send an unsolicited pong message to the server
TEST_FIXTURE(uri_address, send_pong_msg)
{
Expand All @@ -502,6 +536,15 @@ SUITE(send_msg_tests)
client.close().wait();
}

// Send an unsolicited pong message to the server with a body
TEST_FIXTURE(uri_address, send_pong_msg_body)
{
test_websocket_server server;
websocket_client client;
send_pong_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait();
client.close().wait();
}

// Send an unsolicited pong message to the server with websocket_callback_client
TEST_FIXTURE(uri_address, send_pong_msg_callback_client)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ class _test_websocket_server
m_server_connected.set_exception(std::runtime_error("Connection attempt failed."));
});

m_srv.set_ping_handler([this](websocketpp::connection_hdl hdl, std::string input) {
auto fn = m_test_srv->get_next_message_handler();
assert(fn);

test_websocket_msg wsmsg;

wsmsg.set_data(std::vector<uint8_t>(input.begin(), input.end()));

wsmsg.set_msg_type(WEB_SOCKET_PING_TYPE);
fn(wsmsg);

return true;
});

m_srv.set_pong_handler([this](websocketpp::connection_hdl hdl, std::string input) {
auto fn = m_test_srv->get_next_message_handler();
assert(fn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ enum test_websocket_message_type
WEB_SOCKET_UTF8_MESSAGE_TYPE,
WEB_SOCKET_UTF8_FRAGMENT_TYPE,
WEB_SOCKET_CLOSE_TYPE,
WEB_SOCKET_PING_TYPE,
WEB_SOCKET_PONG_TYPE
};

Expand Down