def getFirstTwoHosts(self): #this method listens for broadcast requests #and sends timely broadcast requests to accommodate #new hosts and also replies for connection requests #set time-out for incoming broadcast requests self.soc.settimeout(Config.BROADCAST_TIMEOUT) #set the option for sending bcast packet self.soc.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) b_pac = LinkPacket() b_pac.setMessageByFields(1,Config.NODE_IP_ADDRESS,'') replyList = [] while len(self.nodes) < 2: #stores all the replies for #the broadcasts by the current node #(in-degree,ip-address) replyList = [] #send a bcast packet self.soc.sendto(b_pac.getRawMessage(), (Config.BROADCAST_IP_ADDRESS, Config.UDP_LISTEN_PORT)) print 'Sent broadcast request' while 1: if len(self.nodes) >= 2: return try: pac,addr = self.soc.recvfrom(1024) print '**** ***** ***** ****** ****' r_pac = LinkPacket(pac) except socket.timeout: #no requests or replies in the last few seconds #check if there are already two neighbours if len(self.nodes) >= 2: #return from the function #since the purpose is fulfilled return if len(replyList)==0: #no node replies for bcasts #so repeat it again break print 'Reply list not empty' print replyList #get the list, sort them, choose one #with least degree, send a conn. req. replyList.sort() for tup in replyList: #check if its already a neighbour if tup[1] not in self.nodes: conn_pac = LinkPacket() conn_pac.setMessageByFields(2 , Config.NODE_IP_ADDRESS, str(tup[0])) self.soc.sendto(conn_pac.getRawMessage(), (tup[1], Config.UDP_LISTEN_PORT)) break break if addr[0]==Config.NODE_IP_ADDRESS: #print 'loopback packet' continue if not r_pac.isValid(): #print 'Is Invalid' continue print 'src:',addr r_pac.printSegmentedMessage() rep_pac = LinkPacket() if r_pac.getIPAddress() not in self.nodes and \ r_pac.getRequestType()==10: #someone replied for our bcast replyList.append([ int(r_pac.getPayload()), r_pac.getIPAddress() ]) elif r_pac.getRequestType()==2: #connection request to this machine rep_pac = self.confirmConnectionRequest(r_pac) self.soc.sendto(rep_pac.getRawMessage(), addr) elif r_pac.getRequestType()==1: #someone is bcasting for a new #connection,reply them with current degree rep_pac.setMessageByFields(10, Config.NODE_IP_ADDRESS, str(len(self.nodes))) self.soc.sendto(rep_pac.getRawMessage(), addr) elif r_pac.getRequestType()==6: #got a reply to build a new connection #for a conn. req sent previously self.secondConfirmReq(r_pac) elif r_pac.getRequestType()==4: #neighbour updates self.addorRemoveNeighbourToEntity(r_pac.getIPAddress(), r_pac.getPayload()) elif r_pac.getRequestType()==7: tp = LinkPacket() tp.setMessageByFields(8,self.ip_address,'') self.soc.sendto(tp.getRawMessage(), addr)
def listen(self): #initially send a broadcast for joining the network... while 1: dat,addr = self.soc.recvfrom(1024) #time.sleep(3) #handling all possible cases... pac = LinkPacket(dat) if not pac.isValid(): print 'Corrupted packet from',addr continue to_be_replied=0 r_type = pac.getRequestType() reply_pac = LinkPacket() print "src:",addr,"type:",r_type if r_type==1: # brdcast for conn. request.. so reply with details.. to_be_replied=1 reply_pac.setMessageByFields(10, Config.NODE_IP_ADDRESS, str(len(self.nodes))) elif r_type==2: #conn req for this machine to_be_replied=1 reply_pac = self.confirmConnectionRequest(pac) elif r_type==3: # a path query... to_be_replied=0 #first unset the reply flag... target_ip = Converter.get_decoded_ip(pac.getPayload()[:4]) if target_ip==Config.NODE_IP_ADDRESS: #which means the target node has reached... reply_pac.setMessageByFields(5, target_ip, target_ip+pac.getPayload()[4:]) else: #check if this has already been seen... if pac.getIPAddress()+target_ip in self.query_cache: continue #increment the hop count by '1'... dat = ord(pac.getPayload()[4:]) + 1 #form a packet to forward it... reply_pac.setMessageByFields(3, pac.getIPAddress() , target_ip+chr(dat)) path_length = 0 try: path_length = self.path_cache[target_ip] except KeyError: path_length = 0 if path_length==0: #which means we dont have it in the query... #just forward the packet to all the adjacent nodes... #cache the query and path length... self.path_cache[pac.getIPAddress()] = dat #store the hop count b/w src and this node.. self.query_cache[pac.getIPAddress()+target_ip] = '' #start the threads .. so that they delete the content after a time-out... thread.start_new_thread(self.path_cache, (pac.getIPAddress(),)) thread.start_new_thread(self.query_cache, (pac.getIPAddress()+target_ip,)) for node in self.nodes: self.soc.sendto(reply_pac.getRawMessage(), (node, Config.UDP_LISTEN_PORT)) else: #we have the data from the cache.. so use it!.. reply_pac.setMessageByFields(9, Config.NODE_IP_ADDRESS, target_ip+chr(path_length)) elif r_type==4: pac.printSegmentedMessage() #neighbour update ... to_be_replied=0 self.addorRemoveNeighbourToEntity(pac.getIPAddress(), pac.getPayload()) elif r_type==7: to_be_replied=1 reply_pac.setMessageByFields(8, self.ip_address,'') elif r_type==9 or r_type==5: print 'Path Query Reply:' print pac.getPayload() elif r_type==11: #its a voluntary disconnect req print 'Disconnect request to',pac.getPayload() to_be_replied =0 ip_to_conn = pac.getPayload() #del the reference from the entries try: del self.nodes[pac.getIPAddress()] except KeyError: #do nothing fg=1 if ip_to_conn in self.nodes: #don't send the req. if its already #connected continue reply_pac = LinkPacket() reply_pac.setMessageByFields( 2, Config.NODE_IP_ADDRESS, str(-1)) self.soc.sendto(reply_pac.getRawMessage(), (ip_to_conn, Config.UDP_LISTEN_PORT)) if to_be_replied==1:#reply only if needed... self.soc.sendto(reply_pac.getRawMessage(), addr)