Пример #1
0
    def __init__(self, Ks, cert):
        '''Construct a new network object. The application must invoke bind() before using any
        other function on this object. The private key Ks and certificate cert must be supplied
        to construct a network object.'''
        Network.count = Network.count + 1
        self.name = 'Network[%d]' % (Network.count)
        self.queue = multitask.SmartQueue(
        )  # module's default queue for dispatching and receiving Message events
        self.qsip = multitask.SmartQueue()  # queue for SIP messages
        self.qstun = multitask.SmartQueue()  # queue for STUN-related messages

        self.Ks, self.cert = Ks, cert
        self.udp, self.tcp, self.mcast = createSockets(preferred=(ADDRESS,
                                                                  PORT))
        self.tcp.listen(5)
        self.tcpc = dict(
        )  # table of client connections from Node to connected socket if any.
        ip, port = getlocaladdr(self.udp)
        ignore, ptcp = getlocaladdr(self.tcp)
        self.node = Node(ip=ip,
                         port=port,
                         type=socket.SOCK_DGRAM,
                         guid=H(ip + ':' +
                                str(port)))  # TODO: construct this using H(Kp)
        self.nodetcp = Node(ip=ip,
                            port=ptcp,
                            type=socket.SOCK_STREAM,
                            guid=self.node.guid)
        self.nodemcast = Node(ip=ADDRESS,
                              port=PORT,
                              type=socket.SOCK_DGRAM,
                              guid=self.node.guid)
        self.gen = self.gentcp = self.genmcast = None
Пример #2
0
    def start(self, net=None, servers=None):
        '''Start the p2p node as ordinary node. Create a network object if none.'''
        if self.net is None:
            self.net = net or Network(
                Ks=crypto.generateRSA()[0], cert=None, port=self.port)
            self.net.start()

            # convert from serevrs ip:port list to Node list
            if servers:
                servers = [
                    Node(ip=ip,
                         port=port,
                         type=socket.SOCK_DGRAM,
                         guid=H(ip + ':' + str(port))) for ip, port in servers
                ]
                if _debug: print 'using servers=', servers

            self.client = Client(self.net, server=self.server).start(servers)
            if self.server:
                if self.router is None:
                    self.router = dht.Router(self.net).start()
                if self.storage is None:
                    self.storage = dht.Storage(self.net, self.router).start()
                if not self.router.initialized: self.router.initialized = True
        if not self._gens:
            for gen in [self.handler()]:
                multitask.add(gen)
                self._gens.append(gen)
        return self
Пример #3
0
 def parse(self, data, addr, type):
     '''Parse a message from given remote (host, port) and return parsed Message and remote Node.
     Returns None as message if can't be parsed.'''
     if len(data) < Hsize: return (None, None)
     guid, data = dht.bin2int(data[0:Hsize]), data[Hsize:]
     node = Node(ip=addr[0], port=addr[1], type=type, guid=guid)
     try:
         msg = Message(raw=data)
     except:
         return (None, None)
     return (msg, node)
Пример #4
0
 def start(self, servers=[]):
     '''Start the client with the given set of optional servers list.'''
     if not self._gens:
         guid = H(ADDRESS + ':' + str(PORT))
         try:
             bs = [
                 Node(ip=socket.gethostbyname(BOOTSTRAP),
                      port=PORT,
                      type=socket.SOCK_STREAM,
                      guid=guid)
             ]
         except:
             bs = []
         self.candidates = [self.net.nodemcast] + servers + bs
         if _debug: print 'Client.start candidates=', self.candidates
         self.neighbors = []
         self._gens = [
             self.discoverhandler(),
             self.bootstrap(),
             self.clienthandler()
         ]  # , self.pinghandler()
         for gen in self._gens:
             multitask.add(gen)
     return self
Пример #5
0
 def bootstrap(self, timeout=5, interval=30):
     '''A generator to perform bootstrap function.'''
     candidates = self.candidates[:]  # a copy of list of candidates
     while True:
         if _debug:
             print self.net.name, 'bootstrap server=', self.server, 'neighbors=', len(
                 self.neighbors), 'candidates=', len(candidates)
         if not self.server and not self.neighbors and candidates:  # more candidates but no more neighbors
             node = candidates.pop(0)
             if _debug: print 'bootstrap trying node=', repr(node)
             if node.type == socket.SOCK_DGRAM and isMulticast(node.ip):
                 yield self.net.send(Message(name='Discover:Request'),
                                     node=node)
                 msg = yield self.net.get(
                     lambda x: x.name == 'Discover:Response' and x.
                     multicast,
                     timeout=timeout)
             else:
                 if not isIPv4(node.ip):  # is a IP address?
                     node = Node(ip=socket.gethostbyname(node.ip),
                                 port=node.port,
                                 type=node.type,
                                 guid=node.guid)
                 yield self.net.send(Message(name='Discover:Request'),
                                     node=node)
                 msg = yield self.net.get(
                     lambda x: x.name == 'Discover:Response' and not x.
                     multicast,
                     timeout=timeout)
             if msg:
                 added = False
                 for node in msg.neighbors:
                     if node.hostport == msg.remote.hostport:  # whether msg.remote exists in msg.neighbors, which means remote is a server and we are already connected.
                         if _debug: print 'received neighbor', repr(node)
                         self.neighbors.insert(
                             0,
                             node)  # put this as most preferred neighbor.
                         added = True
                     else:
                         if _debug: print 'received candidate', repr(node)
                         candidates.append(
                             node)  # put this as the next candidate
                 if added:
                     yield self.net.put(
                         Message(name='Discover:Indication',
                                 node=self.node,
                                 neighbors=self.neighbors)
                     )  # indicate change in client.
             else:
                 if _debug: print 'bootstrap did not receive response.'
         elif not self.server and self.neighbors:  # perform neighbor refresh
             yield dht.randomsleep(timeout)
             result = yield self.net.send(Message(name='Ping:Request'),
                                          node=self.neighbors[0],
                                          timeout=timeout)
             if not result:  # no response received, remove the neighbor
                 del self.neighbors[0]
                 yield self.net.put(
                     Message(name='Discover:Indication',
                             node=self.node,
                             neighbors=self.neighbors)
                 )  # indicate change in client.
         elif not self.server and not self.neighbors and not candidates:
             candidates = self.candidates[:]
             yield dht.randomsleep(timeout)
         else:  # just wait before trying again.
             yield dht.randomsleep(interval)