def run(self): while self.alive: succ = self.node.get_successor() if succ is not None and isinstance(succ, Address) == False: succ = Address.get_address_from_string(succ) if succ is None or succ == self.node.local_address: self.node.fillsuc() succ = self.node.get_successor() if succ is not None and succ != self.node.local_address: succ_pre_q = queryadd(succ, Message.getjson("get_your_pre")) if succ_pre_q is None: self.node.delete_successor() else: succ_pre = Address.get_address_from_string( succ_pre_q["payload"]) if succ_pre is not None: if succ_pre == succ: self.node.notify(succ) else: succ_offset = find_offset(self.node.id, hashadd(succ)) succ_pre_offset = find_offset( self.node.id, hashadd(succ_pre)) if succ_pre_offset > 0 and succ_pre_offset < succ_offset: self.node.update_ith_finger(1, succ_pre) time.sleep(1)
def join_(self, receiving_node_addr): response = queryadd(receiving_node_addr, Message.getjson("find_succ_for_id", self.id)) if response is not None and response["subject"] == "set_your_succ": self.update_ith_finger( 1, Address.get_address_from_string(response["payload"])) response = queryadd(self.finger_table[1], Message.getjson("get_your_pre")) if response is not None and response["subject"] == "my_pre": self.set_predecessor( Address.get_address_from_string(response["payload"])) self.notify(self.finger_table[1])
def closestprecedfinger(self, search_id): if search_id is None: return search_id_offset = find_offset(self.id, search_id) for i in range(M, 0, -1): ith_finger = self.finger_table[i] if ith_finger is None: continue if isinstance(ith_finger, Address) == False and len(ith_finger) > 10: ith_finger = Address.get_address_from_string(ith_finger) else: continue ith_finger_id = hashadd(ith_finger) ith_finger_offset = find_offset(self.id, ith_finger_id) if ith_finger_offset > 0 and ith_finger_offset < search_id_offset: query = queryadd(ith_finger, Message.getjson("areyoualive")) if query["subject"] == "iamalive": return ith_finger self.finger_table[i] = None return self.local_address
def update_ith_finger(self, pos, address): if isinstance(address, Address) == False and address is not None: address = Address.get_address_from_string(address) if pos == 1: print("Successor for {0} set to id {1}".format( self.id, hashadd(address))) if pos > 0 and pos <= 2**M: self.finger_table[pos] = address
def __eq__(self, other): if self is None or other is None: return False if isinstance(other, Address) == False: if len(other) > 10: other = Address.get_address_from_string(other) else: return False return self.ipv4 == other.ipv4 and self.port == other.port
def hashadd(addr): if addr is None: return None if isinstance(addr, Address) == False and len(addr) > 0: addr = Address.get_address_from_string(addr) s = "{0}:{1}".format(addr.port, addr.ipv4) hash = hashlib.sha1() hash.update(s.encode()) hash_value = int(hash.hexdigest(), 16) return hash_value % (2**M)
def queryadd(address, msg): if address is None or msg is None or len(msg) == 0: return if isinstance(address, Address) == False and len(address) > 0: address = Address.get_address_from_string(address) addr = (address.ipv4, address.port) try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(addr) except Exception: return None return socketquery(sock, msg)
def ask_for_ip_port(self): if self.seed == False: while True: print( "\nEnter the address of the node you wish to join. For example, 'localhost:8433' or '172.32.21.1:64356'." ) print("Hit Return if you are the seed node.") join_addr = input() if len(join_addr) == 0: break elif len(join_addr) > 10: self.join_(Address.get_address_from_string(join_addr)) return else: print("\nInvalid address. Please try again.\n") print( "\nSeed node initialized with address {0} and id {1}. Waiting for other nodes to join the chord network.\n" .format(self.local_address.to_string(), self.id))
def findsucc(self, search_id): if search_id is None: return if search_id == self.id: return self.get_successor() ret = self.get_successor() pre = self.findpredec(search_id) if pre is not None and pre != self.local_address: ret_q = queryadd(pre, Message.getjson("get_your_succ")) if ret_q is not None and ret_q["subject"] == "my_succ": ret = Address.get_address_from_string(ret_q["payload"]) if ret is None: ret = self.local_address return ret
def handle_message(self, msg): msg_dict = Message.parse_message(msg) subject = msg_dict["subject"] payload = msg_dict["payload"] result = "" if subject == "find_succ_for_id": successor = self.node.findsucc(payload) result = Message.getjson("set_your_succ", str(successor)) elif subject == "get_your_succ": result = Message.getjson("my_succ", str(self.node.get_successor())) elif subject == "get_your_pre": result = Message.getjson("my_pre", str(self.node.predecessor)) elif subject == "find_closest_p": result = Message.getjson( "closest_p", str(self.node.closestprecedfinger(payload))) elif subject == "i_am_your_pre": addr = Address.get_address_from_string(payload) self.node.notified(addr) return elif subject == "get_your_finger_table": result = Message.getjson("my_finger_table", self.node.finger_table) elif subject == "log": print(str(payload)) return elif subject == "areyoualive": result = Message.getjson("iamalive") else: result = Message.getjson("log", "Invalid command!") sendsock(self.from_socket, result)
def fillsuc(self): succ = self.get_successor() if succ is None or succ == self.local_address: for i in range(2, M + 1): ith_finger = self.finger_table[i] if ith_finger is not None and isinstance( ith_finger, Address) == False and len(ith_finger) > 10: ith_finger = Address.get_address_from_string(ith_finger) if ith_finger is not None and ith_finger != self.local_address: # Push this value "up" in the table for j in range(i - 1, 0, -1): self.update_ith_finger(j, ith_finger) break new_succ = self.get_successor() if ( new_succ is None or new_succ == self.local_address ) and self.predecessor is not None and self.predecessor != self.local_address: self.update_ith_finger(1, self.predecessor) if (self.get_successor() is None and self.predecessor is None): self.update_ith_finger(1, self.local_address)
def findpredec(self, search_id): if search_id is None: return ret = self.local_address ret_succ = self.get_successor() most_recently_alive = self.local_address ret_succ_offset = 0 if ret_succ is not None: ret_succ_offset = find_offset(hashadd(ret), hashadd(ret_succ)) search_id_offset = find_offset(self.id, search_id) while not (search_id_offset > 0 and search_id_offset <= ret_succ_offset): curr_node_temp = ret if ret == self.local_address: ret = self.closestprecedfinger(search_id) else: result_q = queryadd( ret, Message.getjson("find_closest_p", search_id)) if result_q is not None and result_q["subject"] == "closest_p": result = None if result_q[ "payload"] is None else Address.get_address_from_string( result_q["payload"]) else: result = None if result is None: ret = most_recently_alive ret_succ_q = queryadd(ret, Message.getjson("get_your_succ")) ret_succ = Address.get_address_from_string( ret_succ_q["payload"] ) if ret_succ_q is not None and ret_succ_q[ "subject"] == "my_succ" else None if ret_succ is None: return self.local_address continue elif result == ret: return result else: most_recently_alive = ret ret_succ_q = queryadd(result, Message.getjson("get_your_succ")) ret_succ = Address.get_address_from_string( ret_succ_q["payload"]) if ret_succ is not None: ret = result else: ret_succ_q = queryadd(ret, Message.getjson("get_your_succ")) ret_succ = Address.get_address_from_string( ret_succ_q["payload"]) ret_succ_offset = find_offset(hashadd(ret), hashadd(ret_succ)) search_id_offset = find_offset(hashadd(ret), search_id) if curr_node_temp == ret: break return ret