Merge branch 'commands' into 'master'
Commands See merge request ynerant/squinnondation!8
This commit is contained in:
		@@ -36,9 +36,9 @@ class TLV:
 | 
			
		||||
        """
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Indicates what to do when this TLV is received from a given hazel.
 | 
			
		||||
        Indicates what to do when this TLV is received from a given peer.
 | 
			
		||||
        It is ensured that the data is valid.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
@@ -72,14 +72,14 @@ class Pad1TLV(TLV):
 | 
			
		||||
        """
 | 
			
		||||
        return self.type.to_bytes(1, sys.byteorder)
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your Pad1TLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        squirrel.add_system_message("I received a Pad1TLV, how disapointing.")
 | 
			
		||||
        user.add_system_message("I received a Pad1TLV, how disapointing.")
 | 
			
		||||
 | 
			
		||||
    def __len__(self) -> int:
 | 
			
		||||
        """
 | 
			
		||||
@@ -122,14 +122,14 @@ class PadNTLV(TLV):
 | 
			
		||||
        return self.type.to_bytes(1, sys.byteorder) + self.length.to_bytes(1, sys.byteorder) \
 | 
			
		||||
            + self.mbz[:self.length]
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your PadNTLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        squirrel.add_system_message(f"I received {self.length} zeros.")
 | 
			
		||||
        user.add_system_message(f"I received {self.length} zeros.")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(length: int) -> "PadNTLV":
 | 
			
		||||
@@ -166,45 +166,48 @@ class HelloTLV(TLV):
 | 
			
		||||
            data += self.dest_id.to_bytes(8, sys.byteorder)
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        time_h = time.time()
 | 
			
		||||
 | 
			
		||||
        if sender.id > 0 and sender.id != self.source_id:
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                f"You were known as the ID {sender.id}, but you declared that you have the ID {self.source_id}.")))
 | 
			
		||||
            squirrel.add_system_message(f"A client known as the id {sender.id} declared that it uses "
 | 
			
		||||
            user.add_system_message(f"A client known as the id {sender.id} declared that it uses "
 | 
			
		||||
                                        f"the id {self.source_id}.")
 | 
			
		||||
            sender.id = self.source_id
 | 
			
		||||
 | 
			
		||||
        if self.source_id == user.id:
 | 
			
		||||
            sender.marked_as_banned = True
 | 
			
		||||
 | 
			
		||||
        if not sender.active:
 | 
			
		||||
            sender.id = self.source_id  # The sender we are given misses an id
 | 
			
		||||
            time_hl = time.time()
 | 
			
		||||
        else:
 | 
			
		||||
            time_hl = sender.last_long_hello_time
 | 
			
		||||
        if self.is_long and self.dest_id == squirrel.id:
 | 
			
		||||
        if self.is_long and self.dest_id == user.id:
 | 
			
		||||
            time_hl = time.time()
 | 
			
		||||
 | 
			
		||||
        # Add entry to/actualize the active hazelnuts dictionnary
 | 
			
		||||
        # Add entry to/actualize the active peers dictionnary
 | 
			
		||||
        sender.last_hello_time = time_h
 | 
			
		||||
        sender.last_long_hello_time = time_hl
 | 
			
		||||
        sender.symmetric = True
 | 
			
		||||
        sender.active = True
 | 
			
		||||
        squirrel.update_hazelnut_table(sender)
 | 
			
		||||
        squirrel.nbNS += 1
 | 
			
		||||
        squirrel.add_system_message(f"{self.source_id} sent me a Hello " + ("long" if self.is_long else "short"))
 | 
			
		||||
        user.update_peer_table(sender)
 | 
			
		||||
        user.nbNS += 1
 | 
			
		||||
        user.add_system_message(f"{self.source_id} sent me a Hello " + ("long" if self.is_long else "short"))
 | 
			
		||||
 | 
			
		||||
        if not self.is_long:
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(HelloTLV.construct(16, squirrel, sender)))
 | 
			
		||||
            user.send_packet(sender, Packet.construct(HelloTLV.construct(16, user, sender)))
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_long(self) -> bool:
 | 
			
		||||
        return self.length == 16
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(length: int, squirrel: Any, destination: Any = None) -> "HelloTLV":
 | 
			
		||||
    def construct(length: int, user: Any, destination: Any = None) -> "HelloTLV":
 | 
			
		||||
        tlv = HelloTLV()
 | 
			
		||||
        tlv.type = 2
 | 
			
		||||
        tlv.source_id = squirrel.id if squirrel else 0
 | 
			
		||||
        tlv.source_id = user.id if user else 0
 | 
			
		||||
        if (destination is None) or destination.id == -1 or length == 8:
 | 
			
		||||
            tlv.length = 8
 | 
			
		||||
            tlv.dest_id = None  # if the destination id is not known, or
 | 
			
		||||
@@ -238,28 +241,28 @@ class NeighbourTLV(TLV):
 | 
			
		||||
            self.ip_address.packed + \
 | 
			
		||||
            self.port.to_bytes(2, sys.byteorder)
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your NeighbourTLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if (self.ip_address, self.port) in squirrel.addresses:
 | 
			
		||||
        if (self.ip_address, self.port) in user.addresses:
 | 
			
		||||
            # This case should never happen (and in our protocol it is not possible),
 | 
			
		||||
            # but we include this test as a security measure.
 | 
			
		||||
            return
 | 
			
		||||
        if not (str(self.ip_address), self.port) in squirrel.hazelnuts:
 | 
			
		||||
            hazelnut = squirrel.new_hazel(str(self.ip_address), self.port)
 | 
			
		||||
            hazelnut.potential = True
 | 
			
		||||
            squirrel.update_hazelnut_table(hazelnut)
 | 
			
		||||
        # squirrel.add_system_message(f"New potential friend {self.ip_address}:{self.port}!")
 | 
			
		||||
        if not (str(self.ip_address), self.port) in user.neighbours:
 | 
			
		||||
            peer = user.new_peer(str(self.ip_address), self.port)
 | 
			
		||||
            peer.potential = True
 | 
			
		||||
            user.update_peer_table(peer)
 | 
			
		||||
        # user.add_system_message(f"New potential friend {self.ip_address}:{self.port}!")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(address: str, port: int) -> "NeighbourTLV":
 | 
			
		||||
        tlv = NeighbourTLV()
 | 
			
		||||
        tlv.type = 3
 | 
			
		||||
        tlv.length = 18  # A priori...
 | 
			
		||||
        tlv.length = 18
 | 
			
		||||
        tlv.ip_address = IPv6Address(address)
 | 
			
		||||
        tlv.port = port
 | 
			
		||||
        return tlv
 | 
			
		||||
@@ -291,53 +294,53 @@ class DataTLV(TLV):
 | 
			
		||||
            socket.htonl(self.nonce).to_bytes(4, sys.byteorder) + \
 | 
			
		||||
            self.data
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        A message has been sent. We log it.
 | 
			
		||||
        """
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your DataTLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        msg = self.data.decode('UTF-8')
 | 
			
		||||
 | 
			
		||||
        # Acknowledge the packet
 | 
			
		||||
        squirrel.send_packet(sender, Packet.construct(AckTLV.construct(self.sender_id, self.nonce)))
 | 
			
		||||
        user.send_packet(sender, Packet.construct(AckTLV.construct(self.sender_id, self.nonce)))
 | 
			
		||||
 | 
			
		||||
        if not squirrel.receive_message_from(self, msg, self.sender_id, self.nonce, sender):
 | 
			
		||||
        if not user.receive_message_from(self, msg, self.sender_id, self.nonce, sender):
 | 
			
		||||
            # The message was already received, do not print it on screen
 | 
			
		||||
            squirrel.add_system_message(f"I was inundated a message which I already knew {self.sender_id, self.nonce}")
 | 
			
		||||
            user.add_system_message(f"I was inundated a message which I already knew {self.sender_id, self.nonce}")
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        nickname_match = re.match("(.*): (.*)", msg)
 | 
			
		||||
        if nickname_match is None:
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "Unable to retrieve your username. Please use the syntax 'nickname: message'")))
 | 
			
		||||
        else:
 | 
			
		||||
            nickname = nickname_match.group(1)
 | 
			
		||||
            author = squirrel.find_hazelnut_by_id(self.sender_id)
 | 
			
		||||
            author = user.find_peer_by_id(self.sender_id)
 | 
			
		||||
            if author:
 | 
			
		||||
                if author.nickname is None:
 | 
			
		||||
                    author.nickname = nickname
 | 
			
		||||
                elif author.nickname != nickname:
 | 
			
		||||
                    squirrel.send_packet(author, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                    user.send_packet(author, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                        "It seems that you used two different nicknames. "
 | 
			
		||||
                        f"Known nickname: {author.nickname}, found: {nickname}")))
 | 
			
		||||
                    author.nickname = nickname
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(message: str, squirrel: Any) -> "DataTLV":
 | 
			
		||||
    def construct(message: str, user: Any) -> "DataTLV":
 | 
			
		||||
        tlv = DataTLV()
 | 
			
		||||
        tlv.type = 4
 | 
			
		||||
        tlv.sender_id = squirrel.id if squirrel else 0
 | 
			
		||||
        tlv.nonce = squirrel.incr_nonce if squirrel else 0
 | 
			
		||||
        tlv.sender_id = user.id if user else 0
 | 
			
		||||
        tlv.nonce = user.incr_nonce if user else 0
 | 
			
		||||
        tlv.data = message.encode("UTF-8")
 | 
			
		||||
        tlv.length = 12 + len(tlv.data)
 | 
			
		||||
 | 
			
		||||
        if squirrel:
 | 
			
		||||
            squirrel.incr_nonce += 1
 | 
			
		||||
        if user:
 | 
			
		||||
            user.incr_nonce += 1
 | 
			
		||||
 | 
			
		||||
        return tlv
 | 
			
		||||
 | 
			
		||||
