class XMLRPCNotificationChannel(Thread):
  """ Comunication channel used by the node to send notification to its controller.
  It is a one-way communication channel from the node to the controller.
  The controller calls the get method, and blocks waiting for a reply. Whenever a
  new event needs to be sent to the controller, this message is sent back in reply
  to the get method call and the controller calls back the get method.  
  """
    
  def __init__(self,host, port):
    """ Constructor.
    host : ip address of the node
    port : port used by this XML/RPC server"""
    Thread.__init__(self)
    self.host = host
    self.port = port
    self.server =  SimpleXMLRPCServer((self.host, self.port))
    self.server.register_instance(self)
    self.stopThread = False
    

    # Message to send queue
    self.outgoing = NotificationQueue()
    
    # this flag is set to True when we want to stop this thread
    self.stopThread = False
    
  def run(self):
    while not self.stopThread:
      self.server.handle_request()

  def get(self):
    """ Wait for notification from the node main thread and send back events to the
    controller. The controller calls the get method and is notified when a network
    event occurs."""
    # get the lock
    self.outgoing.acquire()
    # nothing to send, just wait
    if self.outgoing.empty():
      self.outgoing.wait()

    # the main thread called the notify method to awaken this thread
    # release the lock and send back the message to the controller.
    self.outgoing.release()
    
    e = self.outgoing.get()
    response = e.data()
    return response
    
  def send(self, message):
    """ Send a message to the controller"""
    self.outgoing.put(message)
Example #2
0
  def __init__(self, params):
    """ All informations about this node:
    host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, 
    ori --> a point, 
    exp --> expected number of neighbour, pseudo"""


    # event queue, used for inter-thread communication
    self.events = NotificationQueue()

    # network communication with peers is handled by this object
    netParams = params.getNetParams()
    self.peerConnector = UDPConnector("peer", self.events, netParams)

    controlParams = params.getControlParams()
    self.controlConnector = XMLRPCConnector("control", self.events, controlParams)

    # set the solipsis protocol used
    engineParams = params.getEngineParams()
    self.engine = V0_2_5_Engine(self, engineParams)

    self.controlEngine = ControlEngine(self, engineParams)
    self.internalEngine = InternalEngine(self, engineParams)
    
    position = [params.posX, params.posY]
    
    # call parent class constructor
    Entity.__init__(self, position, params.ori, params.ar, params.caliber,
                  params.pseudo)
    
    self.id = "unknown"
    
    # maximum expected number of neighbours.
    self.exp = params.exp
    
    # our IP address or 'localhost' if not specified in config file
    self.host = params.host
    
    self.alive = True
    self.logger = params.rootLogger
    
    # manage all peers
    peersParams = params.getPeersParams()
    self.peersManager = PeersManager(self, peersParams)

    # set world size in Geometry class
    Geometry.SIZE = params.world_size
    self.params=params
  def __init__(self,host, port):
    """ Constructor.
    host : ip address of the node
    port : port used by this XML/RPC server"""
    Thread.__init__(self)
    self.host = host
    self.port = port
    self.server =  SimpleXMLRPCServer((self.host, self.port))
    self.server.register_instance(self)
    self.stopThread = False
    

    # Message to send queue
    self.outgoing = NotificationQueue()
    
    # this flag is set to True when we want to stop this thread
    self.stopThread = False
