Implemented the inundation, strange type error encountered when testing
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2020 by eichhornchen, ÿnérant
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from datetime import datetime
|
||||
from random import randint
|
||||
from random import randint, uniform
|
||||
from typing import Any, Tuple
|
||||
#from ipaddress import IPv6Address
|
||||
from threading import Thread, RLock
|
||||
@ -61,6 +61,7 @@ class Squirrel(Hazelnut):
|
||||
|
||||
self.history = []
|
||||
self.received_messages = dict()
|
||||
self.recent_messages = dict() #of the form [Pkt(DataTLV), date of first reception, dict(neighbour, date of the next send, nb of times it has already been sent)]
|
||||
self.history_pad = curses.newpad(curses.LINES - 2, curses.COLS)
|
||||
self.input_pad = curses.newpad(1, curses.COLS)
|
||||
self.emoji_pad = curses.newpad(18, 12)
|
||||
@ -75,7 +76,7 @@ class Squirrel(Hazelnut):
|
||||
self.activehazelnuts = dict() #of the form [hazelnut, time of last
|
||||
#hello, time of last long hello, is symmetric]
|
||||
self.nbNS = 0
|
||||
self.minNS = 3 #minimal number of symetric neighbours a squirrel needs
|
||||
self.minNS = 3 #minimal number of symmetric neighbours a squirrel needs
|
||||
#to have.
|
||||
|
||||
self.add_system_message(f"Listening on {self.address}:{self.port}")
|
||||
@ -294,18 +295,93 @@ class Squirrel(Hazelnut):
|
||||
if self.last_line == len(self.history) - 2:
|
||||
self.last_line += 1
|
||||
|
||||
def receive_message_from(self, msg: str, sender_id: int, nonce: int) -> bool:
|
||||
def receive_message_from(self, tlv: DataTLV, msg: str, sender_id: int, nonce: int, relay: Hazelnut) -> bool:
|
||||
"""
|
||||
This method is called by a DataTLV, sent by a real person.
|
||||
This add the message in the history if not already done.
|
||||
Returns True iff the message was not already received previously.
|
||||
"""
|
||||
if (sender_id, nonce) not in self.recent_messages:
|
||||
#If it is a new message, add it to recent_messages
|
||||
d = self.make_inundation_dict()
|
||||
pkt = Packet().construct(tlv)
|
||||
self.recent_messages[(sender_id, nonce)] = [pkt, time.time(), d]
|
||||
|
||||
#in all cases, remove the sender from the list of neighbours to be inundated
|
||||
self.remove_from_inundation(relay, sender_id, nonce)
|
||||
|
||||
if (sender_id, nonce) in self.received_messages:
|
||||
return False
|
||||
|
||||
self.add_message(msg)
|
||||
self.add_message(msg) #for display purposes
|
||||
self.received_messages[(sender_id, nonce)] = Message(msg, sender_id, nonce)
|
||||
return True
|
||||
|
||||
def make_inundation_dict(self) -> dict:
|
||||
"""
|
||||
Takes the activehazels dictionnary and returns a list of [hazel, date+random, 0]
|
||||
"""
|
||||
res = dict()
|
||||
l = list(self.activehazelnuts.items())
|
||||
for key, hazel in l:
|
||||
if hazel[3]: #Only if the neighbour is symmetric
|
||||
next_send = uniform(1, 2)
|
||||
res[key] = [hazel[0], time.time()+next_send, 0]
|
||||
return res
|
||||
|
||||
def remove_from_inundation(self, hazel: Hazelnut, sender_id: int, nonce: int) -> None:
|
||||
"""
|
||||
Remove the sender from the list of neighbours to be inundated
|
||||
"""
|
||||
if (sender_id, nonce) in self.recent_messages:
|
||||
#If a peer is late in its acknowledgement, the absence of the previous if causes an error.
|
||||
self.recent_messages[(sender_id, nonce)][2].pop((hazel.address, hazel.port), None)
|
||||
|
||||
if not self.recent_messages[(sender_id, nonce)][2] : #If dictionnary is empty, remove the message
|
||||
self.recent_messages.pop((sender_id, nonce), None)
|
||||
|
||||
def clean_inundation(self):
|
||||
"""
|
||||
Remove messages which are overdue (older than 2 minutes) from the inundation dictionnary.
|
||||
"""
|
||||
self.refresh_lock.acquire()
|
||||
|
||||
for key in self.recent_messages:
|
||||
if time.time()-self.recent_messages[key][1] > 120:
|
||||
self.recent_messages.pop(key)
|
||||
|
||||
self.refresh_lock.release()
|
||||
|
||||
def main_inundation(self):
|
||||
"""
|
||||
The main inundation function.
|
||||
"""
|
||||
self.refresh_lock.acquire()
|
||||
|
||||
for key in self.recent_messages:
|
||||
for key2 in self.recent_messages[key][2]:
|
||||
if time.time()-self.recent_messages[key][2][key2][1] >= 0:
|
||||
#send the packet if it is overdue
|
||||
self.send_packet(self.recent_messages[key][2][key2][0], self.recent_messages[key][0])
|
||||
|
||||
a = self.recent_messages[key][2][key2][2]
|
||||
|
||||
if a==5: #the neighbour is not reactive enough
|
||||
gatlv = GoAwayTLV().construct(GoAwayType.TIMEOUT, "No acknowledge")
|
||||
pkt = Packet().construct(gatlv)
|
||||
self.send_packet(
|
||||
self.recent_messages[key][2][key2][0], pkt)
|
||||
self.activehazelnuts.pop(key2)
|
||||
self.potentialhazelnuts[key2] = self.recent_messages[key][2][key2][0]
|
||||
self.recent_messages[key][2].pop(key2)
|
||||
|
||||
#change the time until the next send
|
||||
self.recent_messages[key][2][key2][2] = a+1
|
||||
next_send = uniform(2**(a-1), 2**a)
|
||||
self.recent_messages[key][2][key2][1] = time.time()+next_send
|
||||
|
||||
|
||||
self.refresh_lock.release()
|
||||
|
||||
def add_system_message(self, msg: str) -> None:
|
||||
"""
|
||||
@ -649,6 +725,11 @@ class Inondator(Thread):
|
||||
|
||||
def run(self) -> None:
|
||||
while True:
|
||||
#clean the dictionnary
|
||||
self.squirrel.clean_inundation()
|
||||
|
||||
#inundate
|
||||
self.squirrel.main_inundation()
|
||||
|
||||
|
||||
class Message:
|
||||
|
Reference in New Issue
Block a user