Merge branch 'commands' into 'master'
Commands See merge request ynerant/squinnondation!8
This commit is contained in:
commit
25e502ab45
|
@ -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
|
||||
|
|
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()
|
||||
|
|
Loading…
Reference in New Issue