def __init__(self, url, protocols, extensions): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16)) self.url = url
def test_cannot_process_more_data_when_stream_is_terminated(self): m = MagicMock() ws = WebSocket(sock=m) ws.client_terminated = True ws.server_terminated = True self.assertFalse(ws.once())
def __init__(self, *args, **kw): WebSocket.__init__(self, *args, **kw) print str(self) + "connected" SUBSCRIBERS.add(self) global NextUID NextUID = NextUID + 1 UID = NextUID
def test_cannot_process_more_data_when_stream_is_terminated(self): m = MagicMock() ws = WebSocket(sock=m) ws.client_terminated = True ws.server_terminated = True self.assertFalse(ws.once())
def __init__(self, *args, **kw): """ Constructor. This will be called automatically by the server upon connection """ WebSocket.__init__(self, *args, **kw) self.close_callback = None
def __init__(self, url, protocols, extensions): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16)) self.url = url
def __init__(self, *args, **kw): WebSocket.__init__(self, *args, **kw) print str(self) + "connected" SUBSCRIBERS.add(self) global NextUID NextUID = NextUID + 1 UID = NextUID
def __init__(self, *args, **kwargs): self.widget_wslock = threading.Lock() # We don't know what DB they are connected to self.db = None self.session = drayerdb.Session(isClientSide=True) WebSocket.__init__(self, *args, **kwargs)
def test_sending_ping(self): tm = PingControlMessage("hello").single(mask=False) m = MagicMock() ws = WebSocket(sock=m) ws.ping("hello") m.sendall.assert_called_once_with(tm)
def test_send_message_without_masking(self): tm = TextMessage(b'hello world') m = MagicMock() ws = WebSocket(sock=m) ws.send(tm) m.sendall.assert_called_once_with(tm.single())
def test_send_message_without_masking(self): tm = TextMessage(b'hello world') m = MagicMock() ws = WebSocket(sock=m) ws.send(tm) m.sendall.assert_called_once_with(tm.single())
def test_sending_ping(self): tm = PingControlMessage("hello").single(mask=False) m = MagicMock() ws = WebSocket(sock=m) ws.ping("hello") m.sendall.assert_called_once_with(tm)
def __init__(self, *args, **kw): """ Constructor. This will be called automatically by the server upon connection """ WebSocket.__init__(self, *args, **kw) self.close_callback = None
def __init__(self, *args, **kwargs): """ This passes all arguments to the parent constructor. In addition, it defines the following instance variables: send_lock: Used to guarantee thread-safety when sending RPC responses. client_locks: A dict mapping client ids to locks used by those clients. passthru_subscriptions: When we recieve a subscription request for a service method registered on a remote service, we pass that request along to the remote service and send back the responses. This dictionary maps client ids to those subscription objects. session_fields: We copy session data for the currently-authenticated user who made the incoming websocket connection; by default we only copy the username, but this can be overridden in configuration. Remember that Sideboard exposes two websocket handlers at /ws and /wsrpc, with /ws being auth-protected (so the username field will be meaningful) and /wsrpc being client-cert protected (so the username will always be 'rpc'). header_fields: We copy header fields from the request that initiated the websocket connection. cached_queries and cached_fingerprints: When we receive a subscription update, Sideboard re-runs all of the subscription methods to see if new data needs to be pushed out. We do this by storing all of the rpc methods and an MD5 hash of their return values. We store a hash rather than the return values themselves to save on memory, since return values may be very large. The cached_queries dict has this structure: { 'client_id': { 'callback_id': (func, args, kwargs, client_data), ... }, ... } The cached_fingerprints dict has this structure: { 'client_id': { 'callback_id': 'md5_hash_of_return_value', ... }, ... } """ WebSocket.__init__(self, *args, **kwargs) self.instances.add(self) self.send_lock = RLock() self.passthru_subscriptions = {} self.client_locks = defaultdict(RLock) self.cached_queries, self.cached_fingerprints = defaultdict( dict), defaultdict(dict) self.session_fields = self.check_authentication() self.header_fields = self.fetch_headers()
def closed(self, *args): try: WebSocket.closed(self, *args) if handler[0]: handler[0].onClosed() except: logging.error("error in websocket handler:\n%s", traceback.format_exc())
def __init__(self, sock, protocols=None, extensions=None, environ=None, heartbeat_freq=None): WebSocket.__init__(self, sock, protocols, extensions, environ, heartbeat_freq)
def __init__(self, app_name, *args, **kw): self.app_name = app_name self.backend = get_backend() self.verbose = self.backend.verbose cherrypy.log.access_log.info( 'Creating %s with args=%s and keywords=%s.' % (self.app_name, args, kw)) WebSocket.__init__(self, *args, **kw) self.backend.register(self)
def __init__(self, *args, **kwargs): """ This passes all arguments to the parent constructor. In addition, it defines the following instance variables: send_lock: Used to guarantee thread-safety when sending RPC responses. client_locks: A dict mapping client ids to locks used by those clients. passthru_subscriptions: When we recieve a subscription request for a service method registered on a remote service, we pass that request along to the remote service and send back the responses. This dictionary maps client ids to those subscription objects. session_fields: We copy session data for the currently-authenticated user who made the incoming websocket connection; by default we only copy the username, but this can be overridden in configuration. Remember that Sideboard exposes two websocket handlers at /ws and /wsrpc, with /ws being auth-protected (so the username field will be meaningful) and /wsrpc being client-cert protected (so the username will always be 'rpc'). header_fields: We copy header fields from the request that initiated the websocket connection. cached_queries and cached_fingerprints: When we receive a subscription update, Sideboard re-runs all of the subscription methods to see if new data needs to be pushed out. We do this by storing all of the rpc methods and an MD5 hash of their return values. We store a hash rather than the return values themselves to save on memory, since return values may be very large. The cached_queries dict has this structure: { 'client_id': { 'callback_id': (func, args, kwargs, client_data), ... }, ... } The cached_fingerprints dict has this structure: { 'client_id': { 'callback_id': 'md5_hash_of_return_value', ... }, ... } """ WebSocket.__init__(self, *args, **kwargs) self.instances.add(self) self.send_lock = RLock() self.passthru_subscriptions = {} self.client_locks = defaultdict(RLock) self.cached_queries, self.cached_fingerprints = defaultdict(dict), defaultdict(dict) self.session_fields = self.check_authentication() self.header_fields = self.fetch_headers()
def __init__(self, app_name, *args, **kw): self.app_name = app_name self.backend = get_backend() self.verbose = self.backend.verbose cherrypy.log.access_log.info( 'Creating %s with args=%s and keywords=%s.' % (self.app_name, args, kw)) WebSocket.__init__(self, *args, **kw) self.backend.register(self)
def __init__(self, sock, protocols=None, extensions=None, environ=None, heartbeat_freq=None): WebSocket.__init__(self, sock, protocols, extensions, environ, heartbeat_freq) self.json_rpc = cherrypy.engine.json_rpc
def closed(self, code, reason=''): """ This overrides the default closed handler to first clean up all of our subscriptions, remove this websocket from the registry of instances, and log a message before closing. """ log.info('closing: code={!r} reason={!r}', code, reason) self.instances.discard(self) self.unsubscribe_all() WebSocket.closed(self, code, reason)
def closed(self, code, reason=''): """ This overrides the default closed handler to first clean up all of our subscriptions, remove this websocket from the registry of instances, and log a message before closing. """ log.info('closing: code={!r} reason={!r}', code, reason) self.instances.discard(self) self.unsubscribe_all() WebSocket.closed(self, code, reason)
def __init__(self, sock, protocols=None, extensions=None, environ=None, heartbeat_freq=None): WebSocket.__init__(self, sock) self.clients = [] self.settings = cherrypy.engine.publish('get-settings', 'gui')[0] self.type = 'gui'
def test_send_bytes_with_masking(self): tm = TextMessage(b'hello world').single(mask=True) m = MagicMock() ws = WebSocket(sock=m) ws.stream = MagicMock() ws.stream.always_mask = True ws.stream.text_message.return_value.single.return_value = tm ws.send(b'hello world') m.sendall.assert_called_once_with(tm)
def test_send_bytes_with_masking(self): tm = TextMessage(b'hello world').single(mask=True) m = MagicMock() ws = WebSocket(sock=m) ws.stream = MagicMock() ws.stream.always_mask = True ws.stream.text_message.return_value.single.return_value = tm ws.send(b'hello world') m.sendall.assert_called_once_with(tm)
def test_closing_message_received(self): s = MagicMock() m = MagicMock() c = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, close=c): ws.stream = s ws.stream.closing = CloseControlMessage(code=1000, reason='test closing') ws.process(b'unused for this test') c.assert_called_once_with(1000, b'test closing')
def join_queue(socket:WebSocket, data): # keep this order to avoid state conflict channel, pubsub = pub_sub_pool.join() r_queue.put(channel) # {'pattern': None, 'type': 'message', 'data': b'30ae154a-2397-4945-aeed-48dad6c603b6', 'channel': 'queue_channel:19'} msg = pub_sub_pool.next_message(channel, pubsub) uid = msg['data'] if not uid in games: games[uid] = make_game_engine() games[uid].join_game(data["player"]) socket.send(uid)
def __init__(self, *args, **kargs): WebSocket.__init__(self, *args, **kargs) self._logger = logging.getLogger('python') self.comMessage = { "sender": "python", "opCode": "info", "data": { "param": 0, "discription": '' } } print("_________init_________")
def test_closing_message_received(self): s = MagicMock() m = MagicMock() c = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, close=c): ws.stream = s ws.stream.closing = CloseControlMessage(code=1000, reason='test closing') ws.process(b'unused for this test') c.assert_called_once_with(1000, b'test closing')
def __init__(self, *args, **kw): WebSocket.__init__(self, *args, **kw) # cherrypy.log("args type %s" % type(ws)) # # for i in args: # try: # cherrypy.log("args %s \n" % i) # except Exception as error: # cherrypy.log("Can't print args because %s \n" % error) # cherrypy.log("args %s " % args) # cherrypy.log("kw %s " % kw) SUBSCRIBERS.add(self)
def __init__(self, *args, **kwargs): WebSocket.__init__(self, *args, **kwargs) self.debugger_store().chrome_channel.setSocket(self) common_domain_args = {'debugger_store': self.debugger_store()} runtime_domain = RuntimeDomain(**common_domain_args) debugger_domain = DebuggerDomain(runtime_domain, **common_domain_args) self.handlers = HandlerDomainSet( ConsoleDomain(**common_domain_args), debugger_domain, PageDomain(**common_domain_args), runtime_domain, )
def test_send_generator_without_masking(self): tm0 = b'hello' tm1 = b'world' def datasource(): yield tm0 yield tm1 gen = datasource() m = MagicMock() ws = WebSocket(sock=m) ws.send(gen) self.assertEqual(m.sendall.call_count, 2) self.assertRaises(StopIteration, next, gen)
def __init__(self, url, protocols, extensions, heartbeat_freq=None): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions, heartbeat_freq=heartbeat_freq) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16)) self.url = url self.host = None self.scheme = None self.port = None self.resource = None self._parse_url()
def send(self, **message): message = {k: v for k, v in message.items() if v is not None} if "data" in message and "client" in message: fingerprint = _fingerprint(message["data"]) client, callback = message["client"], message.get("callback") repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return self.log.debug("sending {}", message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(",", ":"), sort_keys=True) with self.send_lock: WebSocket.send(self, message)
def test_send_generator_without_masking(self): tm0 = b'hello' tm1 = b'world' def datasource(): yield tm0 yield tm1 gen = datasource() m = MagicMock() ws = WebSocket(sock=m) ws.send(gen) self.assertEqual(m.sendall.call_count, 2) self.assertRaises(StopIteration, next, gen)
def send(self, **message): message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: WebSocket.send(self, message)
def test_get_ipv6_addresses(self): m = MagicMock() m.getsockname.return_value = ('127.0.0.1', 52300, None, None) m.getpeername.return_value = ('127.0.0.1', 4800, None, None) ws = WebSocket(sock=m) self.assertEqual(ws.local_address, ('127.0.0.1', 52300)) self.assertEqual(ws.peer_address, ('127.0.0.1', 4800))
def __init__(self, *args, **kargs): WebSocket.__init__(self, *args, **kargs) self.isAlive = True self._logger = logging.getLogger('python') self.comMessage = { "sender": "python", "opCode": "info", "data": { "param": 0, "discription": '' } } self._serialThread = threading.Thread(target=self.serialLoop, name="wait serial data") self._serialThread.start() print("_________init_________")
def test_format_address(self): m = MagicMock() m.getsockname.return_value = ('127.0.0.1', 52300, None, None) m.getpeername.return_value = ('127.0.0.1', 4800, None, None) ws = WebSocket(sock=m) log = format_addresses(ws) self.assertEqual( log, "[Local => 127.0.0.1:52300 | Remote => 127.0.0.1:4800]")
def send(self, **message): message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: WebSocket.send(self, message)
def __init__(self, *args, **kargs): '''New websockets can be registered with the radio on creation. Channel names can be passed in the URL, for example: ws://localhost:1002/ws/chan0/chan1 A socket may be created with no channels, and then register one or more later on. This is how client-side Radio actually works. ''' WebSocket.__init__(self, *args, **kargs) # derive a list of zero or more channels from the url channels = str(self.environ['REQUEST_URI'])[2:-1].split('/')[2:] # if channels is empty, this does nothing radio.register(channels, self.send, True)
def __init__(self, *args, **kwargs): WebSocket.__init__(self, *args, **kwargs) self.debugger_store().chrome_channel.setSocket(self) common_domain_args = { 'debugger_store': self.debugger_store() } runtime_domain = RuntimeDomain(**common_domain_args) debugger_domain = DebuggerDomain( runtime_domain, **common_domain_args) self.handlers = HandlerDomainSet( ConsoleDomain(**common_domain_args), debugger_domain, PageDomain(**common_domain_args), runtime_domain, )
def test_terminate_with_closing(self): m = MagicMock() s = MagicMock() c = MagicMock() cc = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, closed=c, close_connection=cc): ws.stream = s ws.stream.closing = CloseControlMessage(code=1000, reason='test closing') ws.terminate() self.assertTrue(ws.client_terminated) self.assertTrue(ws.server_terminated) self.assertTrue(ws.terminated) c.assert_called_once_with(1000, b'test closing') cc.assert_called_once_with() self.assertIsNone(ws.stream) self.assertIsNone(ws.environ)
def test_terminate_without_closing(self): m = MagicMock() s = MagicMock() c = MagicMock() cc = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, closed=c, close_connection=cc): ws.stream = s ws.stream.closing = None ws.terminate() self.assertTrue(ws.client_terminated) self.assertTrue(ws.server_terminated) self.assertTrue(ws.terminated) c.assert_called_once_with(1006, "Going away") cc.assert_called_once_with() self.assertIsNone(ws.stream) self.assertIsNone(ws.environ)
def test_terminate_without_closing(self): m = MagicMock() s = MagicMock() c = MagicMock() cc = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, closed=c, close_connection=cc): ws.stream = s ws.stream.closing = None ws.terminate() self.assertTrue(ws.client_terminated) self.assertTrue(ws.server_terminated) self.assertTrue(ws.terminated) c.assert_called_once_with(1006, "Going away") cc.assert_called_once_with() self.assertIsNone(ws.stream) self.assertIsNone(ws.environ)
def __init__(self, url, protocols=None, extensions=None, heartbeat_freq=None): """ A websocket client that implements :rfc:`6455` and provides a simple interface to communicate with a websocket server. This class works on its own but will block if not run in its own thread. When an instance of this class is created, a :py:mod:`socket` is created with the nagle's algorithm disabled and with the capacity to reuse a port that was just used. The address of the server will be extracted from the given websocket url. The websocket key is randomly generated, reset the `key` attribute if you want to provide yours. """ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions, heartbeat_freq=heartbeat_freq) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16)) self.url = url self.host = None self.scheme = None self.port = None self.resource = None self._parse_url()
def send(self, **message): """ This overrides the ws4py-provided send to implement three new features: 1) Instead of taking a string, this method treats its keyword arguments as the message, serializes them to JSON, and sends that. 2) For subscription responses, we keep track of the most recent response we sent for the given subscription. If neither the request or response have changed since the last time we pushed data back to the client for this subscription, we don't send anything. 3) We lock when sending to ensure that our sends are thread-safe. Surprisingly, the "ws4py.threadedclient" class isn't thread-safe! 4) Subscriptions firing will sometimes trigger a send on a websocket which has already been marked as closed. When this happens we log a debug message and then exit without error. """ if self.is_closed: log.debug('ignoring send on an already closed websocket: {}', message) self.unsubscribe_all() return message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: if not self.is_closed: WebSocket.send(self, message)
def test_terminate_with_closing(self): m = MagicMock() s = MagicMock() c = MagicMock() cc = MagicMock() ws = WebSocket(sock=m) with patch.multiple(ws, closed=c, close_connection=cc): ws.stream = s ws.stream.closing = CloseControlMessage(code=1000, reason='test closing') ws.terminate() self.assertTrue(ws.client_terminated) self.assertTrue(ws.server_terminated) self.assertTrue(ws.terminated) c.assert_called_once_with(1000, b'test closing') cc.assert_called_once_with() self.assertIsNone(ws.stream) self.assertIsNone(ws.environ)
def test_close_connection(self): m = MagicMock() ws = WebSocket(sock=m) ws.close_connection() m.shutdown.assert_called_once_with(socket.SHUT_RDWR) m.close.assert_called_once_with() self.assertIsNone(ws.connection) m = MagicMock() m.close = MagicMock(side_effect=RuntimeError) ws = WebSocket(sock=m) ws.close_connection() self.assertIsNone(ws.connection)
def __init__(self, proto): """ A :pep:`3156` ready websocket handler that works well in a coroutine-aware loop such as the one provided by the asyncio module. The provided `proto` instance is a :class:`asyncio.Protocol` subclass instance that will be used internally to read and write from the underlying transport. Because the base :class:`ws4py.websocket.WebSocket` class is still coupled a bit to the socket interface, we have to override a little more than necessary to play nice with the :pep:`3156` interface. Hopefully, some day this will be cleaned out. """ _WebSocket.__init__(self, None) self.started = False self.proto = proto
def __init__(self, proto): """ A :pep:`3156` ready websocket handler that works well in a coroutine-aware loop such as the one provided by the asyncio module. The provided `proto` instance is a :class:`asyncio.Protocol` subclass instance that will be used internally to read and write from the underlying transport. Because the base :class:`ws4py.websocket.WebSocket` class is still coupled a bit to the socket interface, we have to override a little more than necessary to play nice with the :pep:`3156` interface. Hopefully, some day this will be cleaned out. """ _WebSocket.__init__(self, None) self.started = False self.proto = proto
def send(self, **message): """ This overrides the ws4py-provided send to implement three new features: 1) Instead of taking a string, this method treats its keyword arguments as the message, serializes them to JSON, and sends that. 2) For subscription responses, we keep track of the most recent response we sent for the given subscription. If neither the request or response have changed since the last time we pushed data back to the client for this subscription, we don't send anything. 3) We lock when sending to ensure that our sends are thread-safe. Surprisingly, the "ws4py.threadedclient" class isn't thread-safe! 4) Subscriptions firing will sometimes trigger a send on a websocket which has already been marked as closed. When this happens we log a debug message and then exit without error. """ if self.is_closed: log.debug('ignoring send on an already closed websocket: {}', message) self.unsubscribe_all() return message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: if not self.is_closed: WebSocket.send(self, message)
def __init__(self, url, protocols=None, extensions=None, heartbeat_freq=None): """ A websocket client that implements :rfc:`6455` and provides a simple interface to communicate with a websocket server. This class works on its own but will block if not run in its own thread. When an instance of this class is created, a :py:mod:`socket` is created with the nagle's algorithm disabled and with the capacity to reuse a port that was just used. The address of the server will be extracted from the given websocket url. The websocket key is randomly generated, reset the `key` attribute if you want to provide yours. """ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions, heartbeat_freq=heartbeat_freq) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16)) self.url = url self.host = None self.scheme = None self.port = None self.resource = None self._parse_url()
def __init__(self, *args, **kwargs): WebSocket.__init__(self, *args, **kwargs) common_domain_args = { 'debugger': self.debugger(), 'socket': self, } file_manager = FileManager(self) remote_object_manager = RemoteObjectManager() runtime_domain = RuntimeDomain( remote_object_manager, **common_domain_args) self.handlers = HandlerDomainSet( ConsoleDomain(**common_domain_args), DebuggerDomain( runtime_domain, file_manager, remote_object_manager, basepath=self.basepath(), **common_domain_args), PageDomain(**common_domain_args), runtime_domain, )
def test_close_connection(self): m = MagicMock() ws = WebSocket(sock=m) ws.close_connection() m.shutdown.assert_called_once_with(socket.SHUT_RDWR) m.close.assert_called_once_with() self.assertIsNone(ws.connection) m = MagicMock() m.close = MagicMock(side_effect=RuntimeError) ws = WebSocket(sock=m) ws.close_connection() self.assertIsNone(ws.connection)
def __init__(self, *args, **kw): WebSocket.__init__(self, *args, **kw) SUBSCRIBERS.add(self)
def test_socket_error_on_receiving_more_bytes(self): m = MagicMock() m.recv = MagicMock(side_effect=socket.error) ws = WebSocket(sock=m) self.assertFalse(ws.once())
def __init__(self, url, protocols=None, extensions=None, heartbeat_freq=None, ssl_options=None, headers=None): """ A websocket client that implements :rfc:`6455` and provides a simple interface to communicate with a websocket server. This class works on its own but will block if not run in its own thread. When an instance of this class is created, a :py:mod:`socket` is created. If the connection is a TCP socket, the nagle's algorithm is disabled. The address of the server will be extracted from the given websocket url. The websocket key is randomly generated, reset the `key` attribute if you want to provide yours. For instance to create a TCP client: .. code-block:: python >>> from websocket.client import WebSocketBaseClient >>> ws = WebSocketBaseClient('ws://localhost/ws') Here is an example for a TCP client over SSL: .. code-block:: python >>> from websocket.client import WebSocketBaseClient >>> ws = WebSocketBaseClient('wss://localhost/ws') Finally an example of a Unix-domain connection: .. code-block:: python >>> from websocket.client import WebSocketBaseClient >>> ws = WebSocketBaseClient('ws+unix:///tmp/my.sock') Note that in this case, the initial Upgrade request will be sent to ``/``. You may need to change this by setting the resource explicitely before connecting: .. code-block:: python >>> from websocket.client import WebSocketBaseClient >>> ws = WebSocketBaseClient('ws+unix:///tmp/my.sock') >>> ws.resource = '/ws' >>> ws.connect() You may provide extra headers by passing a list of tuples which must be unicode objects. """ self.url = url self.host = None self.scheme = None self.port = None self.unix_socket_path = None self.resource = None self.ssl_options = ssl_options or {} self.extra_headers = headers or [] self._parse_url() if self.unix_socket_path: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) else: # Let's handle IPv4 and IPv6 addresses # Simplified from CherryPy's code try: family, socktype, proto, canonname, sa = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0] except socket.gaierror: family = socket.AF_INET if self.host.startswith('::'): family = socket.AF_INET6 socktype = socket.SOCK_STREAM proto = 0 canonname = "" sa = (self.host, self.port, 0, 0) sock = socket.socket(family, socktype, proto) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) if hasattr(socket, 'AF_INET6') and family == socket.AF_INET6 and \ self.host.startswith('::'): try: sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) except (AttributeError, socket.error): pass WebSocket.__init__(self, sock, protocols=protocols, extensions=extensions, heartbeat_freq=heartbeat_freq) self.stream.always_mask = True self.stream.expect_masking = False self.key = b64encode(os.urandom(16))
def test_no_bytes_were_read(self): m = MagicMock() m.recv.return_value = b'' ws = WebSocket(sock=m) self.assertFalse(ws.once())