From e105702c79e4eff9846d35b8dba29d1a58a2602b Mon Sep 17 00:00:00 2001 From: JCash Date: Sat, 17 Oct 2020 11:40:53 +0200 Subject: [PATCH 1/2] Issue 13: Added support for connect sequence timeout Decreased the select timeout when reading headers Don't call callback with DISCONNECTED if the connection was never connected --- websocket/api/api.script_api | 3 +++ websocket/src/handshake.cpp | 4 ++-- websocket/src/websocket.cpp | 42 ++++++++++++++++++++++++++++++------ websocket/src/websocket.h | 2 ++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/websocket/api/api.script_api b/websocket/api/api.script_api index ac51a09..bdd160b 100644 --- a/websocket/api/api.script_api +++ b/websocket/api/api.script_api @@ -17,6 +17,9 @@ type: table desc: optional parameters as properties. The following parameters can be set members: + - name: timeout + type: number + desc: Timeout for the connection sequence (milliseconds) - name: callback type: function diff --git a/websocket/src/handshake.cpp b/websocket/src/handshake.cpp index e85f356..2a6302b 100644 --- a/websocket/src/handshake.cpp +++ b/websocket/src/handshake.cpp @@ -105,13 +105,13 @@ Result ReceiveHeaders(WebsocketConnection* conn) dmSocket::SelectorZero(&selector); dmSocket::SelectorSet(&selector, dmSocket::SELECTOR_KIND_READ, conn->m_Socket); - dmSocket::Result sr = dmSocket::Select(&selector, 200*1000); + dmSocket::Result sr = dmSocket::Select(&selector, SOCKET_WAIT_TIMEOUT); if (dmSocket::RESULT_OK != sr) { if (dmSocket::RESULT_WOULDBLOCK) { - dmLogWarning("Waiting for socket to be available for reading"); + DebugLog(1, "Waiting for socket to be available for reading"); return RESULT_WOULDBLOCK; } diff --git a/websocket/src/websocket.cpp b/websocket/src/websocket.cpp index a2dd60a..651a79c 100644 --- a/websocket/src/websocket.cpp +++ b/websocket/src/websocket.cpp @@ -178,6 +178,7 @@ static WebsocketConnection* CreateConnection(const char* url) conn->m_Buffer = (char*)malloc(conn->m_BufferCapacity); conn->m_Buffer[0] = 0; conn->m_BufferSize = 0; + conn->m_ConnectTimeout = 0; dmURI::Parts uri; dmURI::Parse(url, &conn->m_Url); @@ -194,6 +195,7 @@ static WebsocketConnection* CreateConnection(const char* url) conn->m_SSLSocket = 0; conn->m_Status = RESULT_OK; conn->m_HasHandshakeData = 0; + conn->m_WasConnected = 0; #if defined(HAVE_WSLAY) conn->m_Ctx = 0; @@ -265,13 +267,12 @@ static int LuaConnect(lua_State* L) const char* url = luaL_checkstring(L, 1); - // long playedTime = luaL_checktable_number(L, 2, "playedTime", -1); - // long progressValue = luaL_checktable_number(L, 2, "progressValue", -1); - // char *description = luaL_checktable_string(L, 2, "description", NULL); - // char *coverImage = luaL_checktable_string(L, 2, "coverImage", NULL); - WebsocketConnection* conn = CreateConnection(url); + // milliseconds + lua_Number timeout = dmScript::CheckTableNumber(L, 2, "timeout", 3000); + conn->m_ConnectTimeout = dmTime::GetTime() + timeout * 1000; + conn->m_Callback = dmScript::CreateCallback(L, 3); if (g_Websocket.m_Connections.Full()) @@ -528,6 +529,13 @@ Result PushMessage(WebsocketConnection* conn, MessageType type, int length, cons return dmWebsocket::RESULT_OK; } +// has the connect procedure taken too long? +static bool CheckConnectTimeout(WebsocketConnection* conn) +{ + uint64_t t = dmTime::GetTime(); + return t >= conn->m_ConnectTimeout; +} + static dmExtension::Result OnUpdate(dmExtension::Params* params) { uint32_t size = g_Websocket.m_Connections.Size(); @@ -544,7 +552,10 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params) conn->m_BufferSize = 0; } - HandleCallback(conn, EVENT_DISCONNECTED, 0, conn->m_BufferSize); + if (conn->m_WasConnected) + { + HandleCallback(conn, EVENT_DISCONNECTED, 0, conn->m_BufferSize); + } g_Websocket.m_Connections.EraseSwap(i); --i; @@ -609,6 +620,12 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params) } else if (STATE_HANDSHAKE_READ == conn->m_State) { + if (CheckConnectTimeout(conn)) + { + CLOSE_CONN("Connect sequence timed out"); + continue; + } + Result result = ReceiveHeaders(conn); if (RESULT_WOULDBLOCK == result) { @@ -645,11 +662,18 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params) #endif dmSocket::SetBlocking(conn->m_Socket, false); + conn->m_WasConnected = 1; SetState(conn, STATE_CONNECTED); HandleCallback(conn, EVENT_CONNECTED, 0, 0); } else if (STATE_HANDSHAKE_WRITE == conn->m_State) { + if (CheckConnectTimeout(conn)) + { + CLOSE_CONN("Connect sequence timed out"); + continue; + } + Result result = SendClientHandshake(conn); if (RESULT_WOULDBLOCK == result) { @@ -665,6 +689,12 @@ static dmExtension::Result OnUpdate(dmExtension::Params* params) } else if (STATE_CONNECTING == conn->m_State) { + if (CheckConnectTimeout(conn)) + { + CLOSE_CONN("Connect sequence timed out"); + continue; + } + #if defined(__EMSCRIPTEN__) conn->m_SSLSocket = dmSSLSocket::INVALID_SOCKET_HANDLE; diff --git a/websocket/src/websocket.h b/websocket/src/websocket.h index 020a8f9..010745c 100644 --- a/websocket/src/websocket.h +++ b/websocket/src/websocket.h @@ -89,6 +89,7 @@ namespace dmWebsocket dmSocket::Socket m_Socket; dmSSLSocket::Socket m_SSLSocket; dmArray m_Messages; // lengths of the messages in the data buffer + uint64_t m_ConnectTimeout; uint8_t m_Key[16]; State m_State; char* m_Buffer; @@ -97,6 +98,7 @@ namespace dmWebsocket Result m_Status; uint8_t m_SSL:1; uint8_t m_HasHandshakeData:1; + uint8_t m_WasConnected:1; uint8_t :6; }; From b54e3e07ad5af50ca145b6b57f33137fdd819cd1 Mon Sep 17 00:00:00 2001 From: JCash Date: Sat, 17 Oct 2020 11:47:23 +0200 Subject: [PATCH 2/2] review fix --- websocket/api/api.script_api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocket/api/api.script_api b/websocket/api/api.script_api index bdd160b..5e5bd7f 100644 --- a/websocket/api/api.script_api +++ b/websocket/api/api.script_api @@ -19,7 +19,7 @@ members: - name: timeout type: number - desc: Timeout for the connection sequence (milliseconds) + desc: Timeout for the connection sequence (milliseconds). Default: 3000 - name: callback type: function