mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
fix: handle client disconnect in compute console WebSocket forwarding
The compute-side telnet_forward (and vnc_forward) let the
WebSocketDisconnect that starlette raises from send_bytes once the peer
is gone escape to the generic task-exception handler. Its str() is
empty, so every client disconnect during active node output logged a
message-less warning:
WARNING gns3server.compute.base_node:658 Exception while forwarding
WebSocket data to TELNET server:
Catch WebSocketDisconnect in both forwarders and log it at INFO as the
normal end of a session, and format the remaining task exceptions with
!r so their type stays visible. Mirrors the controller-side fix for
the same scenario (2324dcd74).
This commit is contained in:
2 files changed
+79
-7
No files matched your search
@@ -640,10 +640,20 @@ class BaseNode:
|
||||
|
||||
async def telnet_forward(telnet_reader):
|
||||
|
||||
while not telnet_reader.at_eof():
|
||||
data = await telnet_reader.read(1024)
|
||||
if data:
|
||||
await websocket.send_bytes(data)
|
||||
try:
|
||||
while not telnet_reader.at_eof():
|
||||
data = await telnet_reader.read(1024)
|
||||
if data:
|
||||
await websocket.send_bytes(data)
|
||||
except WebSocketDisconnect:
|
||||
# the client disconnected while node output was still streaming:
|
||||
# normal end of the session, not an error. Starlette raises
|
||||
# WebSocketDisconnect (whose str() is empty) from send once the
|
||||
# peer is gone, which used to surface as a message-less warning.
|
||||
log.info(
|
||||
f"Client {websocket.client.host}:{websocket.client.port} has disconnected from compute"
|
||||
f" console WebSocket while node output was being forwarded"
|
||||
)
|
||||
|
||||
# keep forwarding websocket data in both direction
|
||||
if sys.version_info >= (3, 11, 0):
|
||||
@@ -657,7 +667,7 @@ class BaseNode:
|
||||
if task.exception():
|
||||
log.warning(
|
||||
f"Exception while forwarding WebSocket data to "
|
||||
f"{self._console_type.upper()} server: {task.exception()}"
|
||||
f"{self._console_type.upper()} server: {task.exception()!r}"
|
||||
)
|
||||
for task in pending:
|
||||
task.cancel()
|
||||
@@ -728,8 +738,16 @@ class BaseNode:
|
||||
data = await vnc_reader.read(65536) # Larger buffer for VNC frames
|
||||
if data:
|
||||
await websocket.send_bytes(data)
|
||||
except WebSocketDisconnect:
|
||||
# the browser disconnected while VNC frames were still streaming
|
||||
# (starlette raises WebSocketDisconnect with an empty str() from
|
||||
# send once the peer is gone — not an error)
|
||||
log.info(
|
||||
f"Client {websocket.client.host}:{websocket.client.port} has disconnected from compute "
|
||||
f"VNC console WebSocket while frames were being forwarded"
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(f"Exception while forwarding VNC data to WebSocket: {e}")
|
||||
log.warning(f"Exception while forwarding VNC data to WebSocket: {e!r}")
|
||||
|
||||
# Keep forwarding WebSocket data in both directions
|
||||
if sys.version_info >= (3, 11, 0):
|
||||
@@ -741,7 +759,7 @@ class BaseNode:
|
||||
done, pending = await asyncio.wait(aws, return_when=asyncio.FIRST_COMPLETED)
|
||||
for task in done:
|
||||
if task.exception():
|
||||
log.warning(f"Exception while forwarding WebSocket data to VNC server: {task.exception()}")
|
||||
log.warning(f"Exception while forwarding WebSocket data to VNC server: {task.exception()!r}")
|
||||
for task in pending:
|
||||
task.cancel()
|
||||
|
||||
|
||||
Reference in new issue
Block a user