From 1d6d6ee2280870b00e01fbb8342742ecf44ce4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Fri, 8 Sep 2017 23:53:23 +0200 Subject: [PATCH] Implement initial load through websocket to cut one unnecessary HTTP GET that caused conn pool overflow. Increased reload / retry delays to reduce server spamming by poorly loaded client. --- html_orig/jssrc/term_conn.js | 261 ++++++++++++++++++----------------- user/cgi_sockets.c | 15 +- 2 files changed, 146 insertions(+), 130 deletions(-) diff --git a/html_orig/jssrc/term_conn.js b/html_orig/jssrc/term_conn.js index 21be843..d9bbd57 100644 --- a/html_orig/jssrc/term_conn.js +++ b/html_orig/jssrc/term_conn.js @@ -1,131 +1,134 @@ /** Handle connections */ -var Conn = (function() { - var ws; - var heartbeatTout; - var pingIv; - var xoff = false; - var autoXoffTout; - - function onOpen(evt) { - console.log("CONNECTED"); - } - - function onClose(evt) { - console.warn("SOCKET CLOSED, code "+evt.code+". Reconnecting..."); - setTimeout(function() { - init(); - }, 200); - // this happens when the buffer gets fucked up via invalid unicode. - // we basically use polling instead of socket then - } - - function onMessage(evt) { - try { - // . = heartbeat - switch (evt.data.charAt(0)) { - case 'B': - case 'T': - case 'S': - Screen.load(evt.data); - break; - - case '-': - //console.log('xoff'); - xoff = true; - autoXoffTout = setTimeout(function(){xoff=false;}, 250); - break; - - case '+': - //console.log('xon'); - xoff = false; - clearTimeout(autoXoffTout); - break; - } - heartbeat(); - } catch(e) { - console.error(e); - } - } - - function canSend() { - return !xoff; - } - - function doSend(message) { - if (_demo) { - console.log("TX: ", message); - return true; // Simulate success - } - if (xoff) { - // TODO queue - console.log("Can't send, flood control."); - return false; - } - - if (!ws) return false; // for dry testing - if (ws.readyState != 1) { - console.error("Socket not ready"); - return false; - } - if (typeof message != "string") { - message = JSON.stringify(message); - } - ws.send(message); - return true; - } - - function init() { - if (_demo) { - console.log("Demo mode!"); - Screen.load(_demo_screen); - showPage(); - return; - } - heartbeat(); - - ws = new WebSocket("ws://"+_root+"/term/update.ws"); - ws.onopen = onOpen; - ws.onclose = onClose; - ws.onmessage = onMessage; - - console.log("Opening socket."); - - // Ask for initial data - $.get('http://'+_root+'/term/init', function(resp, status) { - if (status !== 200) location.reload(true); - console.log("Data received!"); - Screen.load(resp); - heartbeat(); - - showPage(); - }); - } - - function heartbeat() { - clearTimeout(heartbeatTout); - heartbeatTout = setTimeout(heartbeatFail, 2000); - } - - function heartbeatFail() { - console.error("Heartbeat lost, probing server..."); - pingIv = setInterval(function() { - console.log("> ping"); - $.get('http://'+_root+'/system/ping', function(resp, status) { - if (status == 200) { - clearInterval(pingIv); - console.info("Server ready, reloading page..."); - location.reload(); - } - }, { - timeout: 100, - }); - }, 500); - } - - return { - ws: null, - init: init, - send: doSend, - canSend: canSend, // check flood control - }; +var Conn = (function () { + var ws; + var heartbeatTout; + var pingIv; + var xoff = false; + var autoXoffTout; + var reconTout; + + var pageShown = false; + + function onOpen(evt) { + console.log("CONNECTED"); + doSend("i"); + } + + function onClose(evt) { + console.warn("SOCKET CLOSED, code " + evt.code + ". Reconnecting..."); + clearTimeout(reconTout); + reconTout = setTimeout(function () { + init(); + }, 2000); + // this happens when the buffer gets fucked up via invalid unicode. + // we basically use polling instead of socket then + } + + function onMessage(evt) { + try { + // . = heartbeat + switch (evt.data.charAt(0)) { + case 'B': + case 'T': + case 'S': + Screen.load(evt.data); + if(!pageShown) { + showPage(); + pageShown = true; + } + break; + + case '-': + //console.log('xoff'); + xoff = true; + autoXoffTout = setTimeout(function () { + xoff = false; + }, 250); + break; + + case '+': + //console.log('xon'); + xoff = false; + clearTimeout(autoXoffTout); + break; + } + heartbeat(); + } catch (e) { + console.error(e); + } + } + + function canSend() { + return !xoff; + } + + function doSend(message) { + if (_demo) { + console.log("TX: ", message); + return true; // Simulate success + } + if (xoff) { + // TODO queue + console.log("Can't send, flood control."); + return false; + } + + if (!ws) return false; // for dry testing + if (ws.readyState != 1) { + console.error("Socket not ready"); + return false; + } + if (typeof message != "string") { + message = JSON.stringify(message); + } + ws.send(message); + return true; + } + + function init() { + if (_demo) { + console.log("Demo mode!"); + Screen.load(_demo_screen); + showPage(); + return; + } + + clearTimeout(reconTout); + clearTimeout(heartbeatTout); + + ws = new WebSocket("ws://" + _root + "/term/update.ws"); + ws.onopen = onOpen; + ws.onclose = onClose; + ws.onmessage = onMessage; + console.log("Opening socket."); + heartbeat(); + } + + function heartbeat() { + clearTimeout(heartbeatTout); + heartbeatTout = setTimeout(heartbeatFail, 2000); + } + + function heartbeatFail() { + console.error("Heartbeat lost, probing server..."); + pingIv = setInterval(function () { + console.log("> ping"); + $.get('http://' + _root + '/system/ping', function (resp, status) { + if (status == 200) { + clearInterval(pingIv); + console.info("Server ready, reloading page..."); + location.reload(); + } + }, { + timeout: 100, + }); + }, 1000); + } + + return { + ws: null, + init: init, + send: doSend, + canSend: canSend, // check flood control + }; })(); diff --git a/user/cgi_sockets.c b/user/cgi_sockets.c index 2e6d8bc..e409c8f 100644 --- a/user/cgi_sockets.c +++ b/user/cgi_sockets.c @@ -47,6 +47,7 @@ notifyCooldownTimCb(void *arg) static void ICACHE_FLASH_ATTR notifyContentTimCb(void *arg) { + Websock *ws = arg; void *data = NULL; int max_bl, total_bl; char sock_buff[SOCK_BUF_LEN]; @@ -65,8 +66,14 @@ notifyContentTimCb(void *arg) int flg = 0; if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE; if (i > 0) flg |= WEBSOCK_FLAG_CONT; - cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg); + if (ws) { + cgiWebsocketSend(ws, sock_buff, (int) strlen(sock_buff), flg); + } else { + cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg); + } if (cont == HTTPD_CGI_DONE) break; + + system_soft_wdt_feed(); } // cleanup @@ -251,6 +258,12 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags) } break; + case 'i': + // requests initial load + dbg("Client requests initial load"); + notifyContentTimCb(ws); + break; + case 'm': case 'p': case 'r':