@@ -360,18 +363,18 @@ class AckTLV(TLV):
 | 
			
		||||
            self.sender_id.to_bytes(8, sys.byteorder) + \
 | 
			
		||||
            socket.htonl(self.nonce).to_bytes(4, sys.byteorder)
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        When an AckTLV is received, we know that we do not have to inundate that neighbour anymore.
 | 
			
		||||
        """
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your AckTLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        squirrel.add_system_message(f"I received an AckTLV from {sender}")
 | 
			
		||||
        squirrel.remove_from_inundation(sender, self.sender_id, self.nonce)
 | 
			
		||||
        user.add_system_message(f"I received an AckTLV from {sender}")
 | 
			
		||||
        user.remove_from_inundation(sender, self.sender_id, self.nonce)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(sender_id: int, nonce: int) -> "AckTLV":
 | 
			
		||||
@@ -408,17 +411,17 @@ class GoAwayTLV(TLV):
 | 
			
		||||
            self.code.value.to_bytes(1, sys.byteorder) + \
 | 
			
		||||
            self.message.encode("UTF-8")[:self.length - 1]
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        if not sender.active or not sender.symmetric or not sender.id:
 | 
			
		||||
            # It doesn't say hello, we don't listen to it
 | 
			
		||||
            squirrel.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
            user.send_packet(sender, Packet.construct(WarningTLV.construct(
 | 
			
		||||
                "You are not my neighbour, I don't listen to your GoAwayTLV. Please say me Hello before.")))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if sender.active:
 | 
			
		||||
            sender.active = False
 | 
			
		||||
            squirrel.update_hazelnut_table(sender)
 | 
			
		||||
        squirrel.add_system_message("Some told me that he went away : " + self.message)
 | 
			
		||||
            user.update_peer_table(sender)
 | 
			
		||||
        user.add_system_message("Some told me that he went away : " + self.message)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def construct(ga_type: GoAwayType, message: str) -> "GoAwayTLV":
 | 
			
		||||
@@ -445,9 +448,9 @@ class WarningTLV(TLV):
 | 
			
		||||
            self.length.to_bytes(1, sys.byteorder) + \
 | 
			
		||||
            self.message.encode("UTF-8")[:self.length]
 | 
			
		||||
 | 
			
		||||
    def handle(self, squirrel: Any, sender: Any) -> None:
 | 
			
		||||
        squirrel.add_message(f"warning: *A client warned you: {self.message}*"
 | 
			
		||||
                             if not squirrel.squinnondation.no_markdown else
 | 
			
		||||
    def handle(self, user: Any, sender: Any) -> None:
 | 
			
		||||
        user.add_message(f"warning: *A client warned you: {self.message}*"
 | 
			
		||||
                             if not user.squinnondation.no_markdown else
 | 
			
		||||
                             f"warning: A client warned you: {self.message}")
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1114
									
								
								squinnondation/peers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1114
									
								
								squinnondation/peers.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -5,7 +5,7 @@ import curses
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
from .hazel import Hazelnut, Squirrel
 | 
			
		||||
from .peers import Peer, User
 | 
			
		||||
from .messages import Packet, HelloTLV
 | 
			
		||||
from .term_manager import TermManager
 | 
			
		||||
 | 
			
		||||
@@ -59,28 +59,28 @@ class Squinnondation:
 | 
			
		||||
            nickname = screen.getstr(225).decode("UTF-8")  # Limit nickname length to be included in a DataTLV
 | 
			
		||||
            curses.noecho()
 | 
			
		||||
 | 
			
		||||
            squirrel = Squirrel(instance, nickname)
 | 
			
		||||
            user = User(instance, nickname)
 | 
			
		||||
 | 
			
		||||
            if not squirrel.squinnondation.no_emoji:
 | 
			
		||||
            if not user.squinnondation.no_emoji:
 | 
			
		||||
                # Check that the emoji lib is installed
 | 
			
		||||
                try:
 | 
			
		||||
                    import emoji
 | 
			
		||||
                    _ = emoji
 | 
			
		||||
                except ImportError:
 | 
			
		||||
                    squirrel.squinnondation.no_emoji = True
 | 
			
		||||
                    squirrel.add_system_message("Warning: the emoji lib is not installed. The support will be disabled."
 | 
			
		||||
                    user.squinnondation.no_emoji = True
 | 
			
		||||
                    user.add_system_message("Warning: the emoji lib is not installed. The support will be disabled."
 | 
			
		||||
                                                "To use them, please consider to install the emoji package.")
 | 
			
		||||
 | 
			
		||||
            squirrel.refresh_history()
 | 
			
		||||
            squirrel.refresh_input()
 | 
			
		||||
            user.refresh_history()
 | 
			
		||||
            user.refresh_input()
 | 
			
		||||
            if not instance.no_emoji:
 | 
			
		||||
                squirrel.refresh_emoji_pad()
 | 
			
		||||
                user.refresh_emoji_pad()
 | 
			
		||||
 | 
			
		||||
            if instance.args.client_address and instance.args.client_port:
 | 
			
		||||
                hazelnut = Hazelnut(address=instance.args.client_address, port=instance.args.client_port)
 | 
			
		||||
                htlv = HelloTLV().construct(8, squirrel)
 | 
			
		||||
                peer = Peer(address=instance.args.client_address, port=instance.args.client_port)
 | 
			
		||||
                htlv = HelloTLV().construct(8, user)
 | 
			
		||||
                pkt = Packet().construct(htlv)
 | 
			
		||||
                squirrel.send_packet(hazelnut, pkt)
 | 
			
		||||
                user.send_packet(peer, pkt)
 | 
			
		||||
 | 
			
		||||
            squirrel.start_threads()
 | 
			
		||||
            squirrel.wait_for_key()
 | 
			
		||||
            user.start_threads()
 | 
			
		||||
            user.wait_for_key()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user