From ebdab7fda3cfa7a573a3fc034d10be0f8d577937 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Tue, 14 May 2024 16:56:00 +0200 Subject: [PATCH] Improve terminals --- plugins/terminals/fps_terminals/routes.py | 7 ++- plugins/terminals/fps_terminals/server.py | 56 +++++++++++++++-------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/plugins/terminals/fps_terminals/routes.py b/plugins/terminals/fps_terminals/routes.py index ca7d2f8d..6a0bf489 100644 --- a/plugins/terminals/fps_terminals/routes.py +++ b/plugins/terminals/fps_terminals/routes.py @@ -26,7 +26,12 @@ async def create_terminal( self, user: User, ): - name = str(len(TERMINALS) + 1) + name_int = 1 + while True: + if str(name_int) not in TERMINALS: + break + name_int += 1 + name = str(name_int) terminal = Terminal( name=name, last_activity=datetime.utcnow().isoformat() + "Z", diff --git a/plugins/terminals/fps_terminals/server.py b/plugins/terminals/fps_terminals/server.py index cf3805e4..6af794a7 100644 --- a/plugins/terminals/fps_terminals/server.py +++ b/plugins/terminals/fps_terminals/server.py @@ -30,20 +30,28 @@ def __init__(self): async def serve(self, websocket, permissions): self.websocket = websocket self.websockets.append(websocket) - self.event = asyncio.Event() + self.data_from_terminal = asyncio.Queue() self.loop = asyncio.get_event_loop() task = asyncio.create_task(self.send_data()) def on_output(): try: - self.data_or_disconnect = self.p_out.read(65536).decode() - self.event.set() - except Exception: - os.close(self.fd) - self.loop.remove_reader(self.p_out) - self.data_or_disconnect = None - self.event.set() + data = self.p_out.read(65536).decode() + except OSError: + try: + self.loop.remove_reader(self.p_out) + except Exception: + pass + try: + os.close(self.fd) + except OSError: + pass + self.data_from_terminal.put_nowait(None) + self.websockets.clear() + self.quit() + else: + self.data_from_terminal.put_nowait(data) self.loop.add_reader(self.p_out, on_output) await websocket.send_json(["setup", {}]) @@ -58,21 +66,31 @@ def on_output(): winsize = struct.pack("HH", msg[1], msg[2]) fcntl.ioctl(self.fd, termios.TIOCSWINSZ, winsize) except WebSocketDisconnect: - task.cancel() + self.quit(websocket) async def send_data(self): while True: - await self.event.wait() - self.event.clear() - if self.data_or_disconnect is None: - await self.websocket.send_json(["disconnect", 1]) - else: - for websocket in self.websockets: - await websocket.send_json(["stdout", self.data_or_disconnect]) + data = await self.data_from_terminal.get() + if data is None: + try: + await self.websocket.send_json(["disconnect", 1]) + except Exception: + pass + return + + for websocket in self.websockets: + await websocket.send_json(["stdout", data]) - def quit(self, websocket): + def quit(self, websocket=None): if websocket in self.websockets: self.websockets.remove(websocket) if not self.websockets: - os.close(self.fd) - self.loop.remove_reader(self.p_out) + try: + self.loop.remove_reader(self.p_out) + except Exception: + pass + try: + os.close(self.fd) + except OSError: + pass + self.data_from_terminal.put_nowait(None)