1# -*- coding: utf-8 -*- 2""" 3 sockjs.tornado.transports.rawwebsocket 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 6 Raw websocket transport implementation 7""" 8import logging 9import socket 10 11from sockjs.tornado import websocket, session 12from sockjs.tornado.transports import base 13 14LOG = logging.getLogger("tornado.general") 15 16class RawSession(session.BaseSession): 17 """Raw session without any sockjs protocol encoding/decoding. Simply 18 works as a proxy between `SockJSConnection` class and `RawWebSocketTransport`.""" 19 def send_message(self, msg, stats=True, binary=False): 20 self.handler.send_pack(msg, binary) 21 22 def on_message(self, msg): 23 self.conn.on_message(msg) 24 25 26class RawWebSocketTransport(websocket.SockJSWebSocketHandler, base.BaseTransportMixin): 27 """Raw Websocket transport""" 28 name = 'rawwebsocket' 29 30 def initialize(self, server): 31 self.server = server 32 self.session = None 33 self.active = True 34 35 def open(self): 36 # Stats 37 self.server.stats.on_conn_opened() 38 39 # Disable nagle if needed 40 if self.server.settings['disable_nagle']: 41 self.stream.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) 42 43 # Create and attach to session 44 self.session = RawSession(self.server.get_connection_class(), self.server) 45 self.session.set_handler(self) 46 self.session.verify_state() 47 48 def _detach(self): 49 if self.session is not None: 50 self.session.remove_handler(self) 51 self.session = None 52 53 def on_message(self, message): 54 # SockJS requires that empty messages should be ignored 55 if not message or not self.session: 56 return 57 58 try: 59 self.session.on_message(message) 60 except Exception: 61 LOG.exception('RawWebSocket') 62 63 # Close running connection 64 self.abort_connection() 65 66 def on_close(self): 67 # Close session if websocket connection was closed 68 if self.session is not None: 69 # Stats 70 self.server.stats.on_conn_closed() 71 72 session = self.session 73 self._detach() 74 session.close() 75 76 def send_pack(self, message, binary=False): 77 # Send message 78 try: 79 self.write_message(message, binary) 80 except IOError: 81 self.server.io_loop.add_callback(self.on_close) 82 83 def session_closed(self): 84 try: 85 self.close() 86 except IOError: 87 pass 88 finally: 89 self._detach() 90 91 # Websocket overrides 92 def allow_draft76(self): 93 return True 94