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)
def promotionhandler(self, timeout=10): # TODO: change to 10 min (600) for production use. '''Promote the node to super node after some uptime.''' yield dht.randomsleep(timeout) # wait for some uptime if _debug: print 'promotionhandler invoked' if self.client and self.client.neighbors: 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.bs = self.client.neighbors; if _debug: print 'joining the dht' joined = yield self.router.join(self.router.bs[0]) if joined: self.client.server = True
def mcastreceiver(self, maxsize=1500, timeout=None, interval=30): while True: if self.mcast is not None: data, addr = yield multitask.recvfrom(self.mcast, maxsize, timeout=timeout) msg, remote = self.parse(data, addr, self.mcast.type) if not msg: print 'ignoring empty msg'; continue # ignore invalid message. TODO: handle non-p2p message if remote == self.node: if _debug: print 'ignoring our own multicast packet' continue if _debug: print self.name, 'mcast-received %s=>%s: %r'%(remote.hostport, self.nodemcast.hostport, msg) if 'ack' in msg: del msg['ack'] # just remove ack, but don't send an ack for multicast msg['remote'] = remote msg['multicast'] = True # so that application knows that this is received on multicast yield self.put(msg) else: yield dht.randomsleep(interval)
def promotionhandler( self, timeout=10): # TODO: change to 10 min (600) for production use. '''Promote the node to super node after some uptime.''' yield dht.randomsleep(timeout) # wait for some uptime if _debug: print 'promotionhandler invoked' if self.client and self.client.neighbors: 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.bs = self.client.neighbors if _debug: print 'joining the dht' joined = yield self.router.join(self.router.bs[0]) if joined: self.client.server = True
def mcastreceiver(self, maxsize=1500, timeout=None, interval=30): while True: if self.mcast is not None: data, addr = yield multitask.recvfrom(self.mcast, maxsize, timeout=timeout) msg, remote = self.parse(data, addr, self.mcast.type) if not msg: print 'ignoring empty msg' continue # ignore invalid message. TODO: handle non-p2p message if remote == self.node: if _debug: print 'ignoring our own multicast packet' continue if _debug: print self.name, 'mcast-received %s=>%s: %r' % ( remote.hostport, self.nodemcast.hostport, msg) if 'ack' in msg: del msg[ 'ack'] # just remove ack, but don't send an ack for multicast msg['remote'] = remote msg['multicast'] = True # so that application knows that this is received on multicast yield self.put(msg) else: yield dht.randomsleep(interval)
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)