Example #4
0
class Node(Entity):
  
  def __init__(self, params):
    """ All informations about this node:
    host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, 
    ori --> a point, 
    exp --> expected number of neighbour, pseudo"""


    # event queue, used for inter-thread communication
    self.events = NotificationQueue()

    # network communication with peers is handled by this object
    netParams = params.getNetParams()
    self.peerConnector = UDPConnector("peer", self.events, netParams)

    controlParams = params.getControlParams()
    self.controlConnector = XMLRPCConnector("control", self.events, controlParams)

    # set the solipsis protocol used
    engineParams = params.getEngineParams()
    self.engine = V0_2_5_Engine(self, engineParams)

    self.controlEngine = ControlEngine(self, engineParams)
    self.internalEngine = InternalEngine(self, engineParams)
    
    position = [params.posX, params.posY]
    
    # call parent class constructor
    Entity.__init__(self, position, params.ori, params.ar, params.caliber,
                  params.pseudo)
    
    self.id = "unknown"
    
    # maximum expected number of neighbours.
    self.exp = params.exp
    
    # our IP address or 'localhost' if not specified in config file
    self.host = params.host
    
    self.alive = True
    self.logger = params.rootLogger
    
    # manage all peers
    peersParams = params.getPeersParams()
    self.peersManager = PeersManager(self, peersParams)

    # set world size in Geometry class
    Geometry.SIZE = params.world_size
    self.params=params
   
  def getPeersManager(self):
    return self.peersManager

  def updatePosition(self, newPosition):
    """ update the position of the node
    newPosition : the new poition of the node , a list [posX, posY]
    """
    self.node.position = newPosition
    manager = self.getPeersManager()
    # re compute all positions of neighbours
    manager.update()
    

  def send(self, peer, message):
    """
    Send a message to a peer
    message : a solispsis message, e.g. 'HEARTBEAT;10.193.161.35:33363'
    peer    : a Peer object resenting the recipient of the message
    """
    #netEvent = NetworkEvent(message)
    #netEvent.setRecipient(peer.getNetAddress())
    #self.net.send(netEvent)
    self.peerConnector.send(peer, message)

  def sendController(self, message):
    self.controlConnector.send(message)
    
  def enterSolipsis(self):
    """
    Enter Solipsis world, we consider that we have entered solipsis as soon as have
    we are connected to one Solipsis entity
    Raise: SolipsisConnectionError when a timeout expires
    Return : True if the connection succeded
    """
    time_stamp = time.time()
    #message = "KNOCK;SOLIPSIS 0.3"
    message = "HI"
    timeout = self.params.connection_timeout
    
    while True:

      # retrieve peer
      manager = self.getPeersManager()
      peer = manager.getRandomPeer()
            
      # send message  
      self.send(peer, message)      
      time.sleep(0.5)

      # we got an answer, for one of our Hi messages: we have entered Solipsis 
      if not self.events.empty():
        self.alive = True
        return True

      # Time out : impossible to connect
      if time.time() > time_stamp + timeout:
        self.logger.critical("Time out: cannot connect to Solipsis")
        raise SolipsisConnectionError()

  def exit(self):
    """ stop the node and exit
    """
    # stop the network thread
    self.peerConnector.stop()

    # we do not need to stop the controlConnector. The controlConnector
    # stopped after sending us the exit message
    # --> self.controlConnector.stop() not needed !
    
    # wait for the other threads before exiting
    self.peerConnector.join()
    self.controlConnector.join()

    self.alive = False
    
  def mainLoop(self):
    """ Main loop of the program """
    # start control connector
    self.controlConnector.start()
    # start peer connector
    self.peerConnector.start()

    try:
      # enter solipsis : send the first message
      #self.enterSolipsis()
      pass
    except:
      self.logger.critical("cannot enter Solipsis, exiting...")
      self.exit()
      raise

    while self.alive:
      self.events.acquire()
      # no events to process - wait for a notification from other threads
      if self.events.empty():
        self.events.wait()
        
      # We can immediately release the lock: we know that there is an item available
      # because this is the only thread that consumes items from the queue.
      # If other threads can consume item then we must first get the item then
      # release the lock
      self.events.release()
      
      # process one event in queue        
      event = self.events.get()
      
      type = event.type()
      #self.logger.debug("%s - %s - %s ", event.name(), event.type(),
      #                  event.data())
      if( type == Event.PEER ):
        self.engine.process(event)
      elif( type == Event.CONTROL):
        self.controlEngine.process(event)
      elif type == Event.INTERNAL:
        self.internalEngine.process(event)
      else:
        self.logger.critical("Unknown event type" + type)
                      
    self.logger.debug("end of main loop")
    
  def processPeriodicEvent(self, event):
    """ Process periodic tasks
    Send heartbeat message
    Or check global connectivity
    """
    # TO DO
    self.logger.critical("processPeriodicEvent not implemented")
