diff --git a/websocket_server/websocket_server.py b/websocket_server/websocket_server.py index 083ee17..b9568e3 100644 --- a/websocket_server/websocket_server.py +++ b/websocket_server/websocket_server.py @@ -65,6 +65,9 @@ def client_left(self, client, server): def message_received(self, client, server, message): pass + def binary_received(self, client, server, message): + pass + def set_fn_new_client(self, fn): self.new_client = fn @@ -74,6 +77,9 @@ def set_fn_client_left(self, fn): def set_fn_message_received(self, fn): self.message_received = fn + def set_fn_binary_received(self, fn): + self.binary_received = fn + def send_message(self, client, msg): self._unicast(client, msg) @@ -92,6 +98,9 @@ def shutdown_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_R def shutdown_abruptly(self): self._shutdown_abruptly() + def disconnect_client(self, client, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON): + self._disconnect_client(client, status, reason) + def disconnect_clients_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON): self._disconnect_clients_gracefully(status, reason) @@ -162,6 +171,9 @@ def _run_forever(self, threaded): def _message_received_(self, handler, msg): self.message_received(self.handler_to_client(handler), self, msg) + def _binary_received_(self, handler, msg): + self.binary_received(self.handler_to_client(handler), self, msg) + def _ping_received_(self, handler, msg): handler.send_pong(msg) @@ -233,6 +245,13 @@ def _shutdown_abruptly(self): self.server_close() self.shutdown() + def _disconnect_client(self, client, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON): + """ + Terminate a client gracefully without shutting down the server + """ + client["handler"].send_close(status, reason) + self._terminate_client_handler(client["handler"]) + def _disconnect_clients_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON): """ Terminate clients gracefully without shutting down the server @@ -315,8 +334,7 @@ def read_next_message(self): logger.warning("Continuation frames are not supported.") return elif opcode == OPCODE_BINARY: - logger.warning("Binary frames are not supported.") - return + opcode_handler = self.server._binary_received_ elif opcode == OPCODE_TEXT: opcode_handler = self.server._message_received_ elif opcode == OPCODE_PING: @@ -338,7 +356,7 @@ def read_next_message(self): for message_byte in self.read_bytes(payload_length): message_byte ^= masks[len(message_bytes) % 4] message_bytes.append(message_byte) - opcode_handler(self, message_bytes.decode('utf8')) + opcode_handler(self, message_bytes.decode('utf8') if opcode != OPCODE_BINARY else message_bytes) def send_message(self, message): self.send_text(message) @@ -376,16 +394,15 @@ def send_text(self, message, opcode=OPCODE_TEXT): # Validate message if isinstance(message, bytes): - message = try_decode_UTF8(message) # this is slower but ensures we have UTF-8 - if not message: - logger.warning("Can\'t send message, message is not valid UTF-8") - return False + payload = message + opcode = OPCODE_BINARY elif not isinstance(message, str): logger.warning('Can\'t send message, message has to be a string or bytes. Got %s' % type(message)) return False + else: + payload = encode_to_UTF8(message) header = bytearray() - payload = encode_to_UTF8(message) payload_length = len(payload) # Normal payload