Exemple #1
0
    def service_internal(self, service, msg, clear):
        """Handle internal service according to 8/MMI specification"""
        returncode = b"501"
        if b"mmi.service" == service:
            name = msg[-1]
            returncode = b"200" if name in self.services else b"404"
        if b"mmi.services" == service:
            name = msg[-1]
            sl = []
            for serv in self.services:
                sl.append(serv.decode())
            returncode = json.dumps({'services': sl}).encode()
            logging.warning('mmi.services : {0}'.format(returncode))
        if b"mmi.workers" == service:
            name = msg[-1]
            wl = []
            for w in self.workers:
                wl.append(w.decode())
            returncode = json.dumps({'workers': wl}).encode()
            logging.warning('mmi.services : {0}'.format(returncode))
        msg[-1] = returncode

        # insert the protocol header and service name after the routing envelope ([client, ''])
        msg = msg[:2] + [IDP.C_CLIENT, service] + msg[2:]

        if self.verbose:
            logging.info("I: sending MMI reply")
            dump(msg)
        if clear:
            self.socketclear.send(msg)
        else:
            self.socketcurve.send(msg)
Exemple #2
0
    def send_to_worker(self, worker, command, option, msg=None):
        """Send message to worker.

        If message is provided, sends that message.
        """

        if msg is None:
            msg = []
        elif not isinstance(msg, list):
            msg = [msg]

        # Stack routing and protocol envelopes to start of message
        # and routing envelope
        if option is not None:
            msg = [option] + msg
        msg = [worker.address, b'', IDP.W_WORKER, command] + msg

        if self.verbose:
            logging.info("I: sending %r to worker", command)
            dump(msg)

        if (worker.clear):
            self.socketclear.send(msg)
        else:
            self.socketcurve.send(msg)
Exemple #3
0
    def recv(self):

        try:
            items = self.poller.poll(self.timeout)
        except KeyboardInterrupt:
            return None  # interrupted

        if items:
            msg = self.client.recv()
            if self.verbose:
                logging.info("I: received reply:")
                dump(msg)

            # Don't try to handle errors, just assert noisily
            assert len(msg) >= 4

            msg.pop(0)
            header = msg.pop(0)
            assert IDP.C_CLIENT == header

            msg.pop(0)  # popping reply service
            reply = msg
        else:
            reply = None

        return reply
Exemple #4
0
    def send(self, service, request):
        """Send request to broker and get reply by hook or crook.
        Takes ownership of request message and destroys it when sent.
        Returns the reply message or None if there was no reply.
        """
        if not isinstance(request, list):
            request = [request]
        request = [b'', IDP.C_CLIENT, service] + request
        if self.verbose:
            logging.info("I: send request to '%s' service: ", service)
            dump(request)

        self.client.send(request)
Exemple #5
0
    def send(self, service, request):
        """Send request to broker and get reply by hook or crook.
        Takes ownership of request message and destroys it when sent.
        Returns the reply message or None if there was no reply.
        """
        if not isinstance(request, list):
            request = [request]
        request = [IDP.C_CLIENT, service] + request
        if self.verbose:
            logging.info("I: send request to '%s' service: ", service)
            dump(request)
        reply = None

        retries = self.retries
        while retries > 0:
            self.client.send(request)
            try:
                items = self.poller.poll(self.timeout)
            except KeyboardInterrupt:
                break  # interrupted

            if items:
                msg = self.client.recv()
                if self.verbose:
                    logging.info("I: received reply:")
                    dump(msg)

                # Don't try to handle errors, just assert noisily
                assert len(msg) >= 3

                header = msg.pop(0)
                assert IDP.C_CLIENT == header

                reply_service = msg.pop(0)
                assert service == reply_service

                reply = msg
                break
            else:
                if retries:
                    logging.warn("W: no reply, reconnecting...")
                    self.reconnect_to_broker()
                else:
                    logging.warn("W: permanent error, abandoning")
                    break
                retries -= 1

        return reply
Exemple #6
0
    def send_to_broker(self, command, option=None, msg=None):
        """Send message to broker.
        If no msg is provided, creates one internally
        """
        if msg is None:
            msg = []
        elif not isinstance(msg, list):
            msg = [msg]

        if option:
            msg = [option] + msg

        msg = [b'', IDP.W_WORKER, command] + msg
        if self.verbose:
            logging.info("I: sending %s to broker", command)
            dump(msg)
        self.worker.send(msg)
Exemple #7
0
    def route(self, socket, clear=None):
        msg = socket.recv()
        sender = msg.pop(0)
        if self.verbose:
            logging.info("I: received message from: {0}".format(sender))
            dump(msg)

        empty = msg.pop(0)
        assert empty == b''
        header = msg.pop(0)

        if (IDP.C_CLIENT == header):
            self.process_client(sender, msg, clear)
        elif (IDP.W_WORKER == header):
            self.process_worker(sender, msg, clear)
        else:
            logging.error("E: invalid message:")
            dump(msg)
Exemple #8
0
    def route(self, socket, clear=None):
        msg = socket.recv(copy=False)
        sender = msg.pop(0).buffer
        if self.nolegacy:
            sender = sender.toreadonly()
        else:
            sender = sender.tobytes()

        if self.verbose:
            logging.info("I: received message from: {0}".format(sender))
            dump(msg)

        empty = msg.pop(0)
        assert empty.buffer == b''
        header = msg.pop(0)

        if (IDP.C_CLIENT == header.buffer):
            self.process_client(sender, msg, clear)
        elif (IDP.W_WORKER == header.buffer):
            self.process_worker(sender, msg, clear)
        else:
            logging.error("E: invalid message:")
            dump(msg)