Example #5
0
class Node(Entity):
  
  def __init__(self, params):
    """ All informations about this node:
    host --> ip if the node, network_port, GUI_port, posX, posY, ar, ca, 
    ori --> a point, 
    exp --> expected number of neighbour, pseudo"""


    # event queue, used for inter-thread communication
    self.events = NotificationQueue()

    # network communication with peers is handled by this object
    netParams = params.getNetParams()
    self.peerConnector = UDPConnector("peer", self.events, netParams)

    controlParams = params.getControlParams()
    self.controlConnector = XMLRPCConnector("control", self.events, controlParams)

    intParams =  params.getInternalParams()
    self.internalConnector = InternalConnector('internal', self.events, intParams)
    
    position = Position(params.posX, params.posY)
    
    # call parent class constructor
    Entity.__init__(self, position, params.ori, params.ar, params.caliber,
                  params.pseudo)
    
    self.id = "unknown"
    
    # maximum expected number of neighbours.
    self.exp = params.exp
    
    # our IP address or 'localhost' if not specified in config file
    self.host = params.host
    
    self.alive = True
    self.logger = params.rootLogger
    
    # manage all peers
    peersParams = params.getPeersParams()
    self.peersManager = PeersManager(self, peersParams)

    # set world size in Geometry class
    Geometry.SIZE = params.world_size
    self.params=params

    self.state = None
    self.setState('NotConnected')
    
  def getPeersManager(self):
    return self.peersManager

  def setState(self, stateClass):
    stmt = 'state.' + stateClass + '(self, self.logger)'
    try:
      self.state = eval(stmt)
    except:
      raise SolipsisInternalError('unknown state ' + stateClass)

  def fire(self, event):
    """ Send an event.
    event : the event to send.
    """
    connector = None
    type = event.getType()
    if type == 'peer':
      connector = self.peerConnector
    elif type == 'control':
      connector = self.controlConnector
    elif type == 'internal':
      connector = self.internalConnector
    else:
      raise SolipsisInternalError('Unknown event type ' + type )
    
    connector.send(event)
    
  def exit(self):
    """ stop the node and exit
    """
    # stop the network thread
    self.peerConnector.stop()
    self.internalConnector.stop()    
    # we do not need to stop the controlConnector. The controlConnector
    # stopped after sending us the exit message
    # --> self.controlConnector.stop() not needed !
    
    # wait for the other threads before exiting
    self.peerConnector.join()
    self.controlConnector.join()
    self.internalConnector.join()
    self.alive = False
    
  def mainLoop(self):
    """ Main loop of the program """
    # start control connector
    self.controlConnector.start()
    # start peer connector
    self.peerConnector.start()
    # start internal connected : needed for periodic tasks
    self.internalConnector.start()
    

    while self.alive:
      self.events.acquire()
      # no events to process - wait for a notification from other threads
      if self.events.empty():
        self.events.wait()
        
      # We can immediately release the lock: we know that there is an item available
      # because this is the only thread that consumes items from the queue.
      # If other threads can consume item then we must first get the item then
      # release the lock
      self.events.release()
      
      # process one event in queue        
      event = self.events.get()
      request = event.getRequest()

      try:
        # process this request according to our current state
        # e.g.: stmt='self.state.NEAREST(event)'
        stmt = 'self.state.' + request + '(event)'
        eval(stmt)
      except:
        self.logger.debug(sys.exc_info()[0])
        self.logger.debug(sys.exc_info()[1])
        self.logger.debug("unknown request "+ stmt)
                                 
    self.logger.debug("end of main loop")