示例#1
0
    def AROUND(self, event):
        """ A peer sent us an AROUND message """
        # cancel timer since we got our response
        self.timer.cancel()

        peer = event.createRemotePeer()
        # current number of neighbours
        nbNeighbours = len(self.neighbours)
        # last neighbour found
        last = self.neighbours[nbNeighbours-1]

        nodePos = self.node.getPosition() # our position
        bestPos = self.best.getPosition() # position of best node

        peerPos = Geometry.relativePosition(peer.getPosition(),
                                                 self.node.getPosition())

        # check if turn ends : we have at least 3 neighbours and either we got back
        # to the first peer (=> turn completed) or our last neighbour was in the
        # left half plane and this peer is in the right half plane
        if ( nbNeighbours > 2 ) and (peer.getId() == self.best.getId()) or (
            not Geometry.inHalfPlane(bestPos, nodePos, last.getPosition())
            and Geometry.inHalfPlane(bestPos, nodePos, peerPos) ):

            # Our awarenesse radius is the distance between us and our closest
            # neighbour, because we are sure to know all the entities between us
            # and the best.
            bestRelativePos = Geometry.relativePosition(bestPos, nodePos)
            minDistance = Geometry.distance(bestRelativePos, nodePos)
            self.node.setAwarenessRadius(minDistance)

            # register these peers with the peerManager and connect !
            manager = self.node.getPeersManager()
            for p in self.neighbours:
                # FIXME : should we add the peer upon receiving the CONNECT msg?
                manager.addPeer(p)
                factory = EventFactory.getInstance(PeerEvent.TYPE)
                hello = factory.createHELLO()
                hello.setRecipientAddress(p.getAddress())
                self.node.dispatch(hello)

            self.node.setState(Connecting())
        else:
            # add this peer to our list of neighbours
            self.addPeerAround(peer)

            # send this peer a queryaround message
            bestDist = Geometry.distance(bestPos, nodePos)
            factory = EventFactory.getInstance(PeerEvent.TYPE)
            queryaround = factory.createQUERYAROUND(self.best.getId(), bestDist)
            queryaround.setRecipientAddress(peer.getAddress())
            self.node.dispatch(queryaround)
            self.startTimer()
示例#2
0
    def SEARCH(self, event):
        """ search an entity to restore the global connectivity of an other node
        reception of message: SEARCH, id, wise = 1 if counterclockwise"""
        id_ = event.getArg(protocol.ARG_ID)
        wise = event.getArg(protocol.ARG_CLOCKWISE)
        manager = self.node.getPeersManager()
        queryEnt = None

        try:
            # queryEnt is the querying entity
            queryEnt = manager.getPeer(id_)
        except UnknownIdError:
            self.logger.debug('Error, reception of SEARCH message with unknown ' +
                               'peer ID: ' + id_)
            return

        # update the status of querying entity
        manager.heartbeat(id_)

        around = manager.getPeerAround(queryEnt.getPosition(), id_, wise)

        # send message if an entity has been found.
        if around is not None:
            factory = EventFactory.getInstance(PeerEvent.TYPE)
            aroundEvt = factory.createFOUND(around)
            aroundEvt.setRecipientAddress(event.getSenderAddress())
            self.node.dispatch(aroundEvt)
示例#3
0
    def CLOSE(self, event):
        """ Connection closed with one of our peers."""
        id_ = event.getArg(protocol.ARG_ID)
        manager = self.node.getPeersManager()
        manager.removePeer(id_)

        # notify controler that we lost connection with a peer
        factory = EventFactory.getInstance(ControlEvent.TYPE)
        dead = factory.createDEAD(id_)
        self.node.dispatch(dead)

        # check what is our state
        if manager.hasTooFewPeers():
            self.increaseAr()

            # we don't have enough peers but our Global Connectivity is OK
            if manager.hasGlobalConnectity():
                self.node.setState(NotEnoughPeers())
            # not enough peers + GC is NOK
            else:
                self.searchPeers()
                self.node.setState(NotEnoughPeersAndNoGlobalConnectivity())
        # we still have enough peers
        else:
            # but we don't have our GC
            if not manager.hasGlobalConnectity():
                self.searchPeers()
                self.node.setState(NotEnoughPeersAndNoGlobalConnectivity())
