Example #1
1
    def test_all(self):
        z1 = Zyre(b't1')
        z2 = Zyre(b't2')

        z1.set_header(b'test_header', b'test1')
        z2.set_header(b'test_header', b'test2')

        self.assertEquals(z1.start(), 0)
        self.assertEquals(z2.start(), 0)

        e = ZyreEvent(z1)
        self.assertEquals(e.peer_name(), z2.name())
        self.assertEquals(e.peer_uuid(), z2.uuid())
        self.assertEquals(e.type(), b'ENTER')

        e = ZyreEvent(z2)
        self.assertEquals(e.peer_name(), z1.name())
        self.assertEquals(e.peer_uuid(), z1.uuid())
        self.assertEquals(e.type(), b'ENTER')

        z1.join(b'test group')
        z2.join(b'test group')

        e = ZyreEvent(z1)
        self.assertEquals(e.peer_name(), z2.name())
        self.assertEquals(e.peer_uuid(), z2.uuid())
        self.assertEquals(e.type(), b'JOIN')
        self.assertEquals(e.group(), b'test group')

        e = ZyreEvent(z2)
        self.assertEquals(e.peer_name(), z1.name())
        self.assertEquals(e.peer_uuid(), z1.uuid())
        self.assertEquals(e.type(), b'JOIN')
        self.assertEquals(e.group(), b'test group')

        z1.shouts(b'test group', b"Hello World")

        e = ZyreEvent(z2)
        self.assertEquals(e.peer_name(), z1.name())
        self.assertEquals(e.peer_uuid(), z1.uuid())
        self.assertEquals(e.type(), b'SHOUT')
        self.assertEquals(e.group(), b'test group')
        self.assertEquals(e.msg().popstr(), b"Hello World")
Example #2
0
    def __init__(self, interface, netiface=None):
        self.interface = interface

        # Peers book
        self.book = {}
        self.topics = []

        # Publisher
        self.pub_cache = {}
        self.publisher = Zsock.new_xpub(("tcp://*:*").encode())

        # TimeServer
        self.timereply = Zsock.new_rep(("tcp://*:*").encode())

        # Zyre
        self.zyre = Zyre(None)
        if netiface:
            self.zyre.set_interface(string_at(netiface))
            self.interface.log("ZYRE Node forced netiface: ",
                               string_at(netiface))

        self.zyre.set_name(str(self.interface.hplayer.name()).encode())
        self.zyre.set_header(b"TS-PORT",
                             str(get_port(self.timereply)).encode())
        self.zyre.set_header(b"PUB-PORT",
                             str(get_port(self.publisher)).encode())

        self.zyre.set_interval(PING_PEER)
        self.zyre.set_evasive_timeout(PING_PEER * 3)
        self.zyre.set_silent_timeout(PING_PEER * 5)
        self.zyre.set_expired_timeout(PING_PEER * 10)

        self.zyre.start()
        self.zyre.join(b"broadcast")
        self.zyre.join(b"sync")

        # Add self to book
        self.book[self.zyre.uuid()] = Peer(
            self, {
                'uuid': self.zyre.uuid(),
                'name': self.zyre.name().decode(),
                'ip': '127.0.0.1',
                'ts_port': get_port(self.timereply),
                'pub_port': get_port(self.publisher)
            })
        self.book[self.zyre.uuid()].subscribe(self.topics)

        # Start Poller
        self._actor_fn = zactor_fn(
            self.actor_fn
        )  # ctypes function reference must live as long as the actor.
        if netiface:
            netiface = create_string_buffer(str.encode(netiface))
        self.actor = Zactor(self._actor_fn, netiface)
        self.done = False
Example #3
0
File: test.py Project: Asmod4n/zyre
    def test_all(self):
        z1 = Zyre('t1')
        z2 = Zyre('t2')

        z1.set_header('test_header', 'test1')
        z2.set_header('test_header', 'test2')

        self.assertEquals(z1.start(), 0)
        self.assertEquals(z2.start(), 0)

        e = ZyreEvent(z1)
        self.assertEquals(e.name(), z2.name())
        self.assertEquals(e.sender(), z2.uuid())
        self.assertEquals(e.type(), 'enter')

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'enter')

        z1.join('test group')
        z2.join('test group')

        e = ZyreEvent(z1)
        self.assertEquals(e.name(), z2.name())
        self.assertEquals(e.sender(), z2.uuid())
        self.assertEquals(e.type(), 'join')
        self.assertEquals(e.group(), 'test group')

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'join')
        self.assertEquals(e.group(), 'test group')

        z1.shouts('test group', "Hello World")

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'shout')
        self.assertEquals(e.group(), 'test group')
        self.assertEquals(e.msg().popstr(), "Hello World")
Example #4
0
    def test_all(self):
        z1 = Zyre('t1')
        z2 = Zyre('t2')

        z1.set_header('test_header', 'test1')
        z2.set_header('test_header', 'test2')

        self.assertEquals(z1.start(), 0)
        self.assertEquals(z2.start(), 0)

        e = ZyreEvent(z1)
        self.assertEquals(e.name(), z2.name())
        self.assertEquals(e.sender(), z2.uuid())
        self.assertEquals(e.type(), 'enter')

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'enter')

        z1.join('test group')
        z2.join('test group')

        e = ZyreEvent(z1)
        self.assertEquals(e.name(), z2.name())
        self.assertEquals(e.sender(), z2.uuid())
        self.assertEquals(e.type(), 'join')
        self.assertEquals(e.group(), 'test group')

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'join')
        self.assertEquals(e.group(), 'test group')

        z1.shouts('test group', "Hello World")

        e = ZyreEvent(z2)
        self.assertEquals(e.name(), z1.name())
        self.assertEquals(e.sender(), z1.uuid())
        self.assertEquals(e.type(), 'shout')
        self.assertEquals(e.group(), 'test group')
        self.assertEquals(e.msg().popstr(), "Hello World")
