diff --git a/squinnondation/hazel.py b/squinnondation/hazel.py index 7b173f0..e258d90 100644 --- a/squinnondation/hazel.py +++ b/squinnondation/hazel.py @@ -21,6 +21,9 @@ class Hazelnut: def __init__(self, nickname: str = None, address: str = "localhost", port: int = 2500): self.nickname = nickname self.id = -1 + self.last_hello_time = 0 + self.last_long_hello_time = 0 + self.symmetric = False try: # Resolve DNS as an IPv6 @@ -75,11 +78,14 @@ class Squirrel(Hazelnut): # dictionnaries of neighbours self.potentialhazelnuts = dict() - self.activehazelnuts = dict() # of the form [hazelnut, time of last hello, - # time of last long hello, is symmetric] + self.activehazelnuts = dict() self.nbNS = 0 self.minNS = 3 # minimal number of symmetric neighbours a squirrel needs to have. + self.worm = Worm(self) + self.hazel_manager = HazelManager(self) + self.inondator = Inondator(self) + self.add_system_message(f"Listening on {self.address}:{self.port}") self.add_system_message(f"I am {self.id}") @@ -105,7 +111,7 @@ class Squirrel(Hazelnut): creates a new hazelnut. """ if (address, port) in self.activehazelnuts: - return self.activehazelnuts[(address, port)][0] + return self.activehazelnuts[(address, port)] hazelnut = Hazelnut(address=address, port=port) return hazelnut @@ -148,10 +154,6 @@ class Squirrel(Hazelnut): """ Start asynchronous threads. """ - self.worm = Worm(self) - self.hazel_manager = HazelManager(self) - self.inondator = Inondator(self) - # Kill subthreads when exitting the program self.worm.setDaemon(True) self.hazel_manager.setDaemon(True) @@ -260,7 +262,7 @@ class Squirrel(Hazelnut): pkt = Packet.construct(DataTLV.construct(msg, self)) for hazelnut in list(self.activehazelnuts.values()): - self.send_packet(hazelnut[0], pkt) + self.send_packet(hazelnut, pkt) def handle_mouse_click(self, y: int, x: int, attr: int) -> None: """ @@ -346,9 +348,9 @@ class Squirrel(Hazelnut): res = dict() hazels = list(self.activehazelnuts.items()) for key, hazel in hazels: - if hazel[3]: # Only if the neighbour is symmetric + if hazel.symmetric: next_send = uniform(1, 2) - res[key] = [hazel[0], time.time() + next_send, 0] + res[key] = [hazel, time.time() + next_send, 0] return res def remove_from_inundation(self, hazel: Hazelnut, sender_id: int, nonce: int) -> None: @@ -626,9 +628,9 @@ class Squirrel(Hazelnut): self.refresh_lock.acquire() for hazelnut in self.activehazelnuts.values(): - htlv = HelloTLV().construct(16, self, hazelnut[0]) + htlv = HelloTLV().construct(16, self, hazelnut) pkt = Packet().construct(htlv) - self.send_packet(hazelnut[0], pkt) + self.send_packet(hazelnut, pkt) self.refresh_lock.release() @@ -642,12 +644,12 @@ class Squirrel(Hazelnut): val = list(self.activehazelnuts.values()) # create a copy because the dict size will change for hazelnut in val: - if time.time() - hazelnut[1] > 2 * 60: + if time.time() - hazelnut.last_hello_time > 2 * 60: gatlv = GoAwayTLV().construct(GoAwayType.TIMEOUT, "you did not talk to me") pkt = Packet().construct(gatlv) - self.send_packet(hazelnut[0], pkt) - self.activehazelnuts.pop((hazelnut[0].address, hazelnut[0].port)) - self.potentialhazelnuts[(hazelnut[0].address, hazelnut[0].port)] = hazelnut[0] + self.send_packet(hazelnut, pkt) + self.activehazelnuts.pop((hazelnut.address, hazelnut.port)) + self.potentialhazelnuts[(hazelnut.address, hazelnut.port)] = hazelnut self.refresh_lock.release() @@ -662,16 +664,16 @@ class Squirrel(Hazelnut): # could send the same to all neighbour, but it means that neighbour # A could receive a message with itself in it -> if the others do not pay attention, trouble for key, hazelnut in self.activehazelnuts.items(): - if time.time() - hazelnut[2] <= 2 * 60: + if time.time() - hazelnut.last_long_hello_time <= 2 * 60: nb_ns += 1 - self.activehazelnuts[key][3] = True - ntlv = NeighbourTLV().construct(hazelnut[0].address, hazelnut[0].port) + self.activehazelnuts[key].symmetric = True + ntlv = NeighbourTLV().construct(hazelnut.address, hazelnut.port) pkt = Packet().construct(ntlv) for destination in self.activehazelnuts.values(): - if destination[0].id != hazelnut[0].id: - self.send_packet(destination[0], pkt) + if destination.id != hazelnut.id: + self.send_packet(destination, pkt) else: - self.activehazelnuts[key][3] = False + self.activehazelnuts[key].symmetric = False self.nbNS = nb_ns self.refresh_lock.release() @@ -690,7 +692,7 @@ class Squirrel(Hazelnut): gatlv = GoAwayTLV().construct(GoAwayType.EXIT, "I am leaving! Good bye!") pkt = Packet.construct(gatlv) for hazelnut in self.activehazelnuts.values(): - self.send_packet(hazelnut[0], pkt) + self.send_packet(hazelnut, pkt) exit(0) diff --git a/squinnondation/messages.py b/squinnondation/messages.py index d6157a4..3ab31d3 100644 --- a/squinnondation/messages.py +++ b/squinnondation/messages.py @@ -163,7 +163,7 @@ class HelloTLV(TLV): sender.id = self.source_id # The sender we are given misses an id time_hl = time.time() else: - time_hl = squirrel.activehazelnuts[(sender.address, sender.port)][2] + time_hl = sender.last_long_hello_time if self.is_long and self.dest_id == squirrel.id: time_hl = time.time() @@ -171,7 +171,10 @@ class HelloTLV(TLV): squirrel.remove_from_potential(sender.address, sender.port) # Add entry to/actualize the active hazelnuts dictionnary - squirrel.activehazelnuts[(sender.address, sender.port)] = [sender, time_h, time_hl, True] + sender.last_hello_time = time_h + sender.last_long_hello_time = time_hl + sender.symmetric = True + squirrel.activehazelnuts[(sender.address, sender.port)] = sender squirrel.nbNS += 1 # squirrel.add_system_message(f"Aaaawwww, {self.source_id} spoke to me and said Hello " # + ("long" if self.is_long else "short")) diff --git a/squinnondation/squinnondation.py b/squinnondation/squinnondation.py index 22c9999..be8f09d 100644 --- a/squinnondation/squinnondation.py +++ b/squinnondation/squinnondation.py @@ -78,13 +78,10 @@ class Squinnondation: if instance.args.client_address and instance.args.client_port: hazelnut = Hazelnut(address=instance.args.client_address, port=instance.args.client_port) + squirrel.potentialhazelnuts[instance.args.client_address, instance.args.client_port] = hazelnut htlv = HelloTLV().construct(8, squirrel) pkt = Packet().construct(htlv) squirrel.send_packet(hazelnut, pkt) - # if squirrel.port != 8082: - # hazelnut = Hazelnut(address='::1', port=8082) - # squirrel.potentialhazelnuts['::1', 8082] = hazelnut - squirrel.start_threads() squirrel.wait_for_key()