示例#4
0
 def sendUpdates(self):
     """ Send an UPDATE message to all our peers"""
     mng = self.node.getPeersManager()
     update = EventFactory.getInstance(PeerEvent.TYPE).createUPDATE()
     for p in mng.enumeratePeers():
         update.setRecipientAddress(p.getAddress())
         self.node.dispatch(update)
示例#5
0
    def BEST(self, event):
        """ A peer sent us a BEST message
        This is the default behaviour
        """
        # unexpected message, do not process it
        msg = 'BEST'
        if not self.isExpected(msg):
            self.logger.debug('Error, reception of a ' + msg + 'message in state '
                              + str(self.__class__))
            return

        self.timer.cancel()

        # Get the ID and the position of the BEST peer
        bestId = event.getArg(protocol.ARG_ID)
        bestPos = event.getArg(protocol.ARG_POSITION)
        bestAddress = event.getSenderAddress()

        # send a queryaround message
        bestDistance = Geometry.distance(self.node.getPosition(), bestPos)
        factory = EventFactory.getInstance(PeerEvent.TYPE)
        queryaround = factory.createQUERYAROUND(bestId, bestDistance)
        queryaround.setRecipientAddress(bestAddress)
        self.node.dispatch(queryaround)

        # Create a turning state and store the Best peer
        bestPeer = Peer(id=bestId, address=event.getSenderAddress(),
                        position=bestPos)
        scanning = Scanning()
        scanning.setBestPeer(bestPeer)

        # go to the Scanning state
        self.node.setState(scanning)
示例#6
0
    def QUERYAROUND(self, event):
        """ A peer sent us a QUERYAROUND message """
        #peer, idNearest, distNearest:
        source_id = event.getArg(protocol.ARG_ID)
        idNearest = event.getArg(protocol.ARG_BEST_ID)
        distNearest = event.getArg(protocol.ARG_BEST_DISTANCE)
        manager = self.node.getPeersManager()
        target = event.getArg(protocol.ARG_POSITION)
        closest = manager.getClosestPeer(target, source_id)

        factory = EventFactory.getInstance(PeerEvent.TYPE)
        # found a closest peer and this peer is a new one (it isn't idNearest moving
        # toward target position).
        if ( (Geometry.distance(closest.getPosition(), target) < distNearest) and
             closest.getId() <> idNearest ):
            # send a nearest message
            nearestEvent = factory.createNEAREST(closest)
            nearestEvent.setRecipientAddress(event.getSenderAddress())
            self.node.dispatch(nearestEvent)

        else:
            # search for a peer around target position
            around = manager.getPeerAround(target, source_id)
            if around is not None:
                aroundEvt = factory.createAROUND(around)
                aroundEvt.setRecipientAddress(event.getSenderAddress())
                self.node.dispatch(aroundEvt)
            else:
                self.logger.debug('no peer around position: ' + str(target))
示例#7
0
    def CONNECT(self, event):
        """ reception of a connect message """
        # TODO :check that we sent a HELLO message to this peer
        peer = event.createPeer()
        mng = self.node.getPeersManager()
        if  not mng.hasPeer(peer.getId()):
            mng.addPeer(peer)
            factory = EventFactory.getInstance(ControlEvent.TYPE)
            newPeerEvent = factory.createNEW(peer)
            self.node.dispatch(newPeerEvent)

            # Give the list of our services to the peer
            for s in self.node.enumerateServices():
                factory = EventFactory.getInstance(PeerEvent.TYPE)
                srvEvt = factory.createADDSERVICE(s.getId())
                srvEvt.setRecipientAddress(event.getSenderAddress())
                self.node.dispatch(srvEvt)