Example #5
0
    def actor_fn(self, pipe, arg):
        internal_pipe = Zsock(pipe, False) # We don't own the pipe, so False.
        arg = string_at(arg)

        global port

        zyre_node = Zyre(None)
        zyre_node.set_header (b"TS-PORT", str(port).encode());
        zyre_node.start()
        zyre_node.join(b"broadcast")
        zyre_node.join(b"sync")
        zyre_pipe = zyre_node.socket()

        poller = Zpoller(zyre_pipe, internal_pipe)

        internal_pipe.signal(0)

        print('ZYRE Node started')
        terminated = False
        while not terminated:
            # time.sleep(1)
            # sock = poller.wait(1000)
            # if not sock:
            #     continue
            #
            #
            # ZYRE receive
            #
            # if sock == zyre_pipe:
                e = ZyreEvent(zyre_node)

                # ANY
                if e.type() != b"EVASIVE":
                    e.print()
                    pass

                # ENTER: add to phonebook for external contact (i.e. TimeSync)
                if e.type() == b"ENTER":
                    self.timebook.newpeer(e.peer_uuid(), e.peer_addr(), e.header(b"TS-PORT"))

                # EXIT
                elif e.type() == b"EXIT":
                    print( "ZYRE Node: peer is gone..")

                # JOIN
                elif e.type() == b"JOIN":

                    # SYNC clocks
                    if e.group() == b"sync":
                        pass
                        self.timebook.sync(e.peer_uuid())

                # LEAVE
                elif e.type() == b"LEAVE":
                    print("ZYRE Node: peer left a group..")

                # SHOUT -> process event
                elif e.type() == b"SHOUT" or e.type() == b"WHISPER":

                    # Parsing message
                    data = json.loads(e.msg().popstr().decode())
                    data['from'] = e.peer_uuid()

                    # add group
                    if e.type() == b"SHOUT": data['group'] = e.group().decode()
                    else: data['group'] = 'whisper'

                    self.eventProc(data)
            #
            #
            # #
            # # INTERNAL commands
            # #
            # elif sock == internal_pipe:
            #     msg = Zmsg.recv(internal_pipe)
            #     if not msg: break
            #
            #     command = msg.popstr()
            #     if command == b"$TERM":
            #         print('ZYRE Node TERM')
            #         break
            #
            #     elif command == b"JOIN":
            #         group = msg.popstr()
            #         zyre_node.join(group)
            #
            #     elif command == b"LEAVE":
            #         group = msg.popstr()
            #         zyre_node.leave(group)
            #
            #     elif command == b"SHOUT":
            #         group = msg.popstr()
            #         data = msg.popstr()
            #         zyre_node.shouts(group, data)
            #
            #         # if own group -> send to self too !
            #         groups = zlist_strlist( zyre_node.own_groups() )
            #         if group.decode() in groups:
            #             data = json.loads(data.decode())
            #             data['from'] = 'self'
            #             data['group'] = group.decode()
            #             self.eventProc(data)


        # zyre_node.stop()  # HANGS !
        internal_pipe.__del__()
        zyre_node.__del__()
        print('ZYRE Node stopped')   # WEIRD: print helps the closing going smoothly..
        self.done = True
