22A simple translation layer between tornado websockets and asyncio stream
33connections.
44
5- This subsumes the functionality of websockify
5+ This provides similar functionality to websockify
66(https://github.com/novnc/websockify) without needing an extra proxy hop
77or process through with all messages pass for translation.
88"""
1111
1212from .handlers import NamedLocalProxyHandler , SuperviseAndProxyHandler
1313
14- class WebsockifyProtocol (asyncio .Protocol ):
14+ class RawSocketProtocol (asyncio .Protocol ):
1515 """
1616 A protocol handler for the proxied stream connection.
1717 Sends any received blocks directly as websocket messages.
@@ -22,15 +22,16 @@ def __init__(self, handler):
2222 def data_received (self , data ):
2323 "Send the buffer as a websocket message."
2424 self .handler ._record_activity ()
25- # async "semi-synchronous", waiting is only needed for control flow and errors:
25+ # ignore async "semi-synchronous" result, waiting is only needed for control flow and errors
26+ # (see https://github.com/tornadoweb/tornado/blob/bdfc017c66817359158185561cee7878680cd841/tornado/websocket.py#L1073)
2627 self .handler .write_message (data , binary = True )
2728
2829 def connection_lost (self , exc ):
2930 "Close the websocket connection."
30- self .handler .log .info (f"Websockify { self .handler .name } connection lost: { exc } " )
31+ self .handler .log .info (f"Raw websocket { self .handler .name } connection lost: { exc } " )
3132 self .handler .close ()
3233
33- class WebsockifyHandler (NamedLocalProxyHandler ):
34+ class RawSocketHandler (NamedLocalProxyHandler ):
3435 """
3536 HTTP handler that proxies websocket connections into a backend stream.
3637 All other HTTP requests return 405.
@@ -39,51 +40,50 @@ def _create_ws_connection(self, proto: asyncio.BaseProtocol):
3940 "Create the appropriate backend asyncio connection"
4041 loop = asyncio .get_running_loop ()
4142 if self .unix_socket is not None :
42- self .log .info (f"Websockify { self .name } connecting to { self .unix_socket } " )
43+ self .log .info (f"RawSocket { self .name } connecting to { self .unix_socket } " )
4344 return loop .create_unix_connection (proto , self .unix_socket )
4445 else :
45- self .log .info (f"Websockify { self .name } connecting to port { self .port } " )
46+ self .log .info (f"RawSocket { self .name } connecting to port { self .port } " )
4647 return loop .create_connection (proto , 'localhost' , self .port )
4748
4849 async def proxy (self , port , path ):
49- raise web .HTTPError (405 , "websockets only" )
50+ raise web .HTTPError (405 , "this raw_socket_proxy backend only supports websocket connections " )
5051
5152 async def proxy_open (self , host , port , proxied_path = "" ):
5253 """
5354 Open the backend connection. host and port are ignored (as they are in
5455 the parent for unix sockets) since they are always passed known values.
5556 """
56- transp , proto = await self ._create_ws_connection (lambda : WebsockifyProtocol (self ))
57+ transp , proto = await self ._create_ws_connection (lambda : RawSocketProtocol (self ))
5758 self .ws_transp = transp
5859 self .ws_proto = proto
5960 self ._record_activity ()
60- self .log .info (f"Websockify { self .name } connected" )
61+ self .log .info (f"RawSocket { self .name } connected" )
6162
6263 def on_message (self , message ):
6364 "Send websocket messages as stream writes, encoding if necessary."
6465 self ._record_activity ()
65- if hasattr (self , "ws_transp" ):
66- if isinstance (message , str ):
67- message = message .encode ('utf-8' )
68- self .ws_transp .write (message ) # buffered non-blocking. should block?
66+ if isinstance (message , str ):
67+ message = message .encode ('utf-8' )
68+ self .ws_transp .write (message ) # buffered non-blocking. should block (needs new enough tornado)
6969
7070 def on_ping (self , message ):
7171 "No-op"
7272 self ._record_activity ()
7373
7474 def on_close (self ):
7575 "Close the backend connection."
76- self .log .info (f"Websockify { self .name } connection closed" )
76+ self .log .info (f"RawSocket { self .name } connection closed" )
7777 if hasattr (self , "ws_transp" ):
7878 self .ws_transp .close ()
7979
80- class SuperviseAndWebsockifyHandler (SuperviseAndProxyHandler , WebsockifyHandler ):
80+ class SuperviseAndRawSocketHandler (SuperviseAndProxyHandler , RawSocketHandler ):
8181 async def _http_ready_func (self , p ):
8282 # not really HTTP here, just try an empty connection
8383 try :
8484 transp , _ = await self ._create_ws_connection (asyncio .Protocol )
8585 except OSError as exc :
86- self .log .debug (f"Websockify { self .name } connection check failed: { exc } " )
86+ self .log .debug (f"RawSocket { self .name } connection check failed: { exc } " )
8787 return False
8888 transp .close ()
8989 return True
0 commit comments