示例#8
0
 def addPeer(self, peer):
     """ Add a peer and send the necessary notification messages. """
     manager = self.node.getPeersManager()
     manager.addPeer(peer)
     factory = EventFactory.getInstance(ControlEvent.TYPE)
     newPeerEvent = factory.createNEW(peer)
     self.node.dispatch(newPeerEvent)
     if type(self) == Idle:
         if manager.hasTooManyPeers():
             self.node.setState(TooManyPeers())
示例#9
0
    def removePeer(self, peer):
        """ Remove a peer and send the necessary notification messages. """
        manager = self.node.getPeersManager()
        id_ = peer.getId()
        manager.removePeer(id_)

        # notify controler that we lost connection with a peer
        factory = EventFactory.getInstance(ControlEvent.TYPE)
        dead = factory.createDEAD(id_)
        self.node.dispatch(dead)
示例#10
0
 def sendFindNearest(self, peerAddress):
     """ Send a FINNEAREST event and return the timer object assocoiated
     with this request
     peerAddress : network address of the peer who will receive this request
     """
     # create a findnearest event
     factory = EventFactory.getInstance(PeerEvent.TYPE)
     findnearest = factory.createFINDNEAREST()
     findnearest.setRecipientAddress(peerAddress)
     self.node.dispatch(findnearest)
示例#11
0
 def OnTimeOut(self):
     """ The timer expired, add a TIMER event to the event Queue.
     This method is called from a timer thread, queing a new event will ensure
     that the timer procedure will be executed from the main thread
     """
     factory = EventFactory.getInstance(ControlEvent.TYPE)
     timerEvt = factory.createTIMER()
     # this event is directly added to the event queue (and not using the
     # node.dispatch() method) because we don't want this event to be processed
     # by the controller connector but by the node itself
     self.node.events.put(timerEvt)
示例#12
0
    def OnHeartbeat(self, node):
        """ Heartbeat function : send an heartbeat to all peers

        node : the node that is going to send heartbeat
        """
        factory = EventFactory.getInstance(PeerEvent.TYPE)
        hb = factory.createHEARTBEAT()

        # send heartbeat to all our peers
        for p in node.getPeersManager().enumeratePeers():
            hb.setRecipientAddress(p.getAddress())
            node.dispatch(hb)
示例#13
0
    def FOUND(self, event):
        """ an entity detected in an empty sector
        reception of message: FOUND"""
        peer = event.createRemotePeer()
        manager = self.node.getPeersManager()
        id_ = peer.getId()
        factory = EventFactory.getInstance(PeerEvent.TYPE)

        # verify that new entity is neither self neither an already known entity.
        if id_ != self.node.getId() and not manager.hasPeer(id_):
            hello = factory.createHELLO()
            hello.setRecipientAddress(peer.getAddress())
            self.node.dispatch(hello)
示例#14
0
    def TIMER(self, event):
        """ Timeout : check if we still have too many peers peers"""
        manager = self.node.getPeersManager()
        factory = EventFactory.getInstance(PeerEvent.TYPE)

        while manager.getNumberOfPeers() > manager.getExpectedPeers():
            peer = manager.getWorstPeer()
            close = factory.createCLOSE()
            close.setRecipientAddress(peer.getAddress())
            self.node.dispatch(close)
            self.removePeer(peer)

        self.updateAwarenessRadius()
        self.node.setState(Idle())
示例#15
0
 def DELSERVICE(self, event):
     """ A peer sent us a DELSERVICE message.
     The described service is longer available for this peer
     """
     # get service ID
     srvId = event.getArg(protocol.ARG_SERVICE_ID)
     # update the corresponding peer
     id_ = event.getArg(protocol.ARG_ID)
     peer = self.node.getPeersManager().getPeer(id_)
     peer.delService(srvId)
     # notify the controller that this peer deleted a service
     factory = EventFactory.getInstance(ControlEvent.TYPE)
     delsrv = factory.createDELSERVICE(id_, srvId)
     self.node.dispatch(delsrv)
