From f446edb202fdb545320f9b5d6022bca8eee1d348 Mon Sep 17 00:00:00 2001 From: Sergey Pikhovkin Date: Wed, 10 Oct 2018 22:08:22 +0300 Subject: [PATCH] Change methods --- README.md | 10 ++-- setup.py | 2 +- simple_websocket_server/__init__.py | 76 ++++++++++++++--------------- tests/example_server.py | 14 ++---- tests/test_servers.py | 72 +++++++++++++++++++++------ 5 files changed, 104 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 2e127eb..45a78c3 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,14 @@ from simple_websocket_server import WebSocketServer, WebSocket class SimpleEcho(WebSocket): - def handleMessage(self): + def handle(self): # echo message back to client self.send_message(self.data) - def handleConnected(self): + def connected(self): print(self.address, 'connected') - def handleClose(self): + def handle_close(self): print(self.address, 'closed') @@ -52,13 +52,13 @@ class SimpleChat(WebSocket): if client != self: client.send_message(self.address[0] + u' - ' + self.data) - def handleConnected(self): + def connected(self): print(self.address, 'connected') for client in clients: client.send_message(self.address[0] + u' - connected') clients.append(self) - def handleClose(self): + def handle_close(self): clients.remove(self) print(self.address, 'closed') for client in clients: diff --git a/setup.py b/setup.py index 2c3d554..8ef526c 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name='simple-websocket-server', - version='0.2.0', + version='0.3.0', author='Sergei Pikhovkin', author_email='s@pikhovkin.ru', packages=find_packages(exclude=['tests*']), diff --git a/simple_websocket_server/__init__.py b/simple_websocket_server/__init__.py index 2324030..20b2afd 100644 --- a/simple_websocket_server/__init__.py +++ b/simple_websocket_server/__init__.py @@ -118,19 +118,19 @@ def handle(self): """ pass - def handleConnected(self): + def connected(self): """ Called when a websocket client connects to the server. """ pass - def handleClose(self): + def handle_close(self): """ Called when a websocket server gets a Close frame from a client. """ pass - def _handlePacket(self): # pylint: disable=too-many-branches, too-many-statements + def _handle_packet(self): # pylint: disable=too-many-branches, too-many-statements if self.opcode == CLOSE: pass elif self.opcode == STREAM: @@ -233,7 +233,7 @@ def _handlePacket(self): # pylint: disable=too-many-branches, too-many-statemen self.handle() - def _handleData(self): + def _handle_data(self): # do the HTTP header and handshake if self.handshaked is False: data = self.client.recv(self.headertoread) @@ -255,10 +255,10 @@ def _handleData(self): key = self.request.headers['Sec-WebSocket-Key'] k = key.encode('ascii') + GUID_STR.encode('ascii') k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii') - hStr = HANDSHAKE_STR % {'acceptstr': k_s} - self.sendq.append((BINARY, hStr.encode('ascii'))) + hs = HANDSHAKE_STR % {'acceptstr': k_s} + self.sendq.append((BINARY, hs.encode('ascii'))) self.handshaked = True - self.handleConnected() + self.connected() except Exception as e: raise Exception('handshake failed: {}'.format(e)) @@ -270,10 +270,10 @@ def _handleData(self): if VER >= 3: for d in data: - self._parseMessage(d) + self._parse_message(d) else: for d in data: - self._parseMessage(ord(d)) + self._parse_message(ord(d)) def close(self, status=1000, reason=u''): """ @@ -296,7 +296,7 @@ def close(self, status=1000, reason=u''): finally: self.closed = True - def _sendBuffer(self, buff, send_all=False): + def _send_buffer(self, buff, send_all=False): size = len(buff) tosend = size already_sent = 0 @@ -322,7 +322,7 @@ def _sendBuffer(self, buff, send_all=False): return None - def sendFragmentStart(self, data): + def send_fragment_start(self, data): """ Send the start of a data fragment stream to a websocket client. Subsequent data should be sent using sendFragment(). @@ -337,7 +337,7 @@ def sendFragmentStart(self, data): self._send_message(True, opcode, data) - def sendFragment(self, data): + def send_fragment(self, data): """ see sendFragmentStart() @@ -346,7 +346,7 @@ def sendFragment(self, data): """ self._send_message(True, STREAM, data) - def sendFragmentEnd(self, data): + def send_fragment_end(self, data): """ see sendFragmentEnd() @@ -401,7 +401,7 @@ def _send_message(self, fin, opcode, data): self.sendq.append((opcode, payload)) - def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-statements + def _parse_message(self, byte): # pylint: disable=too-many-branches, too-many-statements # read in the header if self.state == HEADERB1: self.fin = byte & 0x80 @@ -436,7 +436,7 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st # if there is no mask and no payload we are done if self.length <= 0: try: - self._handlePacket() + self._handle_packet() finally: self.state = HEADERB1 self.data = bytearray() @@ -468,7 +468,7 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st # if there is no mask and no payload we are done if self.length <= 0: try: - self._handlePacket() + self._handle_packet() finally: self.state = HEADERB1 self.data = bytearray() @@ -494,7 +494,7 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st # if there is no mask and no payload we are done if self.length <= 0: try: - self._handlePacket() + self._handle_packet() finally: self.state = HEADERB1 self.data = bytearray() @@ -516,7 +516,7 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st # if there is no mask and no payload we are done if self.length <= 0: try: - self._handlePacket() + self._handle_packet() finally: self.state = HEADERB1 self.data = bytearray() @@ -541,7 +541,7 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st # check if we have processed length bytes; if so we are done if (self.index + 1) == self.length: try: - self._handlePacket() + self._handle_packet() finally: # self.index = 0 self.state = HEADERB1 @@ -553,20 +553,20 @@ def _parseMessage(self, byte): # pylint: disable=too-many-branches, too-many-st class WebSocketServer(object): request_queue_size = 5 - def __init__(self, host, port, websocketclass, selectInterval=0.1): + def __init__(self, host, port, websocketclass, select_interval=0.1): self.websocketclass = websocketclass self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.serversocket.bind((host, port)) self.serversocket.listen(self.request_queue_size) - self.selectInterval = selectInterval + self.selectInterval = select_interval self.connections = {} self.listeners = [self.serversocket] - def _decorateSocket(self, sock): # pylint: disable=no-self-use + def _decorate_socket(self, sock): # pylint: disable=no-self-use return sock - def _constructWebSocket(self, sock, address): + def _construct_websocket(self, sock, address): return self.websocketclass(self, sock, address) def close(self): @@ -578,10 +578,10 @@ def close(self): def _handle_close(self, client): # pylint: disable=no-self-use client.client.close() - # only call handleClose when we have a successful websocket connection + # only call handle_close when we have a successful websocket connection if client.handshaked: try: - client.handleClose() + client.handle_close() except Exception: # pylint: disable=broad-except pass @@ -595,16 +595,16 @@ def handle_request(self): # pylint: disable=too-many-branches, too-many-stateme writers.append(fileno) if self.selectInterval: - rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval) + r_list, w_list, x_list = select(self.listeners, writers, self.listeners, self.selectInterval) else: - rList, wList, xList = select(self.listeners, writers, self.listeners) + r_list, w_list, x_list = select(self.listeners, writers, self.listeners) - for ready in wList: + for ready in w_list: client = self.connections[ready] try: while client.sendq: opcode, payload = client.sendq.popleft() - remaining = client._sendBuffer(payload) # pylint: disable=protected-access + remaining = client._send_buffer(payload) # pylint: disable=protected-access if remaining is not None: client.sendq.appendleft((opcode, remaining)) break @@ -617,15 +617,15 @@ def handle_request(self): # pylint: disable=too-many-branches, too-many-stateme del self.connections[ready] self.listeners.remove(ready) - for ready in rList: + for ready in r_list: if ready == self.serversocket: sock = None try: sock, address = self.serversocket.accept() - newsock = self._decorateSocket(sock) + newsock = self._decorate_socket(sock) newsock.setblocking(0) # pylint: disable=no-member fileno = newsock.fileno() # pylint: disable=no-member - self.connections[fileno] = self._constructWebSocket(newsock, address) + self.connections[fileno] = self._construct_websocket(newsock, address) self.listeners.append(fileno) except Exception: # pylint: disable=broad-except if sock is not None: @@ -635,13 +635,13 @@ def handle_request(self): # pylint: disable=too-many-branches, too-many-stateme continue client = self.connections[ready] try: - client._handleData() # pylint: disable=protected-access + client._handle_data() # pylint: disable=protected-access except Exception: # pylint: disable=broad-except self._handle_close(client) del self.connections[ready] self.listeners.remove(ready) - for failed in xList: + for failed in x_list: if failed == self.serversocket: self.close() raise Exception('server socket failed') @@ -661,17 +661,17 @@ def serve_forever(self): class SSLWebSocketServer(WebSocketServer): # pylint: disable=too-many-arguments def __init__(self, host, port, websocketclass, certfile, keyfile, - version=ssl.PROTOCOL_TLSv1, selectInterval=0.1): - WebSocketServer.__init__(self, host, port, websocketclass, selectInterval) + version=ssl.PROTOCOL_TLSv1, select_interval=0.1): + WebSocketServer.__init__(self, host, port, websocketclass, select_interval) self.context = ssl.SSLContext(version) self.context.load_cert_chain(certfile, keyfile) - def _decorateSocket(self, sock): + def _decorate_socket(self, sock): sslsock = self.context.wrap_socket(sock, server_side=True) return sslsock - def _constructWebSocket(self, sock, address): + def _construct_websocket(self, sock, address): ws = self.websocketclass(self, sock, address) ws.usingssl = True return ws diff --git a/tests/example_server.py b/tests/example_server.py index 3903747..b24a5d2 100644 --- a/tests/example_server.py +++ b/tests/example_server.py @@ -9,29 +9,23 @@ class SimpleEcho(WebSocket): - def handleMessage(self): + def handle(self): self.send_message(self.data) - def handleConnected(self): - pass - - def handleClose(self): - pass - class SimpleChat(WebSocket): - def handleMessage(self): + def handle(self): for client in clients: if client != self: client.send_message(self.address[0] + u' - ' + self.data) - def handleConnected(self): + def connected(self): print(self.address, 'connected') for client in clients: client.send_message(self.address[0] + u' - connected') clients.append(self) - def handleClose(self): + def handle_close(self): clients.remove(self) print(self.address, 'closed') for client in clients: diff --git a/tests/test_servers.py b/tests/test_servers.py index 6aa8391..88f3943 100644 --- a/tests/test_servers.py +++ b/tests/test_servers.py @@ -1,41 +1,81 @@ # coding: utf-8 from __future__ import print_function +import sys from threading import Thread from contextlib import contextmanager import unittest -from websocket import create_connection, ABNF +VER = sys.version_info[0] +if VER >= 3: + from queue import Queue +else: + from Queue import Queue + +from websocket import create_connection from simple_websocket_server import WebSocketServer, WebSocket +HOST = 'localhost' +PORT = 38200 + + class SimpleEcho(WebSocket): def handle(self): self.send_message(self.data) +class WSServer(WebSocketServer): + request_queue_size = 1000 + + class TestWebSocketServer(unittest.TestCase): @staticmethod @contextmanager - def server(handler): - server = WebSocketServer('localhost', 38200, handler) + def server(server_cls, handler_cls): + server = server_cls(HOST, PORT, handler_cls) server_thread = Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() yield server server.close() - @staticmethod - @contextmanager - def client(): - ws = create_connection('ws://{}:{}'.format('localhost', 38200)) - yield ws - ws.close() - - def test_echo(self): - data = '$äüö^' - with self.server(SimpleEcho): - with self.client() as client: - client.send(data) - self.assertTrue(client.recv() == data) + def test_load(self): + class Worker(Thread): + def __init__(self, q_input, q_output): + self.q_input = q_input + self.q_output = q_output + + super(Worker, self).__init__() + + def run(self): + tasks = self.q_input.get() + while tasks > 0: + tasks -= 1 + + ws = create_connection('ws://{}:{}'.format(HOST, PORT)) + ws.send('$äüö^') + + self.q_output.put(ws.recv()) + + ws.close() + + self.q_input.task_done() + + q_input = Queue() + q_output = Queue() + + CLIENTS = 500 + MESSAGES = 10 + + for r in range(CLIENTS): + q_input.put(MESSAGES) + + with self.server(WSServer, SimpleEcho): + for r in range(CLIENTS): + w = Worker(q_input, q_output) + w.setDaemon(True) + w.start() + + q_input.join()