Skip to content

Commit 0f45af1

Browse files
Kumamon38BillyONeal
authored andcommitted
add ping and pong to message handler (#1143)
Add ping and pong to message handler, and optional pong timeout
1 parent 36e030a commit 0f45af1

File tree

5 files changed

+127
-10
lines changed

5 files changed

+127
-10
lines changed

Release/include/cpprest/ws_msg.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,23 @@ class websocket_outgoing_message
6060
public:
6161
#if !defined(__cplusplus_winrt)
6262
/// <summary>
63-
/// Sets a the outgoing message to be an unsolicited pong message.
63+
/// Sets the outgoing message to be a ping message.
6464
/// This is useful when the client side wants to check whether the server is alive.
6565
/// </summary>
66-
void set_pong_message() { this->set_message_pong(); }
66+
/// <param name="data">UTF-8 String containing the optional ping message.</param>
67+
void set_ping_message(const std::string& data = {})
68+
{
69+
this->set_message_ping(concurrency::streams::container_buffer<std::string>(data));
70+
}
71+
72+
/// <summary>
73+
/// Sets the outgoing message to be an unsolicited pong message.
74+
/// </summary>
75+
/// <param name="data">UTF-8 String containing the optional pong message.</param>
76+
void set_pong_message(const std::string& data = {})
77+
{
78+
this->set_message_pong(concurrency::streams::container_buffer<std::string>(data));
79+
}
6780
#endif
6881

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

142155
#if !defined(__cplusplus_winrt)
143-
void set_message_pong()
156+
void set_message_ping(const concurrency::streams::container_buffer<std::string>& buffer)
157+
{
158+
m_msg_type = websocket_message_type::ping;
159+
m_length = static_cast<size_t>(buffer.size());
160+
m_body = buffer;
161+
}
162+
void set_message_pong(const concurrency::streams::container_buffer<std::string>& buffer)
144163
{
145-
concurrency::streams::container_buffer<std::string> buffer("");
146164
m_msg_type = websocket_message_type::pong;
147165
m_length = static_cast<size_t>(buffer.size());
148166
m_body = buffer;

Release/src/websockets/client/ws_client_wspp.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,35 @@ class wspp_callback_client : public websocket_client_callback_impl,
325325
}
326326
});
327327

328+
client.set_ping_handler(
329+
[this](websocketpp::connection_hdl, const std::string& msg) {
330+
if (m_external_message_handler)
331+
{
332+
_ASSERTE(m_state >= CONNECTED && m_state < CLOSED);
333+
websocket_incoming_message incoming_msg;
334+
335+
incoming_msg.m_msg_type = websocket_message_type::ping;
336+
incoming_msg.m_body = concurrency::streams::container_buffer<std::string>(msg);
337+
338+
m_external_message_handler(incoming_msg);
339+
}
340+
return true;
341+
});
342+
343+
client.set_pong_handler(
344+
[this](websocketpp::connection_hdl, const std::string& msg) {
345+
if (m_external_message_handler)
346+
{
347+
_ASSERTE(m_state >= CONNECTED && m_state < CLOSED);
348+
websocket_incoming_message incoming_msg;
349+
350+
incoming_msg.m_msg_type = websocket_message_type::pong;
351+
incoming_msg.m_body = concurrency::streams::container_buffer<std::string>(msg);
352+
353+
m_external_message_handler(incoming_msg);
354+
}
355+
});
356+
328357
client.set_close_handler([this](websocketpp::connection_hdl con_hdl) {
329358
_ASSERTE(m_state != CLOSED);
330359
shutdown_wspp_impl<WebsocketConfigType>(con_hdl, false);
@@ -434,12 +463,13 @@ class wspp_callback_client : public websocket_client_callback_impl,
434463
{
435464
case websocket_message_type::text_message:
436465
case websocket_message_type::binary_message:
466+
case websocket_message_type::ping:
437467
case websocket_message_type::pong: break;
438468
default: return pplx::task_from_exception<void>(websocket_exception("Message Type not supported."));
439469
}
440470

441471
const auto length = msg.m_length;
442-
if (length == 0 && msg.m_msg_type != websocket_message_type::pong)
472+
if (length == 0 && msg.m_msg_type != websocket_message_type::ping && msg.m_msg_type != websocket_message_type::pong)
443473
{
444474
return pplx::task_from_exception<void>(websocket_exception("Cannot send empty message."));
445475
}
@@ -694,7 +724,18 @@ class wspp_callback_client : public websocket_client_callback_impl,
694724
case websocket_message_type::binary_message:
695725
client.send(this_client->m_con, sp_allocated.get(), length, websocketpp::frame::opcode::binary, ec);
696726
break;
697-
case websocket_message_type::pong: client.pong(this_client->m_con, "", ec); break;
727+
case websocket_message_type::ping:
728+
{
729+
std::string s(reinterpret_cast<char*>(sp_allocated.get()), length);
730+
client.ping(this_client->m_con, s, ec);
731+
break;
732+
}
733+
case websocket_message_type::pong:
734+
{
735+
std::string s(reinterpret_cast<char*>(sp_allocated.get()), length);
736+
client.pong(this_client->m_con, s, ec);
737+
break;
738+
}
698739
default:
699740
// This case should have already been filtered above.
700741
std::abort();

Release/tests/functional/websockets/client/send_msg_tests.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,32 @@ SUITE(send_msg_tests)
104104
}
105105

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

113114
client.connect(uri).wait();
114115

115116
websocket_outgoing_message msg;
116-
msg.set_pong_message();
117+
msg.set_ping_message(body);
118+
return client.send(msg);
119+
}
120+
121+
template<class SocketClientClass>
122+
pplx::task<void> send_pong_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server,
123+
const std::string& body = "")
124+
{
125+
server.next_message(
126+
[body](test_websocket_msg msg) // Handler to verify the message sent by the client.
127+
{ websocket_asserts::assert_message_equals(msg, body, test_websocket_message_type::WEB_SOCKET_PONG_TYPE); });
128+
129+
client.connect(uri).wait();
130+
131+
websocket_outgoing_message msg;
132+
msg.set_pong_message(body);
117133
return client.send(msg);
118134
}
119135

