Skip to content

Commit

Permalink
Improve terminals
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart committed May 14, 2024
1 parent 0e35a05 commit ebdab7f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
7 changes: 6 additions & 1 deletion plugins/terminals/fps_terminals/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
56 changes: 37 additions & 19 deletions plugins/terminals/fps_terminals/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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", {}])
Expand All @@ -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)

0 comments on commit ebdab7f

Please sign in to comment.