Example #6
0
 def run(self):
     self.zyre = Zyre(None)
     if self.logger.level > 0:
         self.zyre.set_verbose()
         # Zsys.set_logsystem(1)
     else:
         # Zsys.set_logsystem(0)
         pass
     self.uuid = self.zyre.uuid()
     self.zyre.set_interface(Config.NIC_NAME.encode('utf-8'))
     if Config.SECURITY:
         certFile = os.path.join(self.riapsHome, "keys",
                                 const.zmqCertificate)
         cert = czmq.Zcert.load(ctypes.c_char_p(certFile.encode('utf-8')))
         self.zyre.set_zcert(cert)
     self.zyre.set_evasive_timeout(const.peerEvasiveTimeout)
     self.zyre.set_expired_timeout(const.peerExpiredTimeout)
     self.zyre.set_header(b'riaps@' + self.hostAddress.encode('utf-8'),
                          b'hello')
     self.command = self.context.socket(zmq.PAIR)
     self.command.connect(const.fmMonitorEndpoint)
     self.zyre.start()
     self.zyre.join(b'riaps')
     self.zyreSocket = self.zyre.socket()
     self.poller = czmq.Zpoller(zyre.c_void_p(self.command.underlying),
                                self.zyreSocket, 0)
     while True:
         reader = self.poller.wait(-1)  # Wait forever
         if self.poller.terminated():
             self.logger.warning("FMMon.run - poller terminated")
             break
         if type(
                 reader
         ) == zyre.c_void_p and reader.value == self.command.underlying:
             msg = self.command.recv_pyobj()
             self.logger.info('FMMon.run - command: %s' % str(msg))
             cmd = msg[0]
             if cmd == 'stop':
                 break
             elif cmd == 'setupApp':
                 appName = msg[1]
                 group = self.groupName(appName)
                 self.zyre.join(group)
                 if appName not in self.groups:
                     self.groups[appName] = set()
                     self.actors[appName] = set()
             elif cmd == 'cleanupApp':
                 appName = msg[1]
                 group = self.groupName(appName)
                 self.zyre.leave(group)
                 if appName in self.groups:
                     del self.groups[appName]
             elif cmd == 'addActor':
                 appName, actorName = msg[1:]
                 assert appName in self.groups
                 self.actors[appName].add(actorName)
                 group = self.groupName(appName)
                 arg = "+ %s.%s" % (appName, actorName)
                 self.logger.info("FMMon.addActor.shout: %s" % arg)
                 self.zyre.shouts(group, arg.encode('utf-8'))
                 for peer in self.groups[appName]:
                     self.logger.info(
                         "FMMon.addactor tell %s.%s has peer at %s" %
                         (appName, actorName, str(peer)))
                     info = ('peer+', appName, actorName, peer)
                     self.command.send_pyobj(info)
             elif cmd == 'delActor':
                 appName, actorName = msg[1:]
                 assert appName in self.groups and actorName in self.actors[
                     appName]
                 self.actors[appName].remove(actorName)
                 group = self.groupName(appName)
                 arg = "- %s.%s" % (appName, actorName)
                 self.logger.info("FMMon.delActor.shout: %s" % arg)
                 self.zyre.shouts(group, arg.encode('utf-8'))
             elif cmd == 'dieActor':
                 appName, actorName = msg[1:]
                 assert appName in self.groups and actorName in self.actors[
                     appName]
                 self.actors[appName].remove(actorName)
                 group = self.groupName(appName)
                 arg = "? %s.%s" % (appName, actorName)
                 self.logger.info("FMMon.dieActor.shout: %s" % arg)
                 self.zyre.shouts(group, arg.encode('utf-8'))
             else:
                 pass  # Should be error
         elif reader == self.zyreSocket:
             event = ZyreEvent(self.zyre)
             eType = event.type()
             _pName = event.peer_name()
             pUUID = event.peer_uuid()
             pAddr = event.peer_addr()
             group = event.group()
             _headers = event.headers()
             msg = event.get_msg()
             #                 if eType != b'EVASIVE':
             #                     print("# %s %s %s %s %s %s %s"
             #                           % (str(eType),str(_pName),str(pUUID),str(pAddr),
             #                              str(group),str(_headers),str(msg)))
             if eType == b'ENTER':
                 self.logger.info("FMMon.ENTER %s from %s" %
                                  (str(pUUID), str(pAddr)))
                 self.peers[pUUID] = pAddr
             elif eType == b'JOIN':
                 groupName = group.decode()
                 self.logger.info("FMMon.JOIN %s from %s" %
                                  (str(groupName), str(pUUID)))
                 if groupName == 'riaps':
                     continue  # Joined riaps group - should be validated
                 else:
                     _, appName = groupName.split('.')
                     if appName not in self.groups:
                         self.groups[appName] = {pUUID}
                         if appName not in self.actors:
                             self.actors[appName] = set()
                     else:
                         self.groups[appName].add(pUUID)
                     if appName in self.actors:
                         peer = pUUID
                         for actorName in self.actors[appName]:
                             arg = "+ %s.%s" % (appName, actorName)
                             self.logger.info(
                                 "FMMon.JOIN.whisper: %s to %s " %
                                 (arg, str(peer)))
                             self.zyre.whispers(peer, arg.encode('utf-8'))
                             self.logger.info(
                                 "FMMon.JOIN tell %s.%s has peer at %s" %
                                 (appName, actorName, str(peer)))
                             info = ('peer+', appName, actorName, peer)
                             self.command.send_pyobj(info)
             elif eType == b'LEAVE':
                 groupName = group.decode()
                 self.logger.info("FMMon.LEAVE %s from %s" %
                                  (str(pUUID), str(group)))
                 if groupName == 'riaps':
                     continue  # Left riaps group - should be validated
                 else:
                     _, appName = groupName.split('.')
                     if appName in self.groups:
                         self.groups[appName].remove(pUUID)
                     if appName in self.actors:
                         for actorName in self.actors[appName]:
                             peer = pUUID
                             self.logger.info(
                                 "FMMon.LEAVE tell %s.%s lost peer at %s" %
                                 (appName, actorName, str(peer)))
                             info = ('peer-', appName, actorName, peer)
                             self.command.send_pyobj(info)
             elif eType == b'EXIT':
                 self.logger.info("FMMon.EXIT %s " % (str(pUUID)))
                 for appName, group in self.groups.items():
                     if pUUID in group:
                         if appName in self.actors:
                             for actorName in self.actors[appName]:
                                 peer = pUUID
                                 self.logger.info(
                                     "FMMon.EXIT tell %s.%s lost peer at %s"
                                     % (appName, actorName, str(peer)))
                                 info = ('peer-', appName, actorName, peer)
                                 self.command.send_pyobj(info)
                 del self.peers[pUUID]
             elif eType == b'SHOUT' or eType == b'WHISPER':
                 arg = msg.popstr().decode()
                 self.logger.info("FMMon.SHOUT %s = %s " %
                                  (str(pUUID), arg))
                 peer = pUUID
                 cmd, pair = arg.split(' ')
                 appName, actorName = pair.split('.')
                 head, cast = '?', '?'
                 if cmd == '+':
                     head, cast = 'peer+', ' has peer '
                 elif cmd == '-':
                     head, cast = 'peer-', ' lost peer '
                 elif cmd == '?':
                     head, cast = 'peer-', ' lost peer '
                 if appName not in self.groups:
                     self.groups[appName] = {pUUID}
                 if appName in self.actors:
                     for actorName in self.actors[appName]:
                         self.logger.info("FMMon.%s: tell %s.%s %s %s" %
                                          (eType.decode(), appName,
                                           actorName, cast, str(peer)))
                         info = (head, appName, actorName, peer)
                         self.command.send_pyobj(info)
             else:
                 pass
     self.command.close()
     for appName in self.actors:
         if appName in self.groups:
             group = self.groupName(appName)
             arg = "- %s.%s" % (appName, actorName)
             self.logger.info("FMMon.terminate.shout: %s" % arg)
             self.zyre.shouts(group, arg.encode('utf-8'))
     self.zyre.leave(b'riaps')
     self.zyre.stop()
