Compare commits
8 Commits
v2.2.0
...
user/bserg
Author | SHA1 | Date | |
---|---|---|---|
067c128474 | |||
a127d9ef0d | |||
4a845e3cc4 | |||
633afa5bed | |||
49fd2a9e53 | |||
6264a8b41d | |||
3990d3bcbf | |||
aa3f201ced |
@ -293,8 +293,8 @@ namespace ix
|
||||
break;
|
||||
}
|
||||
|
||||
// We cannot enter poll which might block forever if we are stopping
|
||||
if (_stop) break;
|
||||
// We can avoid to poll if we want to stop and are not closing
|
||||
if (_stop && !isClosing()) break;
|
||||
|
||||
// 2. Poll to see if there's any new data available
|
||||
WebSocketTransport::PollResult pollResult = _ws.poll();
|
||||
|
@ -71,7 +71,7 @@ namespace ix
|
||||
const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
|
||||
const int WebSocketTransport::kDefaultPingTimeoutSecs(-1);
|
||||
const bool WebSocketTransport::kDefaultEnablePong(true);
|
||||
const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(200);
|
||||
const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
|
||||
constexpr size_t WebSocketTransport::kChunkSize;
|
||||
|
||||
WebSocketTransport::WebSocketTransport() :
|
||||
@ -748,7 +748,7 @@ namespace ix
|
||||
bool compress,
|
||||
const OnProgressCallback& onProgressCallback)
|
||||
{
|
||||
if (_readyState != ReadyState::OPEN)
|
||||
if (_readyState != ReadyState::OPEN && _readyState != ReadyState::CLOSING)
|
||||
{
|
||||
return WebSocketSendInfo();
|
||||
}
|
||||
@ -1041,8 +1041,7 @@ namespace ix
|
||||
_requestInitCancellation = true;
|
||||
|
||||
if (_readyState == ReadyState::CLOSING || _readyState == ReadyState::CLOSED) return;
|
||||
|
||||
sendCloseFrame(code, reason);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_closeDataMutex);
|
||||
_closeCode = code;
|
||||
@ -1056,6 +1055,7 @@ namespace ix
|
||||
}
|
||||
setReadyState(ReadyState::CLOSING);
|
||||
|
||||
sendCloseFrame(code, reason);
|
||||
// wake up the poll, but do not close yet
|
||||
_socket->wakeUpFromPoll(Socket::kSendRequest);
|
||||
}
|
||||
|
@ -44,14 +44,20 @@ if (UNIX)
|
||||
list(APPEND SOURCES
|
||||
IXDNSLookupTest.cpp
|
||||
cmd_websocket_chat.cpp
|
||||
IXWebSocketCloseTest.cpp
|
||||
IXWebSocketPingTest.cpp
|
||||
IXWebSocketPingTimeoutTest.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Some unittest fail for dubious reason on Ubuntu Xenial with TSAN
|
||||
if (MAC OR WIN32)
|
||||
list(APPEND SOURCES
|
||||
IXWebSocketMessageQTest.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Disable tests for now that are failing or not reliable
|
||||
# IXWebSocketPingTest.cpp
|
||||
# IXWebSocketPingTimeoutTest.cpp
|
||||
# IXWebSocketCloseTest.cpp
|
||||
# IXWebSocketMessageQTest.cpp (trigger a segfault on Linux)
|
||||
|
||||
add_executable(ixwebsocket_unittest ${SOURCES})
|
||||
|
||||
|
@ -102,6 +102,7 @@ namespace
|
||||
}
|
||||
|
||||
_webSocket.setUrl(url);
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
|
||||
std::stringstream ss;
|
||||
log(std::string("Connecting to url: ") + url);
|
||||
@ -118,27 +119,27 @@ namespace
|
||||
if (messageType == ix::WebSocketMessageType::Open)
|
||||
{
|
||||
log("client connected");
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log("client disconnected");
|
||||
std::stringstream ss;
|
||||
ss << "client disconnected("
|
||||
<< closeInfo.code
|
||||
<< ","
|
||||
<< closeInfo.reason
|
||||
<< ")";
|
||||
log(ss.str());
|
||||
|
||||
std::lock_guard<std::mutex> lck(_mutexCloseData);
|
||||
|
||||
_closeCode = closeInfo.code;
|
||||
_closeReason = std::string(closeInfo.reason);
|
||||
_closeRemote = closeInfo.remote;
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Error)
|
||||
{
|
||||
ss << "Error ! " << error.reason;
|
||||
log(ss.str());
|
||||
|
||||
_webSocket.disableAutomaticReconnection();
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Pong)
|
||||
{
|
||||
@ -202,12 +203,14 @@ namespace
|
||||
}
|
||||
else if (messageType == ix::WebSocketMessageType::Close)
|
||||
{
|
||||
log("Server closed connection");
|
||||
|
||||
//Logger() << closeInfo.code;
|
||||
//Logger() << closeInfo.reason;
|
||||
//Logger() << closeInfo.remote;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Server closed connection("
|
||||
<< closeInfo.code
|
||||
<< ","
|
||||
<< closeInfo.reason
|
||||
<< ")";
|
||||
log(ss.str());
|
||||
|
||||
std::lock_guard<std::mutex> lck(mutexWrite);
|
||||
|
||||
receivedCloseCode = closeInfo.code;
|
||||
@ -261,11 +264,11 @@ TEST_CASE("Websocket_client_close_default", "[close]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(100);
|
||||
ix::msleep(500);
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
ix::msleep(200);
|
||||
ix::msleep(500);
|
||||
|
||||
// ensure client close is the same as values given
|
||||
REQUIRE(webSocketClient.getCloseCode() == 1000);
|
||||
@ -319,7 +322,7 @@ TEST_CASE("Websocket_client_close_params_given", "[close]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(100);
|
||||
ix::msleep(500);
|
||||
|
||||
webSocketClient.stop(4000, "My reason");
|
||||
|
||||
@ -377,7 +380,7 @@ TEST_CASE("Websocket_server_close", "[close]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(200);
|
||||
ix::msleep(500);
|
||||
|
||||
server.stop();
|
||||
|
||||
@ -404,3 +407,50 @@ TEST_CASE("Websocket_server_close", "[close]")
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Websocket_server_close_immediatly", "[close]")
|
||||
{
|
||||
SECTION("Make sure that close code and reason was read from server.")
|
||||
{
|
||||
ix::setupWebSocketTrafficTrackerCallback();
|
||||
|
||||
int port = getFreePort();
|
||||
ix::WebSocketServer server(port);
|
||||
|
||||
uint16_t serverReceivedCloseCode(0);
|
||||
bool serverReceivedCloseRemote(false);
|
||||
std::string serverReceivedCloseReason("");
|
||||
std::mutex mutexWrite;
|
||||
|
||||
REQUIRE(startServer(server, serverReceivedCloseCode, serverReceivedCloseReason, serverReceivedCloseRemote, mutexWrite));
|
||||
|
||||
std::string session = ix::generateSessionId();
|
||||
WebSocketClient webSocketClient(port);
|
||||
|
||||
webSocketClient.start();
|
||||
|
||||
server.stop();
|
||||
|
||||
ix::msleep(500);
|
||||
|
||||
// ensure client close hasn't been called
|
||||
REQUIRE(webSocketClient.getCloseCode() == 0);
|
||||
REQUIRE(webSocketClient.getCloseReason() == "");
|
||||
REQUIRE(webSocketClient.getCloseRemote() == false);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mutexWrite);
|
||||
|
||||
// Here we ensure that the code/reason wasn't received by the server
|
||||
REQUIRE(serverReceivedCloseCode == 0);
|
||||
REQUIRE(serverReceivedCloseReason == "");
|
||||
REQUIRE(serverReceivedCloseRemote == false);
|
||||
}
|
||||
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +186,8 @@ TEST_CASE("Websocket_message_queue", "[websocket_message_q]")
|
||||
MsgQTestClient testClient;
|
||||
testClient.run("ws://127.0.0.1:" + std::to_string(port));
|
||||
REQUIRE(testClient.isSucceeded());
|
||||
|
||||
server.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -225,8 +225,8 @@ TEST_CASE("Websocket_ping_no_data_sent_setPingInterval", "[setPingInterval]")
|
||||
// -> expected ping messages == 2 as 2100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
@ -272,8 +272,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval", "[setPingInterval]")
|
||||
// -> expected ping messages == 3 as 900+900+1300 = 3100 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 3);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
@ -325,8 +325,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_half_full", "[setPingInterva
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
@ -377,8 +377,8 @@ TEST_CASE("Websocket_ping_data_sent_setPingInterval_full", "[setPingInterval]")
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
@ -422,8 +422,8 @@ TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod
|
||||
// -> expected ping messages == 1 as 1900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
@ -472,8 +472,8 @@ TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod]")
|
||||
// -> expected ping messages == 2 as 900+900+1100 = 2900 seconds, 1 ping sent every second
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
|
@ -259,8 +259,8 @@ TEST_CASE("Websocket_ping_timeout_not_checked", "[setPingTimeout]")
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
// Ensure client close was not by ping timeout
|
||||
@ -298,7 +298,7 @@ TEST_CASE("Websocket_ping_no_timeout", "[setPingTimeout]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(1100);
|
||||
ix::msleep(1200);
|
||||
|
||||
// Here we test ping timeout, no timeout
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
@ -312,8 +312,8 @@ TEST_CASE("Websocket_ping_no_timeout", "[setPingTimeout]")
|
||||
|
||||
webSocketClient.stop();
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
// Ensure client close was not by ping timeout
|
||||
@ -365,7 +365,7 @@ TEST_CASE("Websocket_no_ping_but_timeout", "[setPingTimeout]")
|
||||
REQUIRE(serverReceivedPingMessages == 0);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
// Ensure client close was by ping timeout
|
||||
ix::msleep(300);
|
||||
ix::msleep(1000);
|
||||
REQUIRE(webSocketClient.isClosed() == true);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == true);
|
||||
|
||||
@ -417,7 +417,7 @@ TEST_CASE("Websocket_ping_timeout", "[setPingTimeout]")
|
||||
REQUIRE(serverReceivedPingMessages == 1);
|
||||
REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
|
||||
// Ensure client close was by ping timeout
|
||||
ix::msleep(300);
|
||||
ix::msleep(1000);
|
||||
REQUIRE(webSocketClient.isClosed() == true);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == true);
|
||||
|
||||
@ -429,7 +429,6 @@ TEST_CASE("Websocket_ping_timeout", "[setPingTimeout]")
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // this test fails on travis / commenting it out for now to get back to a green travis state
|
||||
TEST_CASE("Websocket_ping_long_timeout", "[setPingTimeout]")
|
||||
{
|
||||
SECTION("Make sure that ping messages don't have responses (no PONG).")
|
||||
@ -458,7 +457,7 @@ TEST_CASE("Websocket_ping_long_timeout", "[setPingTimeout]")
|
||||
|
||||
REQUIRE(server.getClients().size() == 1);
|
||||
|
||||
ix::msleep(5900);
|
||||
ix::msleep(5800);
|
||||
|
||||
// Here we test ping timeout, no timeout yet (2 ping sent at 2s and 4s)
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
@ -468,7 +467,7 @@ TEST_CASE("Websocket_ping_long_timeout", "[setPingTimeout]")
|
||||
REQUIRE(webSocketClient.isClosed() == false);
|
||||
REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
|
||||
|
||||
ix::msleep(200);
|
||||
ix::msleep(600);
|
||||
|
||||
// Here we test ping timeout, timeout (at 6 seconds)
|
||||
REQUIRE(serverReceivedPingMessages == 2);
|
||||
@ -484,4 +483,3 @@ TEST_CASE("Websocket_ping_long_timeout", "[setPingTimeout]")
|
||||
ix::reportWebSocketTraffic();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -336,8 +336,8 @@ TEST_CASE("Websocket_chat", "[websocket_chat]")
|
||||
REQUIRE(chatA.getReceivedMessages()[1] == "from B2");
|
||||
REQUIRE(chatA.getReceivedMessages()[2].size() == bigMessage.size());
|
||||
|
||||
// Give us 500ms for the server to notice that clients went away
|
||||
ix::msleep(500);
|
||||
// Give us 1000ms for the server to notice that clients went away
|
||||
ix::msleep(1000);
|
||||
REQUIRE(server.getClients().size() == 0);
|
||||
|
||||
ix::reportWebSocketTraffic();
|
||||
|
@ -461,6 +461,11 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Windows does not play nice with multiple files opened by different processes
|
||||
# "The process cannot access the file because it is being used by another process"
|
||||
if platform.system() == 'Windows':
|
||||
args.cpu_count = 1
|
||||
|
||||
# Default sanitizer is tsan
|
||||
sanitizer = args.sanitizer
|
||||
|
||||
|
Reference in New Issue
Block a user