From 93fb40ad7d259785a22c895e8e24e587ec22f43f Mon Sep 17 00:00:00 2001 From: lampysprites Date: Mon, 18 Oct 2021 23:38:45 +0700 Subject: [PATCH 1/9] Expose min/max time between websocket reconnects --- src/app/script/websocket_class.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 9aaab4519..fd46b5495 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -55,7 +55,19 @@ int WebSocket_new(lua_State* L) } lua_pop(L, 1); - int type = lua_getfield(L, 1, "onreceive"); + int type = lua_getfield(L, 1, "minreconnectwait"); + if (type == LUA_TNUMBER) { + ws->setMinWaitBetweenReconnectionRetries(lua_tointeger(L, -1)); + } + lua_pop(L, 1); + + type = lua_getfield(L, 1, "maxreconnectwait"); + if (type == LUA_TNUMBER) { + ws->setMaxWaitBetweenReconnectionRetries(lua_tointeger(L, -1)); + } + lua_pop(L, 1); + + type = lua_getfield(L, 1, "onreceive"); if (type == LUA_TFUNCTION) { int onreceiveRef = luaL_ref(L, LUA_REGISTRYINDEX); From 1f9c2e8987f3fa56ff36f4f4f3c8efb3866e5202 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Mon, 18 Oct 2021 23:40:49 +0700 Subject: [PATCH 2/9] Handle socket messages when window is out of focus --- src/app/script/websocket_class.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index fd46b5495..a96e7326e 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -13,11 +13,14 @@ #include "app/script/engine.h" #include "app/script/luacpp.h" #include "app/script/security.h" +#include "ui/timer.h" +#include "ui/manager.h" #include "ui/system.h" #include #include #include +#include namespace app { namespace script { @@ -27,6 +30,9 @@ namespace { // Additional "enum" value to make message callback simpler #define MESSAGE_TYPE_BINARY ((int)ix::WebSocketMessageType::Fragment + 10) +static ui::Timer* timer; +static std::set connections; + int WebSocket_new(lua_State* L) { static std::once_flag f; @@ -163,6 +169,13 @@ int WebSocket_connect(lua_State* L) { auto ws = get_ptr(L, 1); ws->start(); + + if (connections.empty()) { + timer = new ui::Timer(33, ui::Manager::getDefault()); + timer->start(); + } + connections.insert(ws); + return 0; } @@ -170,6 +183,13 @@ int WebSocket_close(lua_State* L) { auto ws = get_ptr(L, 1); ws->stop(); + + connections.erase(ws); + if (connections.empty()) { + delete timer; + timer = nullptr; + } + return 0; } From 8c902dd8fc7298bac78150eb2c04e440cb8dca6b Mon Sep 17 00:00:00 2001 From: lampysprites Date: Mon, 18 Oct 2021 23:43:50 +0700 Subject: [PATCH 3/9] Avoid deadlock of ClosedDocs and SpriteObserver --- src/app/script/events_class.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/app/script/events_class.cpp b/src/app/script/events_class.cpp index f1cd4778c..d4b1d4190 100644 --- a/src/app/script/events_class.cpp +++ b/src/app/script/events_class.cpp @@ -169,14 +169,6 @@ public: doc()->add_observer(this); } - ~SpriteEvents() { - if (m_observingUndo) { - doc()->undoHistory()->remove_observer(this); - m_observingUndo = false; - } - doc()->remove_observer(this); - } - EventType eventType(const char* eventName) const { if (std::strcmp(eventName, "change") == 0) return Change; From 6075285b5c4e96ce23a4e3473c30906c15e91052 Mon Sep 17 00:00:00 2001 From: lampysprites Date: Tue, 19 Oct 2021 12:23:12 +0700 Subject: [PATCH 4/9] Refactor the websocket timer --- src/app/script/websocket_class.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index a96e7326e..8060fae9f 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -30,8 +30,8 @@ namespace { // Additional "enum" value to make message callback simpler #define MESSAGE_TYPE_BINARY ((int)ix::WebSocketMessageType::Fragment + 10) -static ui::Timer* timer; -static std::set connections; +static std::unique_ptr g_timer; +static std::set g_connections; int WebSocket_new(lua_State* L) { @@ -63,13 +63,13 @@ int WebSocket_new(lua_State* L) int type = lua_getfield(L, 1, "minreconnectwait"); if (type == LUA_TNUMBER) { - ws->setMinWaitBetweenReconnectionRetries(lua_tointeger(L, -1)); + ws->setMinWaitBetweenReconnectionRetries(1000 * lua_tonumber(L, -1)); } lua_pop(L, 1); type = lua_getfield(L, 1, "maxreconnectwait"); if (type == LUA_TNUMBER) { - ws->setMaxWaitBetweenReconnectionRetries(lua_tointeger(L, -1)); + ws->setMaxWaitBetweenReconnectionRetries(1000 * lua_tonumber(L, -1)); } lua_pop(L, 1); @@ -170,11 +170,11 @@ int WebSocket_connect(lua_State* L) auto ws = get_ptr(L, 1); ws->start(); - if (connections.empty()) { - timer = new ui::Timer(33, ui::Manager::getDefault()); - timer->start(); + if (g_connections.empty()) { + g_timer = std::make_unique(33, ui::Manager::getDefault()); + g_timer->start(); } - connections.insert(ws); + g_connections.insert(ws); return 0; } @@ -184,10 +184,9 @@ int WebSocket_close(lua_State* L) auto ws = get_ptr(L, 1); ws->stop(); - connections.erase(ws); - if (connections.empty()) { - delete timer; - timer = nullptr; + g_connections.erase(ws); + if (g_connections.empty()) { + g_timer = nullptr; } return 0; From b29627c8cb1b7be2f616ac88d929f35a2db4f2fd Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Oct 2021 10:50:18 -0300 Subject: [PATCH 5/9] Minor formatting change --- src/app/script/websocket_class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 8060fae9f..cdb2c3658 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -31,7 +31,7 @@ namespace { #define MESSAGE_TYPE_BINARY ((int)ix::WebSocketMessageType::Fragment + 10) static std::unique_ptr g_timer; -static std::set g_connections; +static std::set g_connections; int WebSocket_new(lua_State* L) { From 651fa4a3b6988b3a37c0de5793f8d96fda0a09d5 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Oct 2021 10:57:25 -0300 Subject: [PATCH 6/9] Stop the auxiliar ui::Timer when the last WebSocket is GC'd --- src/app/script/websocket_class.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index cdb2c3658..f5d85189c 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -33,6 +33,15 @@ namespace { static std::unique_ptr g_timer; static std::set g_connections; +static void close_ws(ix::WebSocket* ws) +{ + ws->stop(); + + g_connections.erase(ws); + if (g_connections.empty()) + g_timer.reset(); +} + int WebSocket_new(lua_State* L) { static std::once_flag f; @@ -108,7 +117,7 @@ int WebSocket_new(lua_State* L) int WebSocket_gc(lua_State* L) { auto ws = get_ptr(L, 1); - ws->stop(); + close_ws(ws); delete ws; return 0; } @@ -182,13 +191,7 @@ int WebSocket_connect(lua_State* L) int WebSocket_close(lua_State* L) { auto ws = get_ptr(L, 1); - ws->stop(); - - g_connections.erase(ws); - if (g_connections.empty()) { - g_timer = nullptr; - } - + close_ws(ws); return 0; } From c2f24656d764c99d45d66224b4b0b5684a24e118 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Oct 2021 11:11:57 -0300 Subject: [PATCH 7/9] Don't create a ui::Timer if the UI is not available --- src/app/script/websocket_class.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index f5d85189c..b97fbb727 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -180,8 +180,12 @@ int WebSocket_connect(lua_State* L) ws->start(); if (g_connections.empty()) { - g_timer = std::make_unique(33, ui::Manager::getDefault()); - g_timer->start(); +#ifdef ENABLE_UI + if (App::instance()->isGui()) { + g_timer = std::make_unique(33, ui::Manager::getDefault()); + g_timer->start(); + } +#endif } g_connections.insert(ws); From 5c30315611c6b975f662b87dcab682d2b2d9fbff Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Oct 2021 11:12:15 -0300 Subject: [PATCH 8/9] Avoid std::bad_function_call if we don't specify an onreceive callback for the WebSocket --- src/app/script/websocket_class.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index b97fbb727..499d4ad42 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -107,6 +107,8 @@ int WebSocket_new(lua_State* L) }); } else { + // Set a default handler to avoid a std::bad_function_call exception + ws->setOnMessageCallback([](const ix::WebSocketMessagePtr& msg) { }); lua_pop(L, 1); } } From 5d04eb5a2e7f8477ba14c8a2efa9b92c4707d066 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Oct 2021 11:15:00 -0300 Subject: [PATCH 9/9] [lua] Match WebSocketMessageType constants with the style of all other constants --- src/app/script/websocket_class.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/app/script/websocket_class.cpp b/src/app/script/websocket_class.cpp index 499d4ad42..6be1956f5 100644 --- a/src/app/script/websocket_class.cpp +++ b/src/app/script/websocket_class.cpp @@ -238,14 +238,14 @@ void register_websocket_class(lua_State* L) lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, "WebSocketMessageType"); - setfield_integer(L, "Text", (int)ix::WebSocketMessageType::Message); - setfield_integer(L, "Binary", MESSAGE_TYPE_BINARY); - setfield_integer(L, "Open", (int)ix::WebSocketMessageType::Open); - setfield_integer(L, "Close", (int)ix::WebSocketMessageType::Close); - setfield_integer(L, "Error", (int)ix::WebSocketMessageType::Error); - setfield_integer(L, "Ping", (int)ix::WebSocketMessageType::Ping); - setfield_integer(L, "Pong", (int)ix::WebSocketMessageType::Pong); - setfield_integer(L, "Fragment", (int)ix::WebSocketMessageType::Fragment); + setfield_integer(L, "TEXT", (int)ix::WebSocketMessageType::Message); + setfield_integer(L, "BINARY", MESSAGE_TYPE_BINARY); + setfield_integer(L, "OPEN", (int)ix::WebSocketMessageType::Open); + setfield_integer(L, "CLOSE", (int)ix::WebSocketMessageType::Close); + setfield_integer(L, "ERROR", (int)ix::WebSocketMessageType::Error); + setfield_integer(L, "PING", (int)ix::WebSocketMessageType::Ping); + setfield_integer(L, "PONG", (int)ix::WebSocketMessageType::Pong); + setfield_integer(L, "FRAGMENT", (int)ix::WebSocketMessageType::Fragment); lua_pop(L, 1); }