Example #7
0
class ZyreNode():
    def __init__(self, interface, netiface=None):
        self.interface = interface

        # Peers book
        self.book = {}
        self.topics = []

        # Publisher
        self.pub_cache = {}
        self.publisher = Zsock.new_xpub(("tcp://*:*").encode())

        # TimeServer
        self.timereply = Zsock.new_rep(("tcp://*:*").encode())

        # Zyre
        self.zyre = Zyre(None)
        if netiface:
            self.zyre.set_interface(string_at(netiface))
            self.interface.log("ZYRE Node forced netiface: ",
                               string_at(netiface))

        self.zyre.set_name(str(self.interface.hplayer.name()).encode())
        self.zyre.set_header(b"TS-PORT",
                             str(get_port(self.timereply)).encode())
        self.zyre.set_header(b"PUB-PORT",
                             str(get_port(self.publisher)).encode())

        self.zyre.set_interval(PING_PEER)
        self.zyre.set_evasive_timeout(PING_PEER * 3)
        self.zyre.set_silent_timeout(PING_PEER * 5)
        self.zyre.set_expired_timeout(PING_PEER * 10)

        self.zyre.start()
        self.zyre.join(b"broadcast")
        self.zyre.join(b"sync")

        # Add self to book
        self.book[self.zyre.uuid()] = Peer(
            self, {
                'uuid': self.zyre.uuid(),
                'name': self.zyre.name().decode(),
                'ip': '127.0.0.1',
                'ts_port': get_port(self.timereply),
                'pub_port': get_port(self.publisher)
            })
        self.book[self.zyre.uuid()].subscribe(self.topics)

        # Start Poller
        self._actor_fn = zactor_fn(
            self.actor_fn
        )  # ctypes function reference must live as long as the actor.
        if netiface:
            netiface = create_string_buffer(str.encode(netiface))
        self.actor = Zactor(self._actor_fn, netiface)
        self.done = False

    # ZYRE Zactor
    def actor_fn(self, pipe, netiface):

        # Internal
        internal_pipe = Zsock(pipe, False)  # We don't own the pipe, so False.

        # Poller
        poller = Zpoller(self.zyre.socket(), internal_pipe, self.publisher,
                         self.timereply, None)

        # RUN
        self.interface.log('Node started')
        internal_pipe.signal(0)

        while True:
            sock = poller.wait(500)
            if not sock:
                continue

            #
            # ZYRE receive
            #
            if sock == self.zyre.socket():
                e = ZyreEvent(self.zyre)
                uuid = e.peer_uuid()

                # self.interface.log("ZYREmsg", uuid, e.peer_name().decode(), e.type().decode())

                # ENTER: add to book for external contact (i.e. TimeSync)
                if e.type() == b"ENTER":
                    newpeer = Peer(self, e)
                    existing = None

                    if uuid in self.book:
                        # print ('UUID already exist: replacing')  ## PROBLEM : Same name may appear with different uuid (not a real problem, only if crash and restart with new uuid in a short time..)
                        self.book[uuid].stop()
                        existing = uuid

                    for p in self.book.values():
                        if p.name == newpeer.name:
                            # print ('Name already exist: replacing')
                            p.stop()
                            existing = p.uuid

                    if existing:
                        del self.book[existing]

                    self.book[uuid] = newpeer
                    self.book[uuid].subscribe(self.topics)

                # EVASIVE
                elif e.type() == b"EVASIVE":
                    # if uuid in self.book:
                    #     self.book[uuid].linker(2)
                    pass

                # SILENT
                elif e.type() == b"SILENT":
                    if uuid in self.book:
                        self.book[uuid].linker(1)

                # EXIT
                elif e.type() == b"EXIT":
                    if uuid in self.book:
                        self.book[uuid].linker(0)
                        self.book[uuid].stop()
                        del self.book[uuid]

                # JOIN
                elif e.type() == b"JOIN":
                    # self.interface.log("peer join a group..", e.peer_name(), e.group().decode())

                    # SYNC clocks
                    if e.group() == b"sync":
                        if self.peer(uuid):
                            self.peer(uuid).sync()

                # LEAVE
                elif e.type() == b"LEAVE":
                    # self.interface.log("peer left a group..")
                    pass

                # SHOUT -> process event
                elif e.type() == b"SHOUT" or e.type() == b"WHISPER":

                    # Parsing message
                    data = json.loads(e.msg().popstr().decode())
                    data['from'] = uuid

                    # add group
                    if e.type() == b"SHOUT": data['group'] = e.group().decode()
                    else: data['group'] = 'whisper'

                    self.preProcessor1(data)

            #
            # PUBLISHER event
            #
            elif sock == self.publisher:
                msg = Zmsg.recv(self.publisher)
                if not msg: break
                topic = msg.popstr()

                # Somebody subscribed: push Last Value Cache !
                if len(topic) > 0 and topic[0] == 1:
                    topic = topic[1:]
                    if topic in self.pub_cache:
                        # self.interface.log('XPUB lvc send for', topic.decode())
                        msg = Zmsg.dup(self.pub_cache[topic])
                        Zmsg.send(msg, self.publisher)

                    # else:
                    #     self.interface.log('XPUB lvc empty for', topic.decode())

            #
            # TIMESERVER event
            #
            elif sock == self.timereply:
                msgin = Zmsg.recv(self.timereply)
                msg = Zmsg()
                msg.addstr(str(int(time.time() * PRECISION)).encode())
                Zmsg.send(msg, self.timereply)

            #
            # INTERNAL commands
            #
            elif sock == internal_pipe:
                msg = Zmsg.recv(internal_pipe)
                if not msg or msg.popstr() == b"$TERM":
                    # print('ZYRE Node TERM')
                    break

        internal_pipe.__del__()
        self.interface.log(' - node stopped'
                           )  # WEIRD: print helps the closing going smoothly..
        self.done = True

    def stop(self):
        for peer in self.book.values():
            peer.stop()

        self.actor.sock().send(b"ss", b"$TERM")
        retry = 0
        while not self.done and retry < 10:
            sleep(0.1)
            retry += 1

        # self.zyre.stop()        # HANGS !
        self.zyre.__del__()
        self.publisher.__del__()
        self.timereply.__del__()

    def peer(self, uuid):
        if uuid in self.book and self.book[uuid].active:
            return self.book[uuid]

    def peerByName(self, name):
        for peer in self.book.values():
            if peer.active and peer.name == name:
                return peer

    #
    # PUB/SUB
    #

    def subscribe(self, topics):
        if not isinstance(topics, list): topics = [topics]
        self.topics = list(set(self.topics)
                           | set(topics))  # merge lists and remove duplicates
        for peer in self.book.values():
            peer.subscribe(self.topics)

    def publish(self, topic, args=None):
        topic = topic.encode()

        msg = Zmsg()
        msg.addstr(topic)
        msg.addstr(self.zyre.uuid())
        msg.addstr(json.dumps(args).encode())

        self.pub_cache[topic] = Zmsg.dup(msg)
        Zmsg.send(msg, self.publisher)

    #
    # ZYRE send messages
    #

    def makeMsg(self, event, args=None, delay_ms=0, at=0):
        data = {}
        data['event'] = event
        data['args'] = []
        if args:
            if not isinstance(args, list):
                # self.interface.log('NOT al LIST', args)
                args = [args]
            data['args'] = args

        # at time
        if at > 0:
            data['at'] = at

        # add delay
        if delay_ms > 0:
            if not 'at' in data:
                data['at'] = 0
            data['at'] += int(time.time() * PRECISION +
                              delay_ms * PRECISION / 1000)

        return json.dumps(data).encode()

    def whisper(self, uuid, event, args=None, delay_ms=0, at=0):
        data = self.makeMsg(event, args, delay_ms, at)
        if uuid == self.zyre.uuid():
            data = json.loads(data.decode())
            data['from'] = 'self'
            data['group'] = 'whisper'
            self.preProcessor1(data)
        else:
            self.zyre.whispers(uuid, data)

    def shout(self, group, event, args=None, delay_ms=0, at=0):
        data = self.makeMsg(event, args, delay_ms, at)
        self.zyre.shouts(group.encode(), data)

        # if own group -> send to self too !
        groups = zlist_strlist(self.zyre.own_groups())
        if group in groups:
            data = json.loads(data.decode())
            data['from'] = 'self'
            data['group'] = group
            self.preProcessor1(data)

    def broadcast(self, event, args=None, delay_ms=0, at=0):
        self.shout('broadcast', event, args, delay_ms, at)

    def join(self, group):
        self.zyre.join(group.encode())

    def leave(self, group):
        self.zyre.leave(group.encode())

    #
    # ZYRE messages processor
    #

    def preProcessor1(self, data):
        # if a programmed time is provided, correct it with peer CS
        # Set timer
        if 'at' in data:
            if self.peer(data['from']):
                data['at'] -= self.peer(data['from']).clockshift()
            delay = (data['at']) / PRECISION - time.time()

            if delay <= -10000:
                self.interface.log('WARNING event already passed by', delay,
                                   's, its too late !! discarding... ')
            elif delay <= 0:
                self.interface.log('WARNING event already passed by', delay,
                                   's, playing late... ')
                self.preProcessor2(data)
            elif delay > 3000:
                self.interface.log('WARNING event in', delay,
                                   's, thats weird, playing now... ')
                self.preProcessor2(data)
            else:
                self.interface.log('programmed event in', delay, 's')
                t = Timer(delay, self.preProcessor2, args=[data])
                t.start()
                self.interface.emit('planned', data)

        else:
            self.preProcessor2(data)

    def preProcessor2(self, data):
        self.interface.emit('event', *[data])
        self.interface.emit(data['event'], *data['args'])