Exemple #9
0
    def process_worker(self, sender, msg, clear):
        """Process message sent to us by a worker."""
        assert len(msg) >= 1  # At least, command

        command = msg.pop(0)

        worker_ready = sender in self.workers

        worker = self.require_worker(sender, clear)

        if (IDP.W_REPLY == command):
            if (worker_ready):
                # Remove & save client return envelope and insert the
                # protocol header and service name, then rewrap envelope.
                client = msg.pop(0)
                empty = msg.pop(0)  # ?
                msg = [client, b'', IDP.C_CLIENT, worker.service.name] + msg
                self.socketclear.send(msg)
                self.worker_waiting(worker)
            else:
                logging.warning(
                    'IDP.W_REPLY expected, got: {0} from {1}'.format(
                        command, worker.identity))
                self.delete_worker(worker, True)

        elif (IDP.W_REPLY_CURVE == command):
            if (worker_ready):
                # Remove & save client return envelope and insert the
                # protocol header and service name, then rewrap envelope.
                client = msg.pop(0)
                empty = msg.pop(0)  # ?
                msg = [client, b'', IDP.C_CLIENT, worker.service.name] + msg
                self.socketcurve.send(msg)
                self.worker_waiting(worker)
            else:
                logging.warning(
                    'IDP.W_REPLY expected, got: {0} from {1}'.format(
                        command, worker.identity))
                self.delete_worker(worker, True)

        elif (IDP.W_READY == command):
            assert len(msg) >= 1  # At least, a service name
            service = msg.pop(0)
            # Not first command in session or Reserved service name
            if (worker_ready
                    or service.startswith(self.INTERNAL_SERVICE_PREFIX)):
                logging.warning(
                    'Not first command in session or Reserved service name: {0}'
                    .format(worker.identity))
                self.delete_worker(worker, True)
            else:
                # Attach worker to service and mark as idle
                logging.warning('Attaching: {0}'.format(worker.identity))
                worker.service = self.require_service(service)
                self.worker_waiting(worker)

        elif (IDP.W_HEARTBEAT == command):
            if (worker_ready):
                worker.expiry = time.time() + 1e-3 * self.HEARTBEAT_EXPIRY
            else:
                logging.warning(
                    'Received Heartbeat from unintialized Worker: {0}'.format(
                        worker.identity))
                self.delete_worker(worker, True)

        elif (IDP.W_DISCONNECT == command):
            logging.warning('Received disconnect: {0}'.format(worker.identity))
            self.delete_worker(worker, False)
        else:
            logging.error("E: invalid message:")
            dump(msg)
Exemple #10
0
    def recv(self, reply=None):
        """Send reply, if any, to broker and wait for next request."""
        # Format and send the reply if we were provided one
        assert reply is not None or not self.expect_reply

        if reply is not None:
            if (self.reply_to_clear is not None):
                reply = [self.reply_to_clear, b''] + reply
                self.send_to_broker(IDP.W_REPLY, msg=reply)
            elif (self.reply_to_curve is not None):
                reply = [self.reply_to_curve, b''] + reply
                self.send_to_broker(IDP.W_REPLY_CURVE, msg=reply)
            else:
                logging.error('Missing Reply!')

        self.expect_reply = True

        while True:
            # Poll socket for a reply, with timeout
            try:
                items = self.poller.poll(self.timeout)
            except KeyboardInterrupt:
                break  # Interrupted

            if items:
                msg = self.worker.recv()
                if self.verbose:
                    logging.info("I: received message from broker: ")
                    dump(msg)

                self.liveness = self.HEARTBEAT_LIVENESS
                # Don't try to handle errors, just assert noisily
                assert len(msg) >= 3

                empty = msg.pop(0)
                assert empty == b''

                header = msg.pop(0)
                assert header == IDP.W_WORKER

                command = msg.pop(0)
                if command == IDP.W_REQUEST:
                    # We should pop and save as many addresses as there are
                    # up to a null part, but for now, just save one...
                    self.reply_to_clear = msg.pop(0)
                    self.reply_to_curve = None
                    # pop empty
                    empty = msg.pop(0)
                    assert empty == b''

                    self.last_message = time.time()

                    return msg  # We have a request to process
                elif command == IDP.W_REQUEST_CURVE:
                    # We should pop and save as many addresses as there are
                    # up to a null part, but for now, just save one...
                    self.reply_to_clear = None
                    self.reply_to_curve = msg.pop(0)
                    # pop empty
                    empty = msg.pop(0)
                    assert empty == b''

                    self.last_message = time.time()

                    return msg  # We have a request to process
                elif command == IDP.W_HEARTBEAT:
                    logging.debug('Received W_HEARTBEAT: {0}'.format(
                        self.service))
                    # Do nothing for heartbeats
                    pass
                elif command == IDP.W_DISCONNECT:
                    logging.warning('Received W_DISCONNECT!')
                    self.reconnect_to_broker()
                else:
                    logging.error("E: invalid input message: ")
                    dump(msg)

            else:
                self.liveness -= 1
                if self.liveness == 0:
                    logging.warn("Disconnected from broker - retrying...")
                    try:
                        if self.worker:
                            self.poller.unregister(self.worker.socket)
                            self.worker.close()
                            self.worker = None
                        time.sleep(1e-3 * self.reconnect)
                    except KeyboardInterrupt:
                        break
                    self.reconnect_to_broker()

            if self.idle_timeout:
                now = time.time()
                if now - self.last_message >= self.idle_timeout:
                    self.alive = False
                    logging.warning('Worker has been idle for too much time')
                    break

            # Send HEARTBEAT if it's time
            if time.time() > self.heartbeat_at:
                self.send_to_broker(IDP.W_HEARTBEAT)
                self.heartbeat_at = time.time() + 1e-3 * self.heartbeat

        logging.warn("W: interrupt received, killing worker...")
        return None