示例#16
0
 def TIMER(self, event):
     """ Timeout : check if we still have too many peers peers"""
     manager = self.node.getPeersManager()
     factory = EventFactory.getInstance(PeerEvent.TYPE)
     
     for p in manager.getWorstPeers():
         close = factory.createCLOSE()
         close.setRecipientAddress(p.getAddress())
         manager.removePeer(p.getId())
         self.node.dispatch(close)
         
     self.node.setAwarenessRadius(manager.computeAwarenessRadius())
     self.sendUpdate()
         
     self.setState(Idle())
示例#17
0
    def searchPeers(self):
        """ Our Global connectivity is NOT OK, we have to search for new peers"""
        manager = self.node.getPeersManager()
        factory = EventFactory.getInstance(PeerEvent.TYPE)

        # send msg SEARCH.
        searchEntities = manager.getBadGlobalConnectivityPeers()
        for pair in searchEntities:
            # send message to each entity
            searchClockWise = factory.createSEARCH(True)
            searchCounterclockWise = factory.createSEARCH(False)
            searchClockWise.setRecipientAddress(pair[0].getAddress())
            searchCounterclockWise.setRecipientAddress(pair[1].getAddress())
            self.node.dispatch(searchClockWise)
            self.node.dispatch(searchCounterclockWise)
示例#18
0
    def DETECT(self, event):
        """ Notification that a peer is moving towards us"""
        peer = event.createRemotePeer()
        manager = self.node.getPeersManager()
        # we are only interested by entities that are not yet in our peer list
        if not manager.hasPeer(peer.getId()):

            # with this new peer, we now have too many peers
            # and the newly added peer is in fact our worst neighbour
            # so we remove this peer, and we don't contact this peer
            if manager.isWorstPeer(peer): pass
            else:
                # Connect to this peer
                factory = EventFactory.getInstance(PeerEvent.TYPE)
                hello = factory.createHELLO()
                hello.setRecipientAddress(peer.getAddress())
                self.node.dispatch(hello)
示例#19
0
    def jump(self):
        """ Jump to the node's current position. This involves
        the recursive teleportation algorithm. """
        manager = self.node.getPeersManager()
        peer = manager.getRandomPeer()
        self.sendFindNearest(peer.getAddress())

        # Disconnect from our current peers
        peerFct = EventFactory.getInstance(PeerEvent.TYPE)
        for peer in manager.enumeratePeers():
            evt = peerFct.createCLOSE()
            evt.setRecipientAddress(peer.getAddress())
            self.node.dispatch(evt)
            self.removePeer(peer)

        # Go to the tracking state
        self.node.setState(Locating())
示例#20
0
    def FINDNEAREST(self, event):
        """ A peer sent us a FINDNEAREST message """
        targetPosition = event.getArg(protocol.ARG_POSITION)
        nearestPeer = self.node.getPeersManager().getClosestPeer(targetPosition)

        factory = EventFactory.getInstance(PeerEvent.TYPE)

        # check if I am not closer than nearestPeer
        if (nearestPeer.isCloser(self.node, targetPosition)):
            response = factory.createNEAREST(nearestPeer)
        # I'm closer : send a best message
        else:
            response = factory.createBEST()

        response.setRecipientAddress(event.getSenderAddress())

        # send reply to remote peer
        self.node.dispatch(response)
