1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-10-23 17:10:24 -04:00

Cleanup of tcpkiss

Removed some unneeded logic based around running.  This
patch just uses the connected attribute instead.
This commit is contained in:
Walter Boring 2025-10-10 10:58:44 -04:00
parent eb8104be2f
commit 3d353dcd26

View File

@ -9,7 +9,6 @@ import datetime
import logging import logging
import select import select
import socket import socket
import time
from typing import Any, Callable, Dict from typing import Any, Callable, Dict
import aprslib import aprslib
@ -25,6 +24,7 @@ from aprsd import ( # noqa
exception, exception,
) )
from aprsd.packets import core from aprsd.packets import core
from aprsd.utils import trace
CONF = cfg.CONF CONF = cfg.CONF
LOG = logging.getLogger('APRSD') LOG = logging.getLogger('APRSD')
@ -46,10 +46,12 @@ def handle_fend(buffer: bytes, strip_df_start: bool = True) -> bytes:
return bytes(frame) return bytes(frame)
# class TCPKISSDriver(metaclass=trace.TraceWrapperMetaclass): class TCPKISSDriver(metaclass=trace.TraceWrapperMetaclass):
class TCPKISSDriver: # class TCPKISSDriver:
"""APRSD client driver for TCP KISS connections.""" """APRSD client driver for TCP KISS connections."""
_instance = None
# Class level attributes required by Client protocol # Class level attributes required by Client protocol
packets_received = 0 packets_received = 0
packets_sent = 0 packets_sent = 0
@ -62,6 +64,12 @@ class TCPKISSDriver:
select_timeout = 1 select_timeout = 1
path = None path = None
def __new__(cls, *args, **kwargs):
"""This magic turns this into a singleton."""
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self): def __init__(self):
"""Initialize the KISS client. """Initialize the KISS client.
@ -71,7 +79,6 @@ class TCPKISSDriver:
super().__init__() super().__init__()
self._connected = False self._connected = False
self.keepalive = datetime.datetime.now() self.keepalive = datetime.datetime.now()
self._running = False
# This is initialized in setup_connection() # This is initialized in setup_connection()
self.socket = None self.socket = None
@ -111,7 +118,15 @@ class TCPKISSDriver:
def close(self): def close(self):
"""Close the connection.""" """Close the connection."""
self.stop() self._connected = False
if self.socket:
try:
self.socket.close()
except Exception as e:
LOG.error(f'close: error closing socket: {e}')
pass
else:
LOG.warning('close: socket not initialized. no reason to close.')
def send(self, packet: core.Packet): def send(self, packet: core.Packet):
"""Send an APRS packet. """Send an APRS packet.
@ -163,6 +178,10 @@ class TCPKISSDriver:
LOG.error('KISS is not enabled in configuration') LOG.error('KISS is not enabled in configuration')
return return
if self._connected:
LOG.warning('KISS interface already connected')
return
try: try:
# Configure for TCP KISS # Configure for TCP KISS
if self.is_enabled(): if self.is_enabled():
@ -217,18 +236,14 @@ class TCPKISSDriver:
Raises: Raises:
Exception: If not connected to KISS TNC Exception: If not connected to KISS TNC
""" """
self._running = True
while self._running:
# Ensure connection # Ensure connection
if not self._connected: if not self._connected:
if not self.connect(): return
time.sleep(1)
continue
# Read frame # Read frame
frame = self.read_frame() frame = self.read_frame()
if frame: if frame:
LOG.warning(f'GOT FRAME: {frame} calling {callback}') LOG.info(f'GOT FRAME: {frame} calling {callback}')
kwargs = { kwargs = {
'frame': frame, 'frame': frame,
} }
@ -245,7 +260,6 @@ class TCPKISSDriver:
LOG.warning('No frame received to decode?!?!') LOG.warning('No frame received to decode?!?!')
return None return None
LOG.warning(f'FRAME: {str(frame)}')
try: try:
aprslib_frame = aprslib.parse(str(frame)) aprslib_frame = aprslib.parse(str(frame))
packet = core.factory(aprslib_frame) packet = core.factory(aprslib_frame)
@ -257,16 +271,6 @@ class TCPKISSDriver:
LOG.error(f'Error decoding packet: {e}') LOG.error(f'Error decoding packet: {e}')
return None return None
def stop(self):
"""Stop the KISS interface."""
self._running = False
self._connected = False
if self.socket:
try:
self.socket.close()
except Exception:
pass
def stats(self, serializable: bool = False) -> Dict[str, Any]: def stats(self, serializable: bool = False) -> Dict[str, Any]:
"""Get client statistics. """Get client statistics.
@ -353,13 +357,19 @@ class TCPKISSDriver:
""" """
Generator for complete lines, received from the server Generator for complete lines, received from the server
""" """
if not self.socket:
return None
if not self._connected:
return None
try: try:
self.socket.setblocking(0) self.socket.setblocking(0)
except OSError as e: except OSError as e:
LOG.error(f'socket error when setblocking(0): {str(e)}') LOG.error(f'socket error when setblocking(0): {str(e)}')
raise aprslib.ConnectionDrop('connection dropped') from e raise aprslib.ConnectionDrop('connection dropped') from e
while self._running: while self._connected:
short_buf = b'' short_buf = b''
try: try:
@ -375,6 +385,8 @@ class TCPKISSDriver:
else: else:
continue continue
except Exception as e: except Exception as e:
# No need to log if we are not running.
# this happens when the client is stopped/closed.
LOG.error(f'Error in read loop: {e}') LOG.error(f'Error in read loop: {e}')
self._connected = False self._connected = False
break break