splitted the manager into an event and role manager

This commit is contained in:
study-faraphel 2025-01-03 22:51:08 +01:00
parent c825ef8bef
commit 2286375bae
12 changed files with 125 additions and 38 deletions

View file

@ -1,15 +1,5 @@
import threading
from source.managers import Manager from source.managers import Manager
manager = Manager("wlp1s0") manager = Manager("wlp1s0")
manager.loop()
thread_receive = threading.Thread(target=manager.receiveLoop)
thread_send = threading.Thread(target=manager.sendLoop)
thread_receive.start()
thread_send.start()
thread_receive.join()
thread_send.join()

View file

@ -3,5 +3,5 @@ from source import packets
class DiscoveryEvent(base.BaseEvent): class DiscoveryEvent(base.BaseEvent):
def handle(self, packet: packets.DiscoveryPacket): def handle(self, packet: packets.DiscoveryPacket, address: tuple):
pass print("discovery event !")

View file

@ -0,0 +1,3 @@
from . import base
from .DiscoveryEvent import DiscoveryEvent

View file

@ -1,5 +1,13 @@
import abc import abc
from source import packets
class BaseEvent(abc.ABC): class BaseEvent(abc.ABC):
pass @abc.abstractmethod
def handle(self, packet: packets.base.BasePacket, address: tuple) -> None:
"""
Handle a packet
:param packet: the packet to handle
:param address: the address of the machine that sent the packet
"""

View file

@ -4,6 +4,6 @@ from source import managers, packets
class UndefinedRole(base.BaseRole): class UndefinedRole(base.BaseRole):
def run(self, manager: "managers.Manager"): def handle(self, manager: "managers.Manager"):
packet = packets.DiscoveryPacket() packet = packets.DiscoveryPacket()
manager.communication.broadcast(packet) manager.communication.broadcast(packet)

View file

@ -1 +1,2 @@
from . import base
from .UndefinedRole import UndefinedRole from .UndefinedRole import UndefinedRole

View file

@ -5,7 +5,7 @@ from source import managers
class BaseRole(abc.ABC): class BaseRole(abc.ABC):
@abc.abstractmethod @abc.abstractmethod
def run(self, manager: "managers.Manager") -> None: def handle(self, manager: "managers.Manager") -> None:
""" """
Behavior of the role Behavior of the role
""" """

View file

@ -5,6 +5,7 @@ import zlib
import bidict import bidict
from source import packets from source import packets
from source.managers import Manager
from source.utils.crypto.type import CipherType from source.utils.crypto.type import CipherType
@ -13,7 +14,9 @@ class CommunicationManager:
Manage everything about communication Manage everything about communication
""" """
def __init__(self, interface: str, broadcast_address: str = "ff02::1", port: int = 5555): def __init__(self, manager: "Manager", interface: str, broadcast_address: str = "ff02::1", port: int = 5555):
self.manager = manager
self.broadcast_address = broadcast_address self.broadcast_address = broadcast_address
self.port = port self.port = port
@ -59,7 +62,7 @@ class CommunicationManager:
# get the header identifier of the type of this packet # get the header identifier of the type of this packet
header: typing.Optional[bytes] = self.packet_types.inverse.get(type(packet)) header: typing.Optional[bytes] = self.packet_types.inverse.get(type(packet))
if header is None: if header is None:
raise Exception(f"Unrecognised packet type: {type(packet)}. Has it been registered ?") raise KeyError(f"Unrecognised packet type: {type(packet)}. Has it been registered ?")
# get the encoded packet data # get the encoded packet data
data = packet.pack() data = packet.pack()
@ -88,7 +91,7 @@ class CommunicationManager:
# get the type of the packet from its header # get the type of the packet from its header
packet_type: typing.Optional[typing.Type[packets.base.BasePacket]] = self.packet_types.get(header) packet_type: typing.Optional[typing.Type[packets.base.BasePacket]] = self.packet_types.get(header)
if header is None: if header is None:
raise Exception(f"Unrecognised packet header: {header}. Has it been registered ?") raise KeyError(f"Unrecognised packet header: {header}. Has it been registered ?")
# unpack the packet # unpack the packet
return packet_type.unpack(data) return packet_type.unpack(data)

View file

@ -0,0 +1,53 @@
import typing
import warnings
from source import packets
from source.behaviors import events
from source.managers import Manager
class EventManager:
def __init__(self, manager: "Manager"):
self.manager = manager
# events
self.event_handlers: dict[typing.Type[packets.base.BasePacket], events.base.BaseEvent] = {}
def register_event_handler(self, packet_type: typing.Type[packets.base.BasePacket], event: events.base.BaseEvent) -> None:
"""
Register a new event to react to a specific packet type
:param packet_type: the type of packet to listen to
:param event: the event handler
"""
self.event_handlers[packet_type] = event
def handle(self, packet: packets.base.BasePacket, address: tuple) -> None:
"""
Handle the packet received
:param packet: the packet to handle
:param address: the address of the machine that sent the packet
"""
# get the event handler of this kind of packet
event_handler = self.event_handlers.get(type(packet))
if event_handler is None:
raise KeyError(f"Unrecognised packet type: {type(packet)}. Has it been registered ?")
# use the event handler on the packet
event_handler.handle(packet, address)
def loop(self):
while True:
try:
# wait for a new packet
packet, address = self.manager.communication.receive()
print(f"Received message from {address}: {packet}")
# give it to the event handler
self.manager.event.handle(packet, address)
except KeyboardInterrupt:
print("Stopping listener.")
except Exception as exception:
warnings.warn(str(exception))

View file

@ -1,30 +1,31 @@
from . import CommunicationManager import threading
from source import packets from source import packets
from source.behaviors import roles from source.behaviors import events
class Manager: class Manager:
def __init__(self, interface: str): def __init__(self, interface: str):
self.communication = CommunicationManager(interface) from . import CommunicationManager, EventManager, RoleManager
# communication manager
self.communication = CommunicationManager(self, interface)
self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket) self.communication.register_packet_type(b"DISC", packets.DiscoveryPacket)
# define the role of our machine # event manager
# TODO(Faraphel): give the manager to the role directly ? register ? self.event = EventManager(self)
self.role = roles.UndefinedRole() self.event.register_event_handler(packets.DiscoveryPacket, events.DiscoveryEvent())
# role manager
self.role = RoleManager(self)
def sendLoop(self): def loop(self):
while True: # run a thread for the event and the role manager
self.role.run(self) event_thread = threading.Thread(target=self.event.loop)
role_thread = threading.Thread(target=self.role.loop)
def receiveLoop(self): event_thread.start()
try: role_thread.start()
while True:
packet, address = self.communication.receive()
print(f"Received message from {address}: {packet}")
# get corresponding event event_thread.join()
# handle it role_thread.join()
except KeyboardInterrupt:
print("Stopping listener.")

View file

@ -0,0 +1,25 @@
from source.behaviors import roles
from source.managers import Manager
class RoleManager:
def __init__(self, manager: "Manager"):
self.manager = manager
# the currently used role
self.current: roles.base.BaseRole = roles.UndefinedRole()
def handle(self) -> None:
"""
Run the role
"""
self.current.handle(self.manager)
def loop(self) -> None:
"""
Handle forever
"""
while True:
self.handle()

View file

@ -1,2 +1,5 @@
from .CommunicationManager import CommunicationManager from .CommunicationManager import CommunicationManager
from .EventManager import EventManager
from .RoleManager import RoleManager
from .Manager import Manager from .Manager import Manager