示例#21
0
    def ADDSERVICE(self, event):
        """ A peer sent us a ADDSERVICE message """
        # get service information
        srvId = event.getArg(protocol.ARG_SERVICE_ID)
        srvDesc =event.getArg(protocol.ARG_SERVICE_DESC)
        srvAddress = event.getArg(protocol.ARG_SERVICE_ADDRESS)
        # See solipsis.navigator.service
        srv = Service(srvId, srvDesc, srvAddress)

        # update the corresponding peer
        id_ = event.getArg(protocol.ARG_ID)
        peer = self.node.getPeersManager().getPeer(id_)
        peer.addService(srv)

        # notify the controller that this peer has a new service available
        factory = EventFactory.getInstance(ControlEvent.TYPE)
        addsrv = factory.createADDSERVICE(id_, srvId, srvDesc, srvAddress)
        self.node.dispatch(addsrv)
示例#22
0
    def CLOSE(self, event):
        """ A peer sent us a CLOSE message."""
        # remove the corresponding peer
        id_ = event.getArg(protocol.ARG_ID)
        manager = self.node.getPeersManager()
        manager = removePeer(id_)

        # notify the controller that we lost connection with this peer
        factory = EventFactory.getInstance(ControlEvent.TYPE)
        dead = factory.createDEAD(id_)
        self.node.dispatch(dead)
        if manager.hasTooFewPeers():
            if not manager.hasGlobalConnectivity():
                self.node.setState(NotEnoughPeersAndNoGlobalConnectivity())
            else:
                self.node.setState(NotEnoughPeers())
        elif not manager.hasGlobalConnectivity():
            self.node.setState(NoGlobalConnectivity())
示例#23
0
    def searchPeers(self):
        """ Our Global connectivity is NOT OK, we have to search for new peers"""
        manager = self.node.getPeersManager()
        factory = EventFactory.getInstance(PeerEvent.TYPE)

        if manager.getNumberOfPeers() == 0:
            self.logger.info("All peers lost, relaunching JUMP algorithm")
            self.jump()

        else:
            # send msg SEARCH
            pair = manager.getBadGlobalConnectivityPeers()

            if pair:
                # send message to each entity
                searchClockWise = factory.createSEARCH(True)
                searchCounterclockWise = factory.createSEARCH(False)
                searchClockWise.setRecipientAddress(pair[0].getAddress())
                searchCounterclockWise.setRecipientAddress(pair[1].getAddress())
                self.node.dispatch(searchClockWise)
                self.node.dispatch(searchCounterclockWise)
示例#24
0
    def DETECT(self, event):
        """ Notification that a peer is moving towards us"""
        peer = event.createRemotePeer()
        id_ = peer.getId()
        manager = self.node.getPeersManager()
        # Sanity check 1: don't connect with ourselves
        if id_ == self.node.getId():
            return
        # Sanity check 2: don't connect with someone too far from us
        dist = Geometry.distance(self.node.getPosition(), peer.getPosition())
        ar = self.node.getAwarenessRadius()
        if dist > ar:
            return

        # we are only interested by entities that are not yet in our peer list
        if not manager.hasPeer(id_):
            # Check we don't have too many peers, or have worse peers than this one
            if manager.isPeerAccepted(peer):
                # Connect to this peer
                factory = EventFactory.getInstance(PeerEvent.TYPE)
                hello = factory.createHELLO()
                hello.setRecipientAddress(peer.getAddress())
                self.node.dispatch(hello)
示例#25
0
    def HELLO(self, event):
        """ A new peer is contacting us """
        peer = event.createPeer()
        manager = self.node.getPeersManager()

        factory = EventFactory.getInstance(PeerEvent.TYPE)

        # We have now too many peers and this is the worst one
        if manager.isWorstPeer(peer):
            # refuse connection
            close = factory.createCLOSE()
            close.setRecipientAddress(peer.getAddress())
            self.node.dispatch(close)
        else:
            # check if we have not already connected to this peer
            if not manager.hasPeer(peer.getId()):
                manager.addPeer(peer)
                connect = factory.createCONNECT()
                connect.setRecipientAddress(peer.getAddress())
                self.node.dispatch(connect)
            else:
                self.logger.debug('HELLO from %s, but we are already connected',
                                  peer.getId())
