Esempio n. 1
0
    def handle_event(self):
        if not self.has_events:
            return
        event = PyreEvent(self._pyre_node)
        uuid = event.peer_uuid
        if event.type == "SHOUT" or event.type == "WHISPER":
            try:
                payload = event.msg.pop(0).decode()
                msg = serial.loads(payload)
                msg["subject"]
                msg["sensor_uuid"]
                msg["host_uuid"] = event.peer_uuid.hex
                msg["host_name"] = event.peer_name
            except serial.decoder.JSONDecodeError:
                logger.warning('Malformatted message: "{}"'.format(payload))
            except (ValueError, KeyError):
                logger.warning("Malformatted message: {}".format(msg))
            except Exception:
                logger.debug(tb.format_exc())
            else:
                if msg["subject"] == "attach":
                    if self.sensors.get(msg["sensor_uuid"]):
                        # Sensor already attached. Drop event
                        return
                    sensor_type = SensorType.supported_sensor_type_from_str(
                        msg["sensor_type"])
                    if sensor_type is None:
                        logger.debug("Unsupported sensor type: {}".format(
                            msg["sensor_type"]))
                        return
                elif msg["subject"] == "detach":
                    sensor_entry = self.sensors.get(msg["sensor_uuid"])
                    # Check if sensor has been detached already
                    if not sensor_entry:
                        return
                    msg.update(sensor_entry)
                else:
                    logger.debug("Unknown host message: {}".format(msg))
                    return
                self._execute_callbacks(msg)
        elif event.type == "JOIN":
            # possible values for `group_version`
            # - [<unrelated group>]
            # - [<unrelated group>, <unrelated version>]
            # - ['pupil-mobile']
            # - ['pupil-mobile', <version>]
            group_version = event.group.split("-v")
            group = group_version[0]
            version = group_version[1] if len(group_version) > 1 else "0"

        elif event.type == "EXIT":
            gone_peer = event.peer_uuid.hex
            for host_uuid, sensors in list(self._sensors_by_host.items()):
                if host_uuid != gone_peer:
                    continue
                for sensor_uuid, sensor in list(sensors.items()):
                    self._execute_callbacks({
                        "subject":
                        "detach",
                        "sensor_uuid":
                        sensor_uuid,
                        "sensor_name":
                        sensor["sensor_name"],
                        "host_uuid":
                        host_uuid,
                        "host_name":
                        sensor["host_name"],
                    })
        else:
            logger.debug("Dropping {}".format(event))
Esempio n. 2
0
    def _thread_loop(self,context,pipe):
        # Pyre helper functions
        def setup_group_member():
            group_member = Pyre(self.name)
            # set headers
            for header in self.default_headers:
                group_member.set_header(*header)
            # join active group
            group_member.join(self.active_group)

            # start group_member
            group_member.start()
            return group_member

        def shutdown_group_member(node):
            node.leave(self.active_group)
            node.stop()

        # setup sockets
        local_in  = Msg_Receiver(context, self.g_pool.ipc_sub_url, topics=('remote_notify.',))
        local_out = Msg_Dispatcher(context, self.g_pool.ipc_push_url)
        group_member = setup_group_member()

        # register sockets for polling
        poller = zmq.Poller()
        poller.register(pipe,zmq.POLLIN)
        poller.register(local_in.socket,zmq.POLLIN)
        poller.register(group_member.socket(),zmq.POLLIN)

        logger.info('Pupil Groups started.')

        # Poll loop
        while True:
            # Wait for next readable item
            readable = dict(poller.poll())

            # shout or whisper marked notifications
            if local_in.socket in readable:
                topic, notification = local_in.recv()
                remote_key = 'remote_notify'
                if notification[remote_key] == 'all':
                    del notification[remote_key]
                    serialized = serializer.dumps(notification)
                    group_member.shout(self.active_group,serialized)
                else:
                    peer_uuid_bytes = notification[remote_key]
                    del notification[remote_key]
                    serialized = serializer.dumps(notification)
                    peer_uuid = uuid.UUID(bytes=peer_uuid_bytes)
                    group_member.whisper(peer_uuid,serialized)

            if group_member.socket() in readable:
                event = PyreEvent(group_member)
                if event.msg:
                    for msg in event.msg:
                        try:
                            # try to unpack data
                            notification = serializer.loads(msg)
                            # test if dictionary and if `subject` key is present
                            notification['subject']
                            # add peer information
                            notification['groups.peer'] = {
                                'uuid_bytes': event.peer_uuid_bytes,
                                'name': event.peer_name,
                                'arrival_timestamp': self.g_pool.get_timestamp(),
                                'type': event.type
                            }
                            local_out.notify(notification)
                        except Exception as e:
                            logger.info('Dropped garbage data by peer %s (%s)'%(event.peer_name, event.peer_uuid))
                elif event.type == 'JOIN' and event.group == self.active_group:
                    local_out.notify({
                        'subject': 'groups.member_joined',
                        'name': event.peer_name,
                        'uuid_bytes': event.peer_uuid_bytes
                    })
                elif (event.type == 'LEAVE' and \
                      event.group == self.active_group) or \
                      event.type == 'EXIT':
                    local_out.notify({
                        'subject': 'groups.member_left',
                        'name': event.peer_name,
                        'uuid_bytes': event.peer_uuid_bytes
                    })

            if pipe in readable:
                command = pipe.recv()
                if command == '$RESTART':
                    # Restart group_member node to change name
                    poller.unregister(group_member.socket())
                    shutdown_group_member(group_member)
                    group_member = setup_group_member()
                    poller.register(group_member.socket(),zmq.POLLIN)
                elif command == '$TERM':
                    break

        del local_in
        del local_out
        shutdown_group_member(group_member)
        self.thread_pipe = None