Example #8
0
 def run(self):
     self.zyre = Zyre(None)
     if self.logger.level == logging.DEBUG:
         self.zyre.set_verbose()
     else:
         pass
     self.uuid = self.zyre.uuid()
     self.zyre.set_interface(Config.NIC_NAME.encode('utf-8'))
     if Config.SECURITY:
         certFile = os.path.join(self.riapsHome, "keys",
                                 const.zmqCertificate)
         cert = czmq.Zcert.load(ctypes.c_char_p(certFile.encode('utf-8')))
         self.zyre.set_zcert(cert)
     self.zyre.set_evasive_timeout(const.peerEvasiveTimeout)
     self.zyre.set_expired_timeout(const.peerExpiredTimeout)
     self.zyre.set_header(self.peerHeaderKey(self.hostAddress),
                          self.PEERMARK)
     self.command = self.context.socket(zmq.PAIR)
     self.command.connect(const.discoDhtPeerMonEndpoint)
     self.zyre.start()
     self.zyre.join(self.PEERGROUP)
     self.zyreSocket = self.zyre.socket()
     self.poller = czmq.Zpoller(zyre.c_void_p(self.command.underlying),
                                self.zyreSocket, 0)
     while True:
         reader = self.poller.wait(-1)  # Wait forever
         if self.poller.terminated():
             self.logger.info("DhtPeerMon.run - poller terminated")
             break
         if type(
                 reader
         ) == zyre.c_void_p and reader.value == self.command.underlying:
             msg = self.command.recv_pyobj()
             self.logger.info('DhtPeerMon.run - command: %s' % str(msg))
             cmd = msg[0]
             if cmd == 'stop':
                 break
             else:
                 pass  # Should be error
         elif reader == self.zyreSocket:
             event = ZyreEvent(self.zyre)
             eType = event.type()
             _pName = event.peer_name()
             pUUID = event.peer_uuid()
             pAddr = event.peer_addr()
             group = event.group()
             _headers = event.headers()
             msg = event.get_msg()
             #                 if eType != b'EVASIVE':
             #                     print("# %s %s %s %s %s %s %s"
             #                           % (str(eType),str(_pName),str(pUUID),str(pAddr),
             #                              str(group),str(_headers),str(msg)))
             if eType == b'ENTER':
                 self.logger.info("DhtPeerMon.ENTER %s from %s" %
                                  (str(pUUID), str(pAddr)))
                 try:
                     pAddrStr = pAddr.decode('UTF-8')
                     (peerIp,
                      _peerPort) = parse.parse("tcp://{}:{}", pAddrStr)
                     peerHeaderKey = self.peerHeaderKey(peerIp)
                     _value = _headers.lookup(peerHeaderKey)
                     if (_value):
                         try:
                             value = ctypes.cast(_value,
                                                 ctypes.c_char_p).value
                             assert value == self.PEERMARK
                             self.peers[pUUID] = peerIp
                             self.logger.info("DhtPeerMon.ENTER valid peer")
                         except:
                             self.logger.info(
                                 "DhtPeerMon.ENTER header value mismatch")
                     else:
                         self.logger.info(
                             "DhtPeerMon.ENTER header key mismatch")
                 except:
                     self.logger.info(
                         "DhtPeerMon.ENTER peer addr parsing error")
             elif pUUID not in self.peers:  # Skip the rest if this is not a peer
                 continue
             elif eType == b'JOIN':
                 groupName = group.decode()
                 peer = pUUID
                 self.logger.info("DhtPeerMon.JOIN %s from %s" %
                                  (str(groupName), str(pUUID)))
                 if groupName != self.PEERGROUP:
                     self.logger.info("DhtPeerMon.JOIN another group")
                     pass
                 else:
                     self.peerGroup.add(peer)
                     self.zyre.whispers(
                         peer,
                         ("%s://%d" %
                          (self.PEERGROUP, self.dhtPort)).encode('utf-8'))
             elif eType == b'SHOUT' or eType == b'WHISPER':
                 arg = msg.popstr().decode()
                 self.logger.info("DhtPeerMon.SHOUT %s = %s " %
                                  (str(pUUID), arg))
                 try:
                     pAddrStr = pAddr.decode('UTF-8')
                     (peerIp,
                      _peerPort) = parse.parse("tcp://{}:{}", pAddrStr)
                     assert peerIp == self.peers[pUUID]
                     peerDhtPort = parse.parse("%s://{}" % self.PEERGROUP,
                                               arg)
                     if peerDhtPort:
                         self.logger.info("DhtPeerMon.bootstrap %s:%s" %
                                          (peerIp, peerDhtPort))
                         self.dht.bootstrap(str(peerIp), str(peerDhtPort))
                 except:
                     self.logger.error("DhtPeerMon.bootstrap failed")
             elif eType == b'LEAVE':
                 groupName = group.decode()
                 self.logger.info("DhtPeerMon.LEAVE %s from %s" %
                                  (str(pUUID), str(group)))
                 if groupName != self.PEERGROUP:
                     self.logger.info("DhtPeerMon.LEAVE another group")
                     pass
                 else:
                     self.peerGroup.discard(pUUID)
             elif eType == b'EXIT':
                 self.logger.info("DhtPeerMon.EXIT %s " % (str(pUUID)))
                 if pUUID in self.peers:
                     del self.peers[pUUID]
                     self.peerGroup.discard(pUUID)
             else:
                 pass
     self.command.close()
     self.zyre.leave(self.PEERGROUP)
     self.zyre.stop()
