Spaces:
Runtime error
Runtime error
| # backend/vnc_proxy.py | |
| import asyncio | |
| import websockets | |
| import socket | |
| import logging | |
| from typing import Optional | |
| logger = logging.getLogger(__name__) | |
| class VNCWebSocketProxy: | |
| def __init__(self, vnc_host: str = "localhost", vnc_port: int = 5901): | |
| self.vnc_host = vnc_host | |
| self.vnc_port = vnc_port | |
| self.server = None | |
| async def start_proxy(self, websocket_port: int): | |
| """Start the WebSocket to VNC proxy server""" | |
| try: | |
| self.server = await websockets.serve( | |
| self.handle_websocket, | |
| "localhost", | |
| websocket_port | |
| ) | |
| logger.info(f"VNC WebSocket proxy started on port {websocket_port}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"Failed to start VNC proxy: {e}") | |
| return False | |
| async def stop_proxy(self): | |
| """Stop the proxy server""" | |
| if self.server: | |
| self.server.close() | |
| await self.server.wait_closed() | |
| async def handle_websocket(self, websocket, path): | |
| """Handle WebSocket connections and proxy to VNC""" | |
| vnc_socket = None | |
| try: | |
| # Connect to VNC server | |
| vnc_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| vnc_socket.connect((self.vnc_host, self.vnc_port)) | |
| vnc_socket.setblocking(False) | |
| logger.info(f"Connected to VNC server at {self.vnc_host}:{self.vnc_port}") | |
| # Create tasks for bidirectional communication | |
| ws_to_vnc_task = asyncio.create_task( | |
| self.websocket_to_vnc(websocket, vnc_socket) | |
| ) | |
| vnc_to_ws_task = asyncio.create_task( | |
| self.vnc_to_websocket(vnc_socket, websocket) | |
| ) | |
| # Wait for either task to complete (indicating disconnection) | |
| await asyncio.gather(ws_to_vnc_task, vnc_to_ws_task, return_exceptions=True) | |
| except Exception as e: | |
| logger.error(f"Error in VNC proxy: {e}") | |
| finally: | |
| if vnc_socket: | |
| vnc_socket.close() | |
| async def websocket_to_vnc(self, websocket, vnc_socket): | |
| """Forward WebSocket messages to VNC""" | |
| try: | |
| async for message in websocket: | |
| if isinstance(message, bytes): | |
| await asyncio.get_event_loop().sock_sendall(vnc_socket, message) | |
| except websockets.exceptions.ConnectionClosed: | |
| pass | |
| except Exception as e: | |
| logger.error(f"Error forwarding WebSocket to VNC: {e}") | |
| async def vnc_to_websocket(self, vnc_socket, websocket): | |
| """Forward VNC messages to WebSocket""" | |
| try: | |
| while True: | |
| data = await asyncio.get_event_loop().sock_recv(vnc_socket, 4096) | |
| if not data: | |
| break | |
| await websocket.send(data) | |
| except websockets.exceptions.ConnectionClosed: | |
| pass | |
| except Exception as e: | |
| logger.error(f"Error forwarding VNC to WebSocket: {e}") | |
| # Global proxy manager | |
| vnc_proxies = {} | |
| async def start_vnc_proxy(vnc_port: int) -> Optional[int]: | |
| """Start a VNC WebSocket proxy for the given VNC port""" | |
| websocket_port = vnc_port + 1000 # Offset for WebSocket port | |
| if websocket_port in vnc_proxies: | |
| return websocket_port | |
| proxy = VNCWebSocketProxy("localhost", vnc_port) | |
| success = await proxy.start_proxy(websocket_port) | |
| if success: | |
| vnc_proxies[websocket_port] = proxy | |
| return websocket_port | |
| return None | |
| async def stop_vnc_proxy(websocket_port: int): | |
| """Stop a VNC WebSocket proxy""" | |
| if websocket_port in vnc_proxies: | |
| await vnc_proxies[websocket_port].stop_proxy() | |
| del vnc_proxies[websocket_port] |