home · contact · privacy
Improve client connection failire / reconnect handling.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 12 Nov 2020 00:35:38 +0000 (01:35 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 12 Nov 2020 00:35:38 +0000 (01:35 +0100)
rogue_chat_curses.py
rogue_chat_nocanvas_monochrome.html

index 33b2750788c4c9b241158c9943ff428d726c9a8e..203f3eaefec758c879b3b7bc9edc451f2e385113 100755 (executable)
@@ -2,6 +2,7 @@
 import curses
 import queue
 import threading
+import time
 from plomrogue.game import GameBase
 from plomrogue.parser import Parser
 from plomrogue.mapping import YX, MapGeometrySquare, MapGeometryHex
@@ -257,11 +258,47 @@ class TUI:
             for k in keys_conf:
                 self.keys[k] = keys_conf[k]
         self.show_help = False
+        self.disconnected = True
+        self.force_instant_connect = True
+        self.input_lines = []
         curses.wrapper(self.loop)
 
     def flash(self):
         curses.flash()
 
+    def connect(self):
+
+        def handle_recv(msg):
+            if msg == 'BYE':
+                self.socket.close()
+            else:
+                self.queue.put(msg)
+
+        self.log_msg('@ attempting connect')
+        socket_client_class = PlomSocketClient
+        if self.host.startswith('ws://') or self.host.startswith('wss://'):
+            socket_client_class = WebSocketClient
+        try:
+            self.socket = socket_client_class(handle_recv, self.host)
+            self.socket_thread = threading.Thread(target=self.socket.run)
+            self.socket_thread.start()
+            self.disconnected = False
+            self.socket.send('TASKS')
+            self.switch_mode('login')
+        except ConnectionRefusedError:
+            self.log_msg('@ server connect failure')
+            self.disconnected = True
+            self.switch_mode('waiting_for_server')
+        self.do_refresh = True
+
+    def reconnect(self):
+        self.log_msg('@ attempting reconnect')
+        self.send('QUIT')
+        time.sleep(0.1)  # FIXME necessitated by some some strange SSL race
+                         # conditions with ws4py, find out what exactly
+        self.switch_mode('waiting_for_server')
+        self.connect()
+
     def send(self, msg):
         try:
             if hasattr(self.socket, 'plom_closed') and self.socket.plom_closed:
@@ -269,6 +306,8 @@ class TUI:
             self.socket.send(msg)
         except (BrokenPipeError, BrokenSocketConnection):
             self.log_msg('@ server disconnected :(')
+            self.disconnected = True
+            self.force_instant_connect = True
             self.do_refresh = True
 
     def log_msg(self, msg):
@@ -310,7 +349,6 @@ class TUI:
         self.restore_input_values()
 
     def loop(self, stdscr):
-        import time
         import datetime
 
         def safe_addstr(y, x, line):
@@ -324,38 +362,6 @@ class TUI:
                 stdscr.insstr(y, self.size.x - 2, ' ')
                 stdscr.addstr(y, x, cut)
 
-        def connect():
-
-            def handle_recv(msg):
-                if msg == 'BYE':
-                    self.socket.close()
-                else:
-                    self.queue.put(msg)
-
-            socket_client_class = PlomSocketClient
-            if self.host.startswith('ws://') or self.host.startswith('wss://'):
-                socket_client_class = WebSocketClient
-            while True:
-                try:
-                    self.socket = socket_client_class(handle_recv, self.host)
-                    self.socket_thread = threading.Thread(target=self.socket.run)
-                    self.socket_thread.start()
-                    self.socket.send('TASKS')
-                    self.switch_mode('login')
-                    return
-                except ConnectionRefusedError:
-                    self.log_msg('@ server connect failure, trying again …')
-                    draw_screen()
-                    stdscr.refresh()
-                    time.sleep(1)
-
-        def reconnect():
-            self.send('QUIT')
-            time.sleep(0.1)  # FIXME necessitated by some some strange SSL race
-                             # conditions with ws4py, find out what exactly
-            self.switch_mode('waiting_for_server')
-            connect()
-
         def handle_input(msg):
             command, args = self.parser.parse(msg)
             command(*args)
@@ -559,13 +565,18 @@ class TUI:
         self.explorer = YX(0, 0)
         self.input_ = ''
         input_prompt = '> '
-        connect()
-        last_ping = datetime.datetime.now()
-        interval = datetime.timedelta(seconds=30)
+        interval = datetime.timedelta(seconds=5)
+        last_ping = datetime.datetime.now() - interval
         while True:
+            if self.disconnected and self.force_instant_connect:
+                self.force_instant_connect = False
+                self.connect()
             now = datetime.datetime.now()
             if now - last_ping > interval:
-                self.send('PING')
+                if self.disconnected:
+                    self.connect()
+                else:
+                    self.send('PING')
                 last_ping = now
             if self.do_refresh:
                 draw_screen()
@@ -613,8 +624,6 @@ class TUI:
                         self.switch_mode('play')
                     elif self.input_ in {'/' + self.keys['switch_to_study'], '/study'}:
                         self.switch_mode('study')
-                    elif self.input_ == '/reconnect':
-                        reconnect()
                     elif self.input_.startswith('/nick'):
                         tokens = self.input_.split(maxsplit=1)
                         if len(tokens) == 2:
@@ -650,7 +659,7 @@ class TUI:
             elif self.mode == self.mode_teleport and key == '\n':
                 if self.input_ == 'YES!':
                     self.host = self.teleport_target_host
-                    reconnect()
+                    self.reconnect()
                 else:
                     self.log_msg('@ teleport aborted')
                     self.switch_mode('play')
index e5bef1aa4d8a55ea2450874ab81def6e346b078b..bc30bde72b98106d7e1078a35baaaed261f196d8 100644 (file)
@@ -175,20 +175,18 @@ let server = {
         this.url = url;
         this.websocket = new WebSocket(this.url);
         this.websocket.onopen = function(event) {
-            window.setInterval(function() { server.send(['PING']) }, 30000);
-            this.send('TASKS');
+            server.connected = true;
+            server.send(['TASKS']);
             tui.log_msg("@ server connected! :)");
             tui.switch_mode(mode_login);
         };
         this.websocket.onclose = function(event) {
+            server.connected = false;
+            tui.switch_mode(mode_waiting_for_server);
             tui.log_msg("@ server disconnected :(");
-            tui.log_msg("@ hint: try the '/reconnect' command");
         };
            this.websocket.onmessage = this.handle_event;
         },
-    reconnect: function() {
-          this.reconnect_to(this.url);
-    },
     reconnect_to: function(url) {
         this.websocket.close();
         this.init(url);
@@ -253,7 +251,7 @@ let server = {
         } else if (tokens[0] === 'GAME_ERROR') {
             tui.log_msg('? game error: ' + tokens[1]);
         } else if (tokens[0] === 'PONG') {
-            console.log('PONG');
+            ;
         } else {
             tui.log_msg('? unhandled input: ' + event.data);
         }
@@ -786,12 +784,6 @@ tui.inputEl.addEventListener('keydown', (event) => {
                     } else {
                         tui.log_msg('? need message target and message');
                     }
-                } else if (tokens[0].slice(1) == 'reconnect') {
-                   if (tokens.length > 1) {
-                server.reconnect_to(tokens[1]);
-                   } else {
-                        server.reconnect();
-                   }
                 } else {
                     tui.log_msg('? unknown command');
                 }
@@ -876,5 +868,13 @@ window.setInterval(function() {
         tui.inputEl.focus();
     }
 }, 100);
+window.setInterval(function() {
+    if (server.connected) {
+        server.send(['PING']);
+    } else {
+        server.reconnect_to(server.url);
+        tui.log_msg('@ attempting reconnect …')
+    }
+}, 5000);
 </script>
 </body></html>