class Node(Thread): def __init__(self, ip_addr, port, connect_to=None, seed=False): Thread.__init__(self) self.local_address = Address(ip_addr, port) self.seed = seed self.id = hashadd(self.local_address) print("\nNode initialized with id {0} at address {1}\n".format( self.id, self.local_address.to_string())) self.set_predecessor(self.local_address) self.init_finger_table() self.listener = Listener(self) self.stabilizer = Stabilize(self) self.finger_fixer = FixFingers(self) self.predecessor_stabilizer = CheckPredecessor(self) self.contact_addr = connect_to self.file = filesList def __del__(self): if self.listener is not None: self.listener.die() if self.stabilizer is not None: self.stabilizer.die() if self.finger_fixer is not None: self.finger_fixer.die() if self.predecessor_stabilizer is not None: self.predecessor_stabilizer.die() def get_id_dict(self): return {"id": self.id, "local_address": str(self.local_address)} 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 run(self): self.listener.start() if self.contact_addr is None: self.ask_for_ip_port() else: self.join_(self.contact_addr) self.stabilizer.start() self.finger_fixer.start() self.predecessor_stabilizer.start() def init_finger_table(self): self.finger_table = dict() for i in range(1, M + 1): self.finger_table[i] = None self.update_ith_finger(1, self.local_address) 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 set_predecessor(self, addr): self.predecessor = addr print("Predecessor for {0} set to id {1}".format( self.id, hashadd(addr))) 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 get_successor(self): return self.finger_table[1] def delete_successor(self): succ = self.get_successor() if succ is None: return i = M for i in range(i, 0, -1): ith_finger = self.finger_table[i] if ith_finger is not None and ith_finger == succ: break for j in range(i, 0, -1): self.update_ith_finger(j, None) if self.predecessor is not None and self.predecessor == succ: self.set_predecessor(None) self.fillsuc() 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: pre = self.predecessor pre_pre = None while True: pre_pre = queryadd(pre, "get_your_pre") if pre_pre is not None and pre_pre["payload"] is None: break if pre_pre == pre or pre_pre == self.local_address or pre_pre == new_succ: break else: pre = pre_pre self.update_ith_finger(1, pre) 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 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 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 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 __eq__(self, other): return self.local_address == other.local_address def __hash__(self): return hash(id(self)) def notify(self, successor_addr): if successor_addr != self.local_address: addresssend( successor_addr, Message.getjson("i_am_your_pre", str(self.local_address))) def notified(self, new_pre_addr): if self.predecessor is None or self.predecessor == self.local_address: self.set_predecessor(new_pre_addr) else: old_pre_id = hashadd(self.predecessor) this_id_offset = find_offset(old_pre_id, self.id) new_pre_offset = find_offset(old_pre_id, hashadd(new_pre_addr)) if new_pre_offset > 0 and new_pre_offset < this_id_offset: self.set_predecessor(new_pre_addr) def sendFile(self, filename, hashValue, port): global filesList infoStr = filename + ":" + str(hashValue) soc = socket.socket() try: soc.connect(('127.0.0.1', port)) send = "-f:" + infoStr send = send.encode() soc.send(send) time.sleep(0.2) msg = soc.recv(1024) msg = msg.decode("utf-8") if (msg == "done"): f = open(filename, "rb") l = f.read(1024) while (l): soc.send(l) l = f.read(1024) finally: soc.close() def Filehash(filename): hash = hashlib.md5(filename.encode()) Hash2 = hash.hexdigest() value = int(Hash2, 16) value = value % 9000 filehash = int(value) return filehash def requestFile(port, filename): global filesList soc = socket.socket() try: soc.connect(('127.0.0.1', port)) send = "-r:" + filename send = send.encode() soc.send(send) time.sleep(0.2) f = open(filename, 'wb') i = 0 while (i): l = soc.recv(1024) f.write(l) if ((i % 100) == 0): spr = spr + "." print(spr) if not l: break i = i + 1 f.close() finally: soc.close()