示例#26
0
    def UPDATE(self, event):
        """ A peer sent us an UPDATE message."""
        # extract the peer from the event
        peer = event.createPeer()
        id_ = peer.getId()

        manager = self.node.getPeersManager()
        if not manager.hasPeer(id_):
            self.logger.debug('UPDATE from %s, but we are not connected' % peer.getId())
            return

        # save peer old value
        oldPeer = manager.getPeer(event.getArg(protocol.ARG_ID))

        # update peer
        manager.updatePeer(peer)

        # notify the controller that a peer has changed
        ctlFact = EventFactory.getInstance(ControlEvent.TYPE)
        upd = ctlFact.createUPDATE(peer)
        self.node.dispatch(upd)

        oldPosition = oldPeer.getPosition()
        newPosition = peer.getPosition()
        nodePosition = self.node.getPosition()

        oldAR = oldPeer.getAwarenessRadius()
        newAR = peer.getAwarenessRadius()

        peerFct = EventFactory.getInstance(PeerEvent.TYPE)

        # peer position changed
        if not oldPosition == newPosition:
            # verify entities that could be interested by the entity id
            for ent in manager.enumeratePeers():
                if ent.getId() == id_:
                    continue
                itsAR = ent.getAwarenessRadius()

                # get distance between self and ent
                ourDist = Geometry.distance(nodePosition, ent.getPosition())

                # get distance between ent and entity id
                theirDist = Geometry.distance(ent.getPosition(), newPosition)

                # get old distance between ent and entity id
                theirOldDist = Geometry.distance(ent.getPosition(), oldPosition)

                if (theirDist < itsAR < theirOldDist) or \
                       (theirDist < ourDist < theirOldDist):
                    # modified entity enters in Awareness Area of ent
                    # OR moving entity is now closer than us to ent

                    # The moving peer is notified to a fixed entity
                    detect = peerFct.createDETECT(peer)
                    detect.setRecipientAddress(ent.getAddress())
                    self.node.dispatch(detect)

                elif oldAR < theirOldDist and newAR >= theirDist:
                    # The entity is notified to the moving peer
                    detect = peerFct.createDETECT(ent)
                    detect.setRecipientAddress(peer.getAddress())
                    self.node.dispatch(detect)

        # peer awareness radius changed
        if not oldAR == newAR:
            self.logger.debug('AR updated %d -> %d' % (oldAR, newAR))
            # verify entities that could be interested by the modified entity.
            for ent in manager.enumeratePeers():
                if ent.getId() == id_:
                    continue
                # get distance between ent and modified entity
                position = ent.getPosition()
                theirDist = Geometry.distance(position, newPosition)
                theirOldDist = Geometry.distance(position, oldPosition)
                self.logger.debug('peer %s: position (%s), old dist %d, new dist %d' %
                    (ent.getId(), str(position), theirDist, theirOldDist))

                if oldAR < theirOldDist and newAR >= theirDist:
                    # ent enter in Awareness Area of modified entity.
                    # DETECT message sent to modified entity.
                    detect = peerFct.createDETECT(ent)
                    detect.setRecipientAddress(peer.getAddress())
                    self.node.dispatch(detect)
示例#27
0
 def get_events(self):
     response = self.client.get(url=event_host + '/v3/events', timeout=self.config['lp_wait_timeout'])
     if response.json()['events']:
         return [EventFactory.create(event_json) for event_json in response.json()['events']]
     else:
         return []
示例#28
0
 def GETNODEINFO(self, event):
     factory = EventFactory.getInstance(ControlEvent.TYPE)
     info = factory.createNODEINFO()
     self.node.dispatch(info)
示例#29
0
 def connectionError(self):
     factory = EventFactory.getInstance(ControlEvent.TYPE)
     error = factory.createERROR('Error: cannot connect to Solipsis')
     self.node.setState(NotConnected())
     self.node.dispatch(error)