Esempio n. 3
0
    def _thread_loop(self, context, pipe):
        # Pyre helper functions
        def setup_group_member():
            group_member = Pyre(self.name)
            # set headers
            for header in self.default_headers:
                group_member.set_header(*header)
            # join active group
            group_member.join(self.active_group)

            # start group_member
            group_member.start()
            return group_member

        def shutdown_group_member(node):
            node.leave(self.active_group)
            node.stop()

        # setup sockets
        local_in = Msg_Receiver(context,
                                self.g_pool.ipc_sub_url,
                                topics=("remote_notify.", ))
        local_out = Msg_Dispatcher(context, self.g_pool.ipc_push_url)
        group_member = setup_group_member()

        # register sockets for polling
        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(local_in.socket, zmq.POLLIN)
        poller.register(group_member.socket(), zmq.POLLIN)

        logger.info("Pupil Groups started.")

        # Poll loop
        while True:
            # Wait for next readable item
            readable = dict(poller.poll())

            # shout or whisper marked notifications
            if local_in.socket in readable:
                topic, notification = local_in.recv()
                remote_key = "remote_notify"
                if notification[remote_key] == "all":
                    del notification[remote_key]
                    serialized = serializer.dumps(notification)
                    group_member.shout(self.active_group, serialized)
                else:
                    peer_uuid_bytes = notification[remote_key]
                    del notification[remote_key]
                    serialized = serializer.dumps(notification)
                    peer_uuid = uuid.UUID(bytes=peer_uuid_bytes)
                    group_member.whisper(peer_uuid, serialized)

            if group_member.socket() in readable:
                event = PyreEvent(group_member)
                if event.msg:
                    for msg in event.msg:
                        try:
                            # try to unpack data
                            notification = serializer.loads(msg,
                                                            encoding="utf-8")
                            # test if dictionary and if `subject` key is present
                            notification["subject"]
                            # add peer information
                            notification["groups.peer"] = {
                                "uuid_bytes": event.peer_uuid_bytes,
                                "name": event.peer_name,
                                "arrival_timestamp":
                                self.g_pool.get_timestamp(),
                                "type": event.type,
                            }
                            local_out.notify(notification)
                        except Exception:
                            logger.info(
                                "Dropped garbage data by peer {} ({})".format(
                                    event.peer_name, event.peer_uuid))
                elif event.type == "JOIN" and event.group == self.active_group:
                    local_out.notify({
                        "subject": "groups.member_joined",
                        "name": event.peer_name,
                        "uuid_bytes": event.peer_uuid_bytes,
                    })
                elif (event.type == "LEAVE" and event.group
                      == self.active_group) or event.type == "EXIT":
                    local_out.notify({
                        "subject": "groups.member_left",
                        "name": event.peer_name,
                        "uuid_bytes": event.peer_uuid_bytes,
                    })

            if pipe in readable:
                command = pipe.recv_string()
                if command == "$RESTART":
                    # Restart group_member node to change name
                    poller.unregister(group_member.socket())
                    shutdown_group_member(group_member)
                    group_member = setup_group_member()
                    poller.register(group_member.socket(), zmq.POLLIN)
                elif command == "$TERM":
                    break

        del local_in
        del local_out
        shutdown_group_member(group_member)
        self.thread_pipe = None
Esempio n. 4
0
 def poll_network(self):
     while has_data(self.network.socket()):
         event = PyreEvent(self.network)
         if event.type == 'JOIN' and event.group == 'pupil-mobile':
             self.network.whisper(event.peer_uuid, self.sensor_attach_json())