Skip to content

Commit

Permalink
custom dispatcher pings/timeouts (#795)
Browse files Browse the repository at this point in the history
* rel example

* tweaked rel example for linter

* added rel note to examples.rst

* slightly more compact example

* added example header

* matched wording

* _socket.recv(): _recv() except socket.error - changed or to and; added except TimeoutError - raise WebSocketTimeoutException

* _app - custom dispatcher check_callback() integration (and fixed pyevent compatibility): WrappedDispatcher (for use with generic event dispatchers such as pyevent and rel); create_dispatcher() accepts dispatcher kwarg (default None), and if it is specified, returns a WrappedDispatcher; use create_dispatcher() (passing specified dispatcher if any) every time (regardless of dispatcher specification)

* Add clarifying comment, rerun CI tests

* Add space to make linter happy

Co-authored-by: engn33r <engn33r@users.noreply.github.com>
  • Loading branch information
bubbleboy14 and engn33r committed Feb 25, 2022
1 parent 8d11afc commit f719d0a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
21 changes: 18 additions & 3 deletions websocket/_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ def select(self):
return r[0][0]


class WrappedDispatcher:
"""
WrappedDispatcher
"""
def __init__(self, app, ping_timeout, dispatcher):
self.app = app
self.ping_timeout = ping_timeout
self.dispatcher = dispatcher

def read(self, sock, read_callback, check_callback):
self.dispatcher.read(sock, read_callback)
self.ping_timeout and self.dispatcher.timeout(self.ping_timeout, check_callback)


class WebSocketApp:
"""
Higher level of APIs are provided. The interface is like JavaScript WebSocket object.
Expand Down Expand Up @@ -316,8 +330,7 @@ def teardown(close_frame=None):
http_proxy_auth=http_proxy_auth, subprotocols=self.subprotocols,
host=host, origin=origin, suppress_origin=suppress_origin,
proxy_type=proxy_type)
if not dispatcher:
dispatcher = self.create_dispatcher(ping_timeout)
dispatcher = self.create_dispatcher(ping_timeout, dispatcher)

self._callback(self.on_open)

Expand Down Expand Up @@ -375,7 +388,9 @@ def check():
teardown()
return not isinstance(e, KeyboardInterrupt)

def create_dispatcher(self, ping_timeout):
def create_dispatcher(self, ping_timeout, dispatcher=None):
if dispatcher: # If custom dispatcher is set, use WrappedDispatcher
return WrappedDispatcher(self, ping_timeout, dispatcher)
timeout = ping_timeout or 10
if self.sock.is_ssl():
return SSLDispatcher(self, timeout)
Expand Down
6 changes: 3 additions & 3 deletions websocket/_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ def _recv():
pass
except socket.error as exc:
error_code = extract_error_code(exc)
if error_code is None:
raise
if error_code != errno.EAGAIN or error_code != errno.EWOULDBLOCK:
if error_code != errno.EAGAIN and error_code != errno.EWOULDBLOCK:
raise

sel = selectors.DefaultSelector()
Expand All @@ -111,6 +109,8 @@ def _recv():
bytes_ = sock.recv(bufsize)
else:
bytes_ = _recv()
except TimeoutError:
raise WebSocketTimeoutException("Connection timed out")
except socket.timeout as e:
message = extract_err_message(e)
raise WebSocketTimeoutException(message)
Expand Down

0 comments on commit f719d0a

Please sign in to comment.