6 from plomrogue.errors import BrokenSocketConnection
7 from plomrogue.io_tcp import PlomSocket
8 from ws4py.client import WebSocketBaseClient
12 class WebSocketClient(WebSocketBaseClient):
14 def __init__(self, recv_handler, *args, **kwargs):
15 super().__init__(*args, **kwargs)
16 self.recv_handler = recv_handler
19 def received_message(self, message):
21 message = str(message)
22 self.recv_handler(message)
25 def plom_closed(self):
26 return self.client_terminated
30 class PlomSocketClient(PlomSocket):
32 def __init__(self, recv_handler, url):
34 self.recv_handler = recv_handler
35 host, port = url.split(':')
36 super().__init__(socket.create_connection((host, port)))
44 for msg in self.recv():
46 self.socket = ssl.wrap_socket(self.socket)
48 self.recv_handler(msg)
49 except BrokenSocketConnection:
50 pass # we assume socket will be known as dead by now
56 def __init__(self, host, logger=None):
59 self.queue = queue.Queue()
60 self.disconnected = True
61 self.force_instant_connect = True
62 self.interval = datetime.timedelta(seconds=5)
63 self.last_ping = datetime.datetime.now() - self.interval
78 self.log('attempting connect')
79 socket_client_class = PlomSocketClient
80 if self.host.startswith('ws://') or self.host.startswith('wss://'):
81 socket_client_class = WebSocketClient
83 self.socket = socket_client_class(handle_recv, self.host)
84 self.socket_thread = threading.Thread(target=self.socket.run)
85 self.socket_thread.start()
86 self.disconnected = False
87 time.sleep(0.1) # give potential SSL negotation some time …
89 except ConnectionRefusedError:
90 self.log('server connect failure')
91 self.disconnected = True
95 if self.socket is None:
96 raise BrokenSocketConnection
97 if hasattr(self.socket, 'plom_closed') and self.socket.plom_closed:
98 raise BrokenSocketConnection
100 except (BrokenPipeError, BrokenSocketConnection):
101 self.log('server disconnected :(')
102 self.disconnected = True
103 self.force_instant_connect = True
105 def keep_connection_alive(self):
106 if self.disconnected and self.force_instant_connect:
107 self.force_instant_connect = False
109 now = datetime.datetime.now()
110 if now - self.last_ping > self.interval:
111 if self.disconnected:
117 def get_message(self):
120 msg = self.queue.get(block=False)