mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-24 08:58:49 -05:00
Update Client to report login status
This patch updates the aprsd client base class to report login succes and any error string associated with a login failure. Also exposes the login status so anyone using the client to check for login failure. Update webchat, listen, server commands to check for initial login failures and exit if the login failed. No reason to continue on if the login fails.
This commit is contained in:
parent
9f7d169c18
commit
06c1fb985e
@ -23,13 +23,24 @@ class APRSISClient(base.APRSClient):
|
|||||||
max_timeout = {"hours": 0.0, "minutes": 2, "seconds": 0}
|
max_timeout = {"hours": 0.0, "minutes": 2, "seconds": 0}
|
||||||
self.max_delta = datetime.timedelta(**max_timeout)
|
self.max_delta = datetime.timedelta(**max_timeout)
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
stats = {}
|
stats = {}
|
||||||
if self.is_configured():
|
if self.is_configured():
|
||||||
|
if self._client:
|
||||||
|
keepalive = self._client.aprsd_keepalive
|
||||||
|
server_string = self._client.server_string
|
||||||
|
if serializable:
|
||||||
|
keepalive = keepalive.isoformat()
|
||||||
|
else:
|
||||||
|
keepalive = "None"
|
||||||
|
server_string = "None"
|
||||||
stats = {
|
stats = {
|
||||||
"server_string": self._client.server_string,
|
"connected": self.is_connected,
|
||||||
"sever_keepalive": self._client.aprsd_keepalive,
|
|
||||||
"filter": self.filter,
|
"filter": self.filter,
|
||||||
|
"keepalive": keepalive,
|
||||||
|
"login_status": self.login_status,
|
||||||
|
"server_string": server_string,
|
||||||
|
"transport": self.transport(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
@ -99,22 +110,31 @@ class APRSISClient(base.APRSClient):
|
|||||||
self.connected = False
|
self.connected = False
|
||||||
backoff = 1
|
backoff = 1
|
||||||
aprs_client = None
|
aprs_client = None
|
||||||
|
retries = 3
|
||||||
|
retry_count = 0
|
||||||
while not self.connected:
|
while not self.connected:
|
||||||
|
retry_count += 1
|
||||||
|
if retry_count >= retries:
|
||||||
|
break
|
||||||
try:
|
try:
|
||||||
LOG.info(f"Creating aprslib client({host}:{port}) and logging in {user}.")
|
LOG.info(f"Creating aprslib client({host}:{port}) and logging in {user}.")
|
||||||
aprs_client = aprsis.Aprsdis(user, passwd=password, host=host, port=port)
|
aprs_client = aprsis.Aprsdis(user, passwd=password, host=host, port=port)
|
||||||
# Force the log to be the same
|
# Force the log to be the same
|
||||||
aprs_client.logger = LOG
|
aprs_client.logger = LOG
|
||||||
aprs_client.connect()
|
aprs_client.connect()
|
||||||
self.connected = True
|
self.connected = self.login_status["success"] = True
|
||||||
|
self.login_status["message"] = aprs_client.server_string
|
||||||
backoff = 1
|
backoff = 1
|
||||||
except LoginError as e:
|
except LoginError as e:
|
||||||
LOG.error(f"Failed to login to APRS-IS Server '{e}'")
|
LOG.error(f"Failed to login to APRS-IS Server '{e}'")
|
||||||
self.connected = False
|
self.connected = self.login_status["success"] = False
|
||||||
|
self.login_status["message"] = e.message
|
||||||
|
LOG.error(e.message)
|
||||||
time.sleep(backoff)
|
time.sleep(backoff)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error(f"Unable to connect to APRS-IS server. '{e}' ")
|
LOG.error(f"Unable to connect to APRS-IS server. '{e}' ")
|
||||||
self.connected = False
|
self.connected = self.login_status["success"] = False
|
||||||
|
self.login_status["message"] = e.message
|
||||||
time.sleep(backoff)
|
time.sleep(backoff)
|
||||||
# Don't allow the backoff to go to inifinity.
|
# Don't allow the backoff to go to inifinity.
|
||||||
if backoff > 5:
|
if backoff > 5:
|
||||||
@ -135,5 +155,7 @@ class APRSISClient(base.APRSClient):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
LOG.info(e.__cause__)
|
LOG.info(e.__cause__)
|
||||||
|
raise e
|
||||||
else:
|
else:
|
||||||
LOG.warning("client is None, might be resetting.")
|
LOG.warning("client is None, might be resetting.")
|
||||||
|
self.connected = False
|
||||||
|
@ -19,6 +19,10 @@ class APRSClient:
|
|||||||
_client = None
|
_client = None
|
||||||
|
|
||||||
connected = False
|
connected = False
|
||||||
|
login_status = {
|
||||||
|
"success": False,
|
||||||
|
"message": None,
|
||||||
|
}
|
||||||
filter = None
|
filter = None
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
|
||||||
@ -38,6 +42,18 @@ class APRSClient:
|
|||||||
dict: Statistics about the connection and packet handling
|
dict: Statistics about the connection and packet handling
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_connected(self):
|
||||||
|
return self.connected
|
||||||
|
|
||||||
|
@property
|
||||||
|
def login_success(self):
|
||||||
|
return self.login_status.get("success", False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def login_failure(self):
|
||||||
|
return self.login_status["message"]
|
||||||
|
|
||||||
def set_filter(self, filter):
|
def set_filter(self, filter):
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
if self._client:
|
if self._client:
|
||||||
|
@ -27,6 +27,9 @@ class Aprsdis(aprslib.IS):
|
|||||||
# date for last time we heard from the server
|
# date for last time we heard from the server
|
||||||
aprsd_keepalive = datetime.datetime.now()
|
aprsd_keepalive = datetime.datetime.now()
|
||||||
|
|
||||||
|
# Which server we are connected to?
|
||||||
|
server_string = "None"
|
||||||
|
|
||||||
# timeout in seconds
|
# timeout in seconds
|
||||||
select_timeout = 1
|
select_timeout = 1
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
@ -14,8 +14,11 @@ LOG = logging.getLogger("APRSD")
|
|||||||
|
|
||||||
class APRSDFakeClient(base.APRSClient, metaclass=trace.TraceWrapperMetaclass):
|
class APRSDFakeClient(base.APRSClient, metaclass=trace.TraceWrapperMetaclass):
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
return {}
|
return {
|
||||||
|
"transport": "Fake",
|
||||||
|
"connected": True,
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_enabled():
|
def is_enabled():
|
||||||
|
@ -17,12 +17,18 @@ class KISSClient(base.APRSClient):
|
|||||||
|
|
||||||
_client = None
|
_client = None
|
||||||
|
|
||||||
def stats(self) -> dict:
|
def stats(self, serializable=False) -> dict:
|
||||||
stats = {}
|
stats = {}
|
||||||
if self.is_configured():
|
if self.is_configured():
|
||||||
return {
|
stats = {
|
||||||
|
"connected": self.is_connected,
|
||||||
"transport": self.transport(),
|
"transport": self.transport(),
|
||||||
}
|
}
|
||||||
|
if self.transport() == client.TRANSPORT_TCPKISS:
|
||||||
|
stats["host"] = CONF.kiss_tcp.host
|
||||||
|
stats["port"] = CONF.kiss_tcp.port
|
||||||
|
elif self.transport() == client.TRANSPORT_SERIALKISS:
|
||||||
|
stats["device"] = CONF.kiss_serial.device
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -17,22 +17,4 @@ class APRSClientStats:
|
|||||||
|
|
||||||
@wrapt.synchronized(lock)
|
@wrapt.synchronized(lock)
|
||||||
def stats(self, serializable=False):
|
def stats(self, serializable=False):
|
||||||
cl = client.client_factory.create()
|
return client.client_factory.create().stats(serializable=serializable)
|
||||||
stats = {
|
|
||||||
"transport": cl.transport(),
|
|
||||||
"filter": cl.filter,
|
|
||||||
"connected": cl.connected,
|
|
||||||
}
|
|
||||||
|
|
||||||
if cl.transport() == client.TRANSPORT_APRSIS:
|
|
||||||
stats["server_string"] = cl.client.server_string
|
|
||||||
keepalive = cl.client.aprsd_keepalive
|
|
||||||
if serializable:
|
|
||||||
keepalive = keepalive.isoformat()
|
|
||||||
stats["server_keepalive"] = keepalive
|
|
||||||
elif cl.transport() == client.TRANSPORT_TCPKISS:
|
|
||||||
stats["host"] = CONF.kiss_tcp.host
|
|
||||||
stats["port"] = CONF.kiss_tcp.port
|
|
||||||
elif cl.transport() == client.TRANSPORT_SERIALKISS:
|
|
||||||
stats["device"] = CONF.kiss_serial.device
|
|
||||||
return stats
|
|
||||||
|
@ -256,6 +256,12 @@ def listen(
|
|||||||
LOG.info("Creating client connection")
|
LOG.info("Creating client connection")
|
||||||
aprs_client = client_factory.create()
|
aprs_client = client_factory.create()
|
||||||
LOG.info(aprs_client)
|
LOG.info(aprs_client)
|
||||||
|
if not aprs_client.login_success:
|
||||||
|
# We failed to login, will just quit!
|
||||||
|
msg = f"Login Failure: {aprs_client.login_failure}"
|
||||||
|
LOG.error(msg)
|
||||||
|
print(msg)
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
LOG.debug(f"Filter by '{filter}'")
|
LOG.debug(f"Filter by '{filter}'")
|
||||||
aprs_client.set_filter(filter)
|
aprs_client.set_filter(filter)
|
||||||
|
@ -58,6 +58,14 @@ def server(ctx, flush):
|
|||||||
LOG.info("Creating client connection")
|
LOG.info("Creating client connection")
|
||||||
aprs_client = client_factory.create()
|
aprs_client = client_factory.create()
|
||||||
LOG.info(aprs_client)
|
LOG.info(aprs_client)
|
||||||
|
if not aprs_client.login_success:
|
||||||
|
# We failed to login, will just quit!
|
||||||
|
msg = f"Login Failure: {aprs_client.login_failure}"
|
||||||
|
LOG.error(msg)
|
||||||
|
print(msg)
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
# Check to make sure the login worked.
|
||||||
|
|
||||||
# Create the initial PM singleton and Register plugins
|
# Create the initial PM singleton and Register plugins
|
||||||
# We register plugins first here so we can register each
|
# We register plugins first here so we can register each
|
||||||
|
@ -24,7 +24,9 @@ from aprsd import utils as aprsd_utils
|
|||||||
from aprsd.client import client_factory, kiss
|
from aprsd.client import client_factory, kiss
|
||||||
from aprsd.main import cli
|
from aprsd.main import cli
|
||||||
from aprsd.threads import aprsd as aprsd_threads
|
from aprsd.threads import aprsd as aprsd_threads
|
||||||
from aprsd.threads import keep_alive, rx, tx
|
from aprsd.threads import keep_alive, rx
|
||||||
|
from aprsd.threads import stats as stats_thread
|
||||||
|
from aprsd.threads import tx
|
||||||
from aprsd.utils import trace
|
from aprsd.utils import trace
|
||||||
|
|
||||||
|
|
||||||
@ -614,10 +616,24 @@ def webchat(ctx, flush, port):
|
|||||||
LOG.error("APRS client is not properly configured in config file.")
|
LOG.error("APRS client is not properly configured in config file.")
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
# Creates the client object
|
||||||
|
LOG.info("Creating client connection")
|
||||||
|
aprs_client = client_factory.create()
|
||||||
|
LOG.info(aprs_client)
|
||||||
|
if not aprs_client.login_success:
|
||||||
|
# We failed to login, will just quit!
|
||||||
|
msg = f"Login Failure: {aprs_client.login_failure}"
|
||||||
|
LOG.error(msg)
|
||||||
|
print(msg)
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
keepalive = keep_alive.KeepAliveThread()
|
keepalive = keep_alive.KeepAliveThread()
|
||||||
LOG.info("Start KeepAliveThread")
|
LOG.info("Start KeepAliveThread")
|
||||||
keepalive.start()
|
keepalive.start()
|
||||||
|
|
||||||
|
stats_store_thread = stats_thread.APRSDStatsStoreThread()
|
||||||
|
stats_store_thread.start()
|
||||||
|
|
||||||
socketio = init_flask(loglevel, quiet)
|
socketio = init_flask(loglevel, quiet)
|
||||||
rx_thread = rx.APRSDPluginRXThread(
|
rx_thread = rx.APRSDPluginRXThread(
|
||||||
packet_queue=threads.packet_queue,
|
packet_queue=threads.packet_queue,
|
||||||
|
@ -5,6 +5,7 @@ import tracemalloc
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
import timeago
|
||||||
|
|
||||||
from aprsd import packets, utils
|
from aprsd import packets, utils
|
||||||
from aprsd.client import client_factory
|
from aprsd.client import client_factory
|
||||||
@ -98,6 +99,9 @@ class KeepAliveThread(APRSDThread):
|
|||||||
|
|
||||||
# check the APRS connection
|
# check the APRS connection
|
||||||
cl = client_factory.create()
|
cl = client_factory.create()
|
||||||
|
cl_stats = cl.stats()
|
||||||
|
keepalive = timeago.format(cl_stats.get("keepalive", None))
|
||||||
|
LOGU.opt(colors=True).info(f"<green>Client keepalive {keepalive}</green>")
|
||||||
# Reset the connection if it's dead and this isn't our
|
# Reset the connection if it's dead and this isn't our
|
||||||
# First time through the loop.
|
# First time through the loop.
|
||||||
# The first time through the loop can happen at startup where
|
# The first time through the loop can happen at startup where
|
||||||
|
@ -18,6 +18,8 @@ LOG = logging.getLogger("APRSD")
|
|||||||
|
|
||||||
|
|
||||||
class APRSDRXThread(APRSDThread):
|
class APRSDRXThread(APRSDThread):
|
||||||
|
_client = None
|
||||||
|
|
||||||
def __init__(self, packet_queue):
|
def __init__(self, packet_queue):
|
||||||
super().__init__("RX_PKT")
|
super().__init__("RX_PKT")
|
||||||
self.packet_queue = packet_queue
|
self.packet_queue = packet_queue
|
||||||
@ -33,6 +35,12 @@ class APRSDRXThread(APRSDThread):
|
|||||||
self._client = client_factory.create()
|
self._client = client_factory.create()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if not self._client.is_connected:
|
||||||
|
self._client = client_factory.create()
|
||||||
|
time.sleep(1)
|
||||||
|
return True
|
||||||
|
|
||||||
# setup the consumer of messages and block until a messages
|
# setup the consumer of messages and block until a messages
|
||||||
try:
|
try:
|
||||||
# This will register a packet consumer with aprslib
|
# This will register a packet consumer with aprslib
|
||||||
|
Loading…
Reference in New Issue
Block a user