static long webSocketTimeOut = 60000; static O eleu_webSocket_onMessage, eleu_webSocket_new; static O eleu_webSocket_handler; svoid eleu_webSocket_init { if (webServerPort != 0) pcall { //serveHttp(webServerPort); serveHttpWithWebsockets(webServerPort, eleu_webSocket_handler()); } } static O eleu_webSocket_handler() { if (eleu_webSocket_handler == null) eleu_webSocket_handler = func(final NanoHTTPD.IHTTPSession handshake) { class MyWebSocket extends WebSocket { L msgs = synchroList(); volatile long lastMessage = sysNow(); S botID; *() { super(handshake); } protected void onPong(WebSocketFrame pongFrame) { // don't use WebSocket ping/pong - it doesn't work } protected void onMessage(WebSocketFrame messageFrame) { //print("websocket msg: " + messageFrame.getTextPayload()); lastMessage = sysNow(); S s = messageFrame.getTextPayload(); if (eq(s, "ping")) incAtomicLong(webSocketPongs); pcall { if (botID != null) call(getBot(botID), 'onWebSocketMessage, this, s); else { msgs.add(s); callF(eleu_webSocket_onMessage, this, s); } } } protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { //print("websocket close"); webSockets.remove(this); } protected void onException(IOException e) { printStackTrace(e); } void closeMe() ctex { webSockets.remove(this); close(WebSocketFrame.CloseCode.NormalClosure, ""); } void clean() { if (sysNow() >= lastMessage + webSocketTimeOut) { webSockets.remove(this); pcall { close(WebSocketFrame.CloseCode.NormalClosure, "timeout"); } } } }; new MyWebSocket ws; S uri = handshake.getUri(); print("WebSocket URI: " + uri); webSockets.add(ws); bool dispatched = false; pcall { uri = dropPrefix("/", uri); int i = smartIndexOf(uri, '/'); S botID = takeFirst(i, uri); if (isInteger(botID)) { O bot = getBot(botID); if (bot == null) fail("Bot not found: " + botID); call(bot, 'onNewWebSocket, ws, or2(substring(uri, i), "/")); print("WebSocket dispatched to " + botID); ws.botID = botID; dispatched = true; } } if (!dispatched) pcallF(eleu_webSocket_new, ws); ret ws; }; ret eleu_webSocket_handler; }