diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h
index 9b3fe713a7..171234edf0 100644
--- a/Release/include/cpprest/ws_msg.h
+++ b/Release/include/cpprest/ws_msg.h
@@ -73,6 +73,15 @@ class websocket_outgoing_message
{
public:
+ ///
+ /// Sets a the outgoing message to be an unsolicited pong message.
+ /// This is useful when the client side wants to check whether the server is alive.
+ ///
+ void set_pong_message()
+ {
+ this->set_message_pong();
+ }
+
///
/// Sets a UTF-8 message as the message body.
///
@@ -152,6 +161,14 @@ class websocket_outgoing_message
const pplx::task_completion_event & body_sent() const { return m_body_sent; }
+ void set_message_pong()
+ {
+ concurrency::streams::container_buffer buffer("");
+ m_msg_type = websocket_message_type::pong;
+ m_length = static_cast(buffer.size());
+ m_body = buffer;
+ }
+
void set_message(const concurrency::streams::container_buffer &buffer)
{
m_msg_type = websocket_message_type::text_message;
diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp
index 1e53f69e39..bd17af922e 100644
--- a/Release/src/websockets/client/ws_client_wspp.cpp
+++ b/Release/src/websockets/client/ws_client_wspp.cpp
@@ -373,13 +373,14 @@ class wspp_callback_client : public websocket_client_callback_impl, public std::
{
case websocket_message_type::text_message:
case websocket_message_type::binary_message:
+ case websocket_message_type::pong:
break;
default:
return pplx::task_from_exception(websocket_exception("Invalid message type"));
}
const auto length = msg.m_length;
- if (length == 0)
+ if (length == 0 && msg.m_msg_type != websocket_message_type::pong)
{
return pplx::task_from_exception(websocket_exception("Cannot send empty message."));
}
@@ -639,13 +640,19 @@ class wspp_callback_client : public websocket_client_callback_impl, public std::
ec);
break;
case websocket_message_type::binary_message:
- client.send(
+ 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;
default:
// This case should have already been filtered above.
std::abort();
diff --git a/Release/tests/functional/websockets/client/send_msg_tests.cpp b/Release/tests/functional/websockets/client/send_msg_tests.cpp
index f0cd3ea82a..1303207a0e 100644
--- a/Release/tests/functional/websockets/client/send_msg_tests.cpp
+++ b/Release/tests/functional/websockets/client/send_msg_tests.cpp
@@ -103,6 +103,21 @@ pplx::task send_text_msg_helper(SocketClientClass& client, web::uri uri, t
return client.send(msg);
}
+template
+pplx::task send_pong_msg_helper(SocketClientClass& client, web::uri uri, test_websocket_server& server)
+{
+ 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);
+ });
+
+ client.connect(uri).wait();
+
+ websocket_outgoing_message msg;
+ msg.set_pong_message();
+ return client.send(msg);
+}
+
pplx::task send_msg_from_stream(websocket_client& client,
test_websocket_server& server,
web::uri uri,
@@ -456,6 +471,25 @@ TEST_FIXTURE(uri_address, send_stream_binary_msg_no_length)
client.close().wait();
}
+// Send an unsolicited pong message to the server
+TEST_FIXTURE(uri_address, send_pong_msg)
+{
+ test_websocket_server server;
+ websocket_client client;
+ send_pong_msg_helper(client, m_uri, server).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)
+{
+ test_websocket_server server;
+ websocket_callback_client client;
+ send_pong_msg_helper(client, m_uri, server).wait();
+ client.close().wait();
+}
+
+
} // SUITE(send_msg_tests)
}}}}
diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp
index c1377ee4ec..4485e93f86 100644
--- a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp
+++ b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp
@@ -134,6 +134,19 @@ namespace utilities {
m_server_connected.set_exception(std::runtime_error("Connection attempt failed."));
});
+ m_srv.set_pong_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(input.begin(), input.end()));
+
+ wsmsg.set_msg_type(WEB_SOCKET_PONG_TYPE);
+ fn(wsmsg);
+ });
+
m_srv.set_message_handler([this](websocketpp::connection_hdl hdl, server::message_ptr msg)
{
auto pay = msg->get_payload();
@@ -151,12 +164,12 @@ namespace utilities {
wsmsg.set_msg_type(utilities::WEB_SOCKET_BINARY_MESSAGE_TYPE);
break;
case websocketpp::frame::opcode::text:
- wsmsg.set_msg_type(utilities::WEB_SOCKET_UTF8_MESSAGE_TYPE);
+ wsmsg.set_msg_type(utilities::WEB_SOCKET_UTF8_MESSAGE_TYPE);
break;
case websocketpp::frame::opcode::close:
wsmsg.set_msg_type(utilities::WEB_SOCKET_CLOSE_TYPE);
break;
- default:
+ default:
// Websocketspp does not currently support explicit fragmentation. We should not get here.
std::abort();
}
@@ -262,7 +275,7 @@ namespace utilities {
case test_websocket_message_type::WEB_SOCKET_CLOSE_TYPE:
flags = websocketpp::frame::opcode::close; // WebSocket::FRAME_OP_CLOSE;
break;
- case test_websocket_message_type::WEB_SOCKET_UTF8_FRAGMENT_TYPE:
+ case test_websocket_message_type::WEB_SOCKET_UTF8_FRAGMENT_TYPE:
case test_websocket_message_type::WEB_SOCKET_BINARY_FRAGMENT_TYPE:
default:
throw std::runtime_error("invalid message type");
diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.h b/Release/tests/functional/websockets/utilities/test_websocket_server.h
index b5440068b2..5126c8281d 100644
--- a/Release/tests/functional/websockets/utilities/test_websocket_server.h
+++ b/Release/tests/functional/websockets/utilities/test_websocket_server.h
@@ -50,7 +50,8 @@ enum test_websocket_message_type
WEB_SOCKET_BINARY_FRAGMENT_TYPE,
WEB_SOCKET_UTF8_MESSAGE_TYPE,
WEB_SOCKET_UTF8_FRAGMENT_TYPE,
- WEB_SOCKET_CLOSE_TYPE
+ WEB_SOCKET_CLOSE_TYPE,
+ WEB_SOCKET_PONG_TYPE
};
// Interface containing details about the HTTP handshake request received by the test server.