diff options
Diffstat (limited to 'src/leap/bitmask/backend/backend_proxy.py')
-rw-r--r-- | src/leap/bitmask/backend/backend_proxy.py | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/src/leap/bitmask/backend/backend_proxy.py b/src/leap/bitmask/backend/backend_proxy.py index f683e465..e2611251 100644 --- a/src/leap/bitmask/backend/backend_proxy.py +++ b/src/leap/bitmask/backend/backend_proxy.py @@ -18,6 +18,8 @@ The BackendProxy handles calls from the GUI and forwards (through ZMQ) to the backend. """ +# XXX should document the relationship to the API here. + import functools import Queue import threading @@ -25,7 +27,7 @@ import time import zmq -from leap.bitmask.backend.api import API, STOP_REQUEST +from leap.bitmask.backend.api import API, STOP_REQUEST, PING_REQUEST from leap.bitmask.backend.utils import get_backend_certificates import logging @@ -37,9 +39,15 @@ class BackendProxy(object): The BackendProxy handles calls from the GUI and forwards (through ZMQ) to the backend. """ + PORT = '5556' SERVER = "tcp://localhost:%s" % PORT + POLL_TIMEOUT = 4000 # ms + POLL_TRIES = 3 + + PING_INTERVAL = 2 # secs + def __init__(self): self._socket = None @@ -62,6 +70,9 @@ class BackendProxy(object): socket.connect(self.SERVER) self._socket = socket + self._ping_at = 0 + self.online = False + self._call_queue = Queue.Queue() self._worker_caller = threading.Thread(target=self._worker) self._worker_caller.start() @@ -82,9 +93,26 @@ class BackendProxy(object): except Queue.Empty: pass time.sleep(0.01) + self._ping() logger.debug("BackendProxy worker stopped.") + def _reset_ping(self): + """ + Reset the ping timeout counter. + This is called for every ping and request. + """ + self._ping_at = time.time() + self.PING_INTERVAL + + def _ping(self): + """ + Heartbeat helper. + Sends a PING request just to know that the server is alive. + """ + if time.time() > self._ping_at: + self._send_request(PING_REQUEST) + self._reset_ping() + def _api_call(self, *args, **kwargs): """ Call the `api_method` method in backend (through zmq). @@ -134,16 +162,35 @@ class BackendProxy(object): # logger.debug("Sending request to backend: {0}".format(request)) self._socket.send(request) - try: - # Get the reply. - self._socket.recv() - # response = self._socket.recv() - # msg = "Received reply for '{0}' -> '{1}'" - # msg = msg.format(request, response) - # logger.debug(msg) - except zmq.error.Again as e: - msg = "Timeout error contacting backend. {0!r}".format(e) + poll = zmq.Poller() + poll.register(self._socket, zmq.POLLIN) + + reply = None + tries = 0 + + while True: + socks = dict(poll.poll(self.POLL_TIMEOUT)) + if socks.get(self._socket) == zmq.POLLIN: + reply = self._socket.recv() + break + + tries += 1 + if tries < self.POLL_TRIES: + logger.warning('Retrying receive... {0}/{1}'.format( + tries, self.POLL_TRIES)) + else: + break + + if reply is None: + msg = "Timeout error contacting backend." logger.critical(msg) + self.online = False + else: + # msg = "Received reply for '{0}' -> '{1}'".format(request, reply) + # logger.debug(msg) + self.online = True + # request received, no ping needed for other interval. + self._reset_ping() def __getattribute__(self, name): """ |