@@ -493,6 +509,24 @@ SUITE(send_msg_tests)
493509
}
494510

495511
#if !defined(__cplusplus_winrt)
512+
// Send a ping message to the server
513+
TEST_FIXTURE(uri_address, send_ping_msg)
514+
{
515+
test_websocket_server server;
516+
websocket_client client;
517+
send_ping_msg_helper(client, m_uri, server).wait();
518+
client.close().wait();
519+
}
520+
521+
// Send a ping message to the server with a body
522+
TEST_FIXTURE(uri_address, send_ping_msg_body)
523+
{
524+
test_websocket_server server;
525+
websocket_client client;
526+
send_ping_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait();
527+
client.close().wait();
528+
}
529+
496530
// Send an unsolicited pong message to the server
497531
TEST_FIXTURE(uri_address, send_pong_msg)
498532
{
@@ -502,6 +536,15 @@ SUITE(send_msg_tests)
502536
client.close().wait();
503537
}
504538

539+
// Send an unsolicited pong message to the server with a body
540+
TEST_FIXTURE(uri_address, send_pong_msg_body)
541+
{
542+
test_websocket_server server;
543+
websocket_client client;
544+
send_pong_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait();
545+
client.close().wait();
546+
}
547+
505548
// Send an unsolicited pong message to the server with websocket_callback_client
506549
TEST_FIXTURE(uri_address, send_pong_msg_callback_client)
507550
{

Release/tests/functional/websockets/utilities/test_websocket_server.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,20 @@ class _test_websocket_server
122122
m_server_connected.set_exception(std::runtime_error("Connection attempt failed."));
123123
});
124124

125+
m_srv.set_ping_handler([this](websocketpp::connection_hdl hdl, std::string input) {
126+
auto fn = m_test_srv->get_next_message_handler();
127+
assert(fn);
128+
129+
test_websocket_msg wsmsg;
130+
131+
wsmsg.set_data(std::vector<uint8_t>(input.begin(), input.end()));
132+
133+
wsmsg.set_msg_type(WEB_SOCKET_PING_TYPE);
134+
fn(wsmsg);
135+
136+
return true;
137+
});
138+
125139
m_srv.set_pong_handler([this](websocketpp::connection_hdl hdl, std::string input) {
126140
auto fn = m_test_srv->get_next_message_handler();
127141
assert(fn);

Release/tests/functional/websockets/utilities/test_websocket_server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ enum test_websocket_message_type
4646
WEB_SOCKET_UTF8_MESSAGE_TYPE,
4747
WEB_SOCKET_UTF8_FRAGMENT_TYPE,
4848
WEB_SOCKET_CLOSE_TYPE,
49+
WEB_SOCKET_PING_TYPE,
4950
WEB_SOCKET_PONG_TYPE
5051
};
5152

0 commit comments

Comments
 (0)