Example #9
0
class FMMonitor(threading.Thread):
    def __init__(self, context, hostAddress, riapsHome):
        threading.Thread.__init__(self, daemon=True)
        self.logger = logging.getLogger(__name__)
        self.context = context
        self.hostAddress = hostAddress
        self.riapsHome = riapsHome
        self.control = None
        self.peers = {}  # uuid : address - all peers
        self.groups = {}  # groupName : { peers* } - peers in group
        self.actors = {}  # appName : { actors* }  - actors in apps
        self.uuid = None
        self.logger.info('FMMon:__inited__')

    def setup(self):
        self.logger.info('FMMon:setup()')
        self.control = self.context.socket(zmq.PAIR)
        self.control.bind(const.fmMonitorEndpoint)
        return self.control

    def getUUID(self):
        while self.uuid == None:
            time.sleep(0.1)
        return self.uuid

    def setupApp(self, appName):
        msg = ('setupApp', appName)
        self.control.send_pyobj(msg)

    def cleanupApp(self, appName):
        msg = ('cleanupApp', appName)
        self.control.send_pyobj(msg)

    def addActor(self, appName, actorName):
        msg = ('addActor', appName, actorName)
        self.control.send_pyobj(msg)

    def delActor(self, appName, actorName):
        msg = ('delActor', appName, actorName)
        self.control.send_pyobj(msg)

    def dieActor(self, appName, actorName):
        msg = ('dieActor', appName, actorName)
        self.control.send_pyobj(msg)

    def terminate(self):
        if self.control != None:
            self.control.send_pyobj(('stop', ))
        else:
            self.setup()
            time.sleep(0.1)
            self.control.send_pyobj(('stop', ))

    def peerHeaderKey(self, ipAddress):
        return b'riaps@' + ipAddress.encode('utf-8')

    PEERMARK = b'CAFE'

    def groupName(self, appName):
        return b'riaps.' + appName.encode('utf-8')

    def run(self):
        self.zyre = Zyre(None)
        if self.logger.level > 0:
            self.zyre.set_verbose()
            # Zsys.set_logsystem(1)
        else:
            # Zsys.set_logsystem(0)
            pass
        self.uuid = self.zyre.uuid()
        self.zyre.set_interface(Config.NIC_NAME.encode('utf-8'))
        if Config.SECURITY:
            certFile = os.path.join(self.riapsHome, "keys",
                                    const.zmqCertificate)
            cert = czmq.Zcert.load(ctypes.c_char_p(certFile.encode('utf-8')))
            self.zyre.set_zcert(cert)
        self.zyre.set_evasive_timeout(const.peerEvasiveTimeout)
        self.zyre.set_expired_timeout(const.peerExpiredTimeout)
        self.zyre.set_header(self.peerHeaderKey(self.hostAddress),
                             self.PEERMARK)
        self.command = self.context.socket(zmq.PAIR)
        self.command.connect(const.fmMonitorEndpoint)
        self.zyre.start()
        self.zyre.join(b'riaps')
        self.zyreSocket = self.zyre.socket()
        self.poller = czmq.Zpoller(zyre.c_void_p(self.command.underlying),
                                   self.zyreSocket, 0)
        while True:
            reader = self.poller.wait(-1)  # Wait forever
            if self.poller.terminated():
                self.logger.warning("FMMon.run - poller terminated")
                break
            if type(
                    reader
            ) == zyre.c_void_p and reader.value == self.command.underlying:
                msg = self.command.recv_pyobj()
                self.logger.info('FMMon.run - command: %s' % str(msg))
                cmd = msg[0]
                if cmd == 'stop':
                    break
                elif cmd == 'setupApp':
                    appName = msg[1]
                    group = self.groupName(appName)
                    self.zyre.join(group)
                    if appName not in self.groups:
                        self.groups[appName] = set()
                        self.actors[appName] = set()
                elif cmd == 'cleanupApp':
                    appName = msg[1]
                    group = self.groupName(appName)
                    self.zyre.leave(group)
                    if appName in self.groups:
                        del self.groups[appName]
                elif cmd == 'addActor':
                    appName, actorName = msg[1:]
                    assert appName in self.groups
                    self.actors[appName].add(actorName)
                    group = self.groupName(appName)
                    arg = "+ %s.%s" % (appName, actorName)
                    self.logger.info("FMMon.addActor.shout: %s" % arg)
                    self.zyre.shouts(group, arg.encode('utf-8'))
                    for peer in self.groups[appName]:
                        self.logger.info(
                            "FMMon.addactor tell %s.%s has peer at %s" %
                            (appName, actorName, str(peer)))
                        info = ('peer+', appName, actorName, peer)
                        self.command.send_pyobj(info)
                elif cmd == 'delActor':
                    appName, actorName = msg[1:]
                    assert appName in self.groups and actorName in self.actors[
                        appName]
                    self.actors[appName].remove(actorName)
                    group = self.groupName(appName)
                    arg = "- %s.%s" % (appName, actorName)
                    self.logger.info("FMMon.delActor.shout: %s" % arg)
                    self.zyre.shouts(group, arg.encode('utf-8'))
                elif cmd == 'dieActor':
                    appName, actorName = msg[1:]
                    assert appName in self.groups and actorName in self.actors[
                        appName]
                    self.actors[appName].remove(actorName)
                    group = self.groupName(appName)
                    arg = "? %s.%s" % (appName, actorName)
                    self.logger.info("FMMon.dieActor.shout: %s" % arg)
                    self.zyre.shouts(group, arg.encode('utf-8'))
                else:
                    pass  # Should be error
            elif reader == self.zyreSocket:
                event = ZyreEvent(self.zyre)
                eType = event.type()
                _pName = event.peer_name()
                pUUID = event.peer_uuid()
                pAddr = event.peer_addr()
                group = event.group()
                _headers = event.headers()
                msg = event.get_msg()
                #                 if eType != b'EVASIVE':
                #                     print("# %s %s %s %s %s %s %s"
                #                           % (str(eType),str(_pName),str(pUUID),str(pAddr),
                #                              str(group),str(_headers),str(msg)))
                if eType == b'ENTER':
                    self.logger.info("FMMon.ENTER %s from %s" %
                                     (str(pUUID), str(pAddr)))
                    try:
                        pAddrStr = pAddr.decode('UTF-8')
                        (peerIp,
                         _peerPort) = parse.parse("tcp://{}:{}", pAddrStr)
                        peerHeaderKey = self.peerHeaderKey(peerIp)
                        _value = _headers.lookup(peerHeaderKey)
                        if (_value):
                            try:
                                value = ctypes.cast(_value,
                                                    ctypes.c_char_p).value
                                assert value == self.PEERMARK
                                self.peers[pUUID] = pAddr
                                self.logger.info("FMMon.ENTER valid peer")
                            except:
                                self.logger.info(
                                    "FMMon.ENTER header value mismatch")
                        else:
                            self.logger.info("FMMon.ENTER header key mismatch")
                    except:
                        self.logger.info("FMMon.ENTER peer addr parsing error")
                elif pUUID not in self.peers:  # Skip the rest if this is not a peer
                    continue
                elif eType == b'JOIN':
                    groupName = group.decode()
                    self.logger.info("FMMon.JOIN %s from %s" %
                                     (str(groupName), str(pUUID)))
                    if groupName == 'riaps':
                        continue  # Joined riaps group - should be validated
                    else:
                        _head, appName = groupName.split('.')
                        if _head == 'riaps':
                            if appName not in self.groups:
                                self.groups[appName] = {pUUID}
                                if appName not in self.actors:
                                    self.actors[appName] = set()
                            else:
                                self.groups[appName].add(pUUID)
                            if appName in self.actors:
                                peer = pUUID
                                for actorName in self.actors[appName]:
                                    arg = "+ %s.%s" % (appName, actorName)
                                    self.logger.info(
                                        "FMMon.JOIN.whisper: %s to %s " %
                                        (arg, str(peer)))
                                    self.zyre.whispers(peer,
                                                       arg.encode('utf-8'))
                                    self.logger.info(
                                        "FMMon.JOIN tell %s.%s has peer at %s"
                                        % (appName, actorName, str(peer)))
                                    info = ('peer+', appName, actorName, peer)
                                    self.command.send_pyobj(info)
                        else:
                            pass
                elif eType == b'LEAVE':
                    groupName = group.decode()
                    self.logger.info("FMMon.LEAVE %s from %s" %
                                     (str(pUUID), str(group)))
                    if groupName == 'riaps':
                        continue  # Left riaps group - should be validated
                    else:
                        _head, appName = groupName.split('.')
                        if _head == 'riaps':
                            if appName in self.groups:
                                self.groups[appName].remove(pUUID)
                            if appName in self.actors:
                                for actorName in self.actors[appName]:
                                    peer = pUUID
                                    self.logger.info(
                                        "FMMon.LEAVE tell %s.%s lost peer at %s"
                                        % (appName, actorName, str(peer)))
                                    info = ('peer-', appName, actorName, peer)
                                    self.command.send_pyobj(info)
                        else:
                            pass
                elif eType == b'EXIT':
                    self.logger.info("FMMon.EXIT %s " % (str(pUUID)))
                    for appName, group in self.groups.items():
                        if pUUID in group:
                            if appName in self.actors:
                                for actorName in self.actors[appName]:
                                    peer = pUUID
                                    self.logger.info(
                                        "FMMon.EXIT tell %s.%s lost peer at %s"
                                        % (appName, actorName, str(peer)))
                                    info = ('peer-', appName, actorName, peer)
                                    self.command.send_pyobj(info)
                    if pUUID in self.peers: del self.peers[pUUID]
                elif eType == b'SHOUT' or eType == b'WHISPER':
                    # IF SHOUT, verify that this is for us
                    arg = msg.popstr().decode()
                    self.logger.info("FMMon.SHOUT %s = %s " %
                                     (str(pUUID), arg))
                    peer = pUUID
                    cmd, pair = arg.split(' ')
                    appName, actorName = pair.split('.', 1)
                    head, cast = '?', '?'
                    if cmd == '+':
                        head, cast = 'peer+', ' has peer '
                    elif cmd == '-':
                        head, cast = 'peer-', ' lost peer '
                    elif cmd == '?':
                        head, cast = 'peer-', ' lost peer '
                    if appName not in self.groups:
                        self.groups[appName] = {pUUID}
                    if appName in self.actors:
                        for actorName in self.actors[appName]:
                            self.logger.info("FMMon.%s: tell %s.%s %s %s" %
                                             (eType.decode(), appName,
                                              actorName, cast, str(peer)))
                            info = (head, appName, actorName, peer)
                            self.command.send_pyobj(info)
                else:
                    pass
        self.command.close()
        for appName in self.actors:
            if appName in self.groups:
                group = self.groupName(appName)
                arg = "- %s.%s" % (appName, actorName)
                self.logger.info("FMMon.terminate.shout: %s" % arg)
                self.zyre.shouts(group, arg.encode('utf-8'))
        self.zyre.leave(b'riaps')
        self.zyre.stop()