mirror of
https://git.ugnet.gay/CrossTalk/azul.git
synced 2026-05-27 22:59:49 +00:00
production init
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import asyncio
|
||||
import struct
|
||||
import settings
|
||||
|
||||
from core.backend import Backend
|
||||
from typing import Optional, Callable
|
||||
from threading import Thread
|
||||
from util.misc import Logger, ProtocolRunner
|
||||
|
||||
from .ctrl import OSCARCtrl
|
||||
from .proto.snac import SNACMessage
|
||||
|
||||
|
||||
def register(loop: asyncio.AbstractEventLoop, backend: Backend) -> None:
|
||||
backend.add_runner(ProtocolRunner('0.0.0.0', 5190, ListenerOSCAR, args=['OSCAR', backend, OSCARCtrl], service = 'OSCAR'))
|
||||
|
||||
|
||||
class ListenerOSCAR(asyncio.Protocol):
|
||||
logger: Logger
|
||||
backend: Backend
|
||||
controller: OSCARCtrl
|
||||
transport: Optional[asyncio.WriteTransport]
|
||||
|
||||
buffer: bytes = b''
|
||||
data_thread: Thread = None
|
||||
|
||||
def __init__(self,
|
||||
logger_prefix: str,
|
||||
backend: Backend,
|
||||
controller_factory: Callable[[Logger, str, Backend], OSCARCtrl]) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.logger = Logger(logger_prefix, self)
|
||||
self.backend = backend
|
||||
self.controller = controller_factory(self.logger, 'direct', backend)
|
||||
self.controller.close_callback = self._on_close
|
||||
self.transport = None
|
||||
|
||||
def connection_made(self, transport: asyncio.BaseTransport) -> None:
|
||||
self.controller.transport = transport
|
||||
self.controller.on_connect()
|
||||
self.logger.log_connect()
|
||||
|
||||
def connection_lost(self, exc: Optional[Exception]) -> None:
|
||||
self.controller.close()
|
||||
self.logger.log_disconnect()
|
||||
|
||||
def data_received(self, packet: bytes) -> None:
|
||||
if self.backend.maintenance_mode:
|
||||
self.transport.close()
|
||||
return
|
||||
|
||||
self.buffer += packet
|
||||
|
||||
if self.data_thread is None or not self.data_thread.is_alive():
|
||||
self.data_thread = Thread(target=self.parse_buffer)
|
||||
self.data_thread.start()
|
||||
|
||||
def parse_buffer(self) -> None:
|
||||
while True:
|
||||
if self.buffer[0] != 0x2A:
|
||||
break
|
||||
|
||||
# TODO(subpurple): Bufferize this?
|
||||
frame, sequence, length = struct.unpack('>BHH', self.buffer[1:6])
|
||||
|
||||
if len(self.buffer) < length + 6:
|
||||
break
|
||||
|
||||
if len(self.buffer) >= length + 6:
|
||||
data = self.buffer[6:length + 6]
|
||||
|
||||
match frame:
|
||||
# SIGNON
|
||||
case 0x01:
|
||||
self.controller.on_signon_frame(data)
|
||||
|
||||
# DATA (always contains a SNAC)
|
||||
case 0x02:
|
||||
if len(data) < 10:
|
||||
return
|
||||
|
||||
msg = SNACMessage()
|
||||
msg.unmarshal(data)
|
||||
self.controller.on_data_frame(msg)
|
||||
|
||||
# ERROR
|
||||
case 0x03:
|
||||
self.controller.on_error_frame(data)
|
||||
|
||||
# SIGNOFF
|
||||
case 0x04:
|
||||
self.controller.on_signoff_frame(data)
|
||||
|
||||
# KEEP_ALIVE
|
||||
case 0x05:
|
||||
pass
|
||||
|
||||
case _:
|
||||
self.logger.info('Recieved unknown frame:', str(frame), 'with data:', data.hex())
|
||||
|
||||
self.buffer = self.buffer[length + 6:]
|
||||
|
||||
if len(self.buffer) < 6:
|
||||
break
|
||||
|
||||
def _on_close(self) -> None:
|
||||
if self.transport is not None:
|
||||
self.transport.close()
|
||||
Reference in New Issue
Block a user