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
manager = Manager("wlp1s0")
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()
manager.loop()

View file

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

View file

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

View file

@ -1,5 +1,13 @@
import abc
from source import packets
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):
def run(self, manager: "managers.Manager"):
def handle(self, manager: "managers.Manager"):
packet = packets.DiscoveryPacket()
manager.communication.broadcast(packet)

View file

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

View file

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

View file

@ -5,6 +5,7 @@ import zlib
import bidict
from source import packets
from source.managers import Manager
from source.utils.crypto.type import CipherType
@ -13,7 +14,9 @@ class CommunicationManager:
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.port = port
@ -59,7 +62,7 @@ class CommunicationManager:
# get the header identifier of the type of this packet
header: typing.Optional[bytes] = self.packet_types.inverse.get(type(packet))
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
data = packet.pack()
@ -88,7 +91,7 @@ class CommunicationManager:
# get the type of the packet from its header
packet_type: typing.Optional[typing.Type[packets.base.BasePacket]] = self.packet_types.get(header)
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
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.behaviors import roles
from source.behaviors import events
class Manager:
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)
# define the role of our machine
# TODO(Faraphel): give the manager to the role directly ? register ?
self.role = roles.UndefinedRole()
# event manager
self.event = EventManager(self)
self.event.register_event_handler(packets.DiscoveryPacket, events.DiscoveryEvent())
# role manager
self.role = RoleManager(self)
def sendLoop(self):
while True:
self.role.run(self)
def loop(self):
# run a thread for the event and the role manager
event_thread = threading.Thread(target=self.event.loop)
role_thread = threading.Thread(target=self.role.loop)
def receiveLoop(self):
try:
while True:
packet, address = self.communication.receive()
print(f"Received message from {address}: {packet}")
event_thread.start()
role_thread.start()
# get corresponding event
# handle it
except KeyboardInterrupt:
print("Stopping listener.")
event_thread.join()
role_thread.join()

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 .EventManager import EventManager
from .RoleManager import RoleManager
from .Manager import Manager