1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-09-05 14:47:53 -04:00

Removed flask-classful from webchat

This patch removed the dependency on flask-classful.  This required
making all of the flask web routing non class based.

This patch also changes the aprsis class to allow retries for failed
connections when the aprsis servers are full and not responding to
login requests.
This commit is contained in:
Hemna 2023-07-19 11:27:34 -04:00
parent e1183a7e30
commit 6a6e854caf
5 changed files with 127 additions and 120 deletions

View File

@ -152,9 +152,10 @@ class APRSISClient(Client):
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}'")
connected = False connected = False
raise e 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}' ")
connected = False
time.sleep(backoff) time.sleep(backoff)
backoff = backoff * 2 backoff = backoff * 2
continue continue

View File

@ -112,23 +112,23 @@ class Aprsdis(aprslib.IS):
self._sendall(login_str) self._sendall(login_str)
self.sock.settimeout(5) self.sock.settimeout(5)
test = self.sock.recv(len(login_str) + 100) test = self.sock.recv(len(login_str) + 100)
self.logger.debug("Server: '%s'", test)
if is_py3: if is_py3:
test = test.decode("latin-1") test = test.decode("latin-1")
test = test.rstrip() test = test.rstrip()
self.logger.debug("Server: %s", test) self.logger.debug("Server: '%s'", test)
a, b, callsign, status, e = test.split(" ", 4) if not test:
raise LoginError(f"Server Response Empty: '{test}'")
_, _, callsign, status, e = test.split(" ", 4)
s = e.split(",") s = e.split(",")
if len(s): if len(s):
server_string = s[0].replace("server ", "") server_string = s[0].replace("server ", "")
else: else:
server_string = e.replace("server ", "") server_string = e.replace("server ", "")
self.logger.info(f"Connected to {server_string}")
self.server_string = server_string
stats.APRSDStats().set_aprsis_server(server_string)
if callsign == "": if callsign == "":
raise LoginError("Server responded with empty callsign???") raise LoginError("Server responded with empty callsign???")
if callsign != self.callsign: if callsign != self.callsign:
@ -141,6 +141,10 @@ class Aprsdis(aprslib.IS):
else: else:
self.logger.info("Login successful") self.logger.info("Login successful")
self.logger.info(f"Connected to {server_string}")
self.server_string = server_string
stats.APRSDStats().set_aprsis_server(server_string)
except LoginError as e: except LoginError as e:
self.logger.error(str(e)) self.logger.error(str(e))
self.close() self.close()
@ -148,6 +152,7 @@ class Aprsdis(aprslib.IS):
except Exception as e: except Exception as e:
self.close() self.close()
self.logger.error(f"Failed to login '{e}'") self.logger.error(f"Failed to login '{e}'")
self.logger.exception(e)
raise LoginError("Failed to login") raise LoginError("Failed to login")
def consumer(self, callback, blocking=True, immortal=False, raw=False): def consumer(self, callback, blocking=True, immortal=False, raw=False):

View File

@ -12,7 +12,6 @@ import click
import flask import flask
from flask import request from flask import request
from flask.logging import default_handler from flask.logging import default_handler
import flask_classful
from flask_httpauth import HTTPBasicAuth from flask_httpauth import HTTPBasicAuth
from flask_socketio import Namespace, SocketIO from flask_socketio import Namespace, SocketIO
from oslo_config import cfg from oslo_config import cfg
@ -31,9 +30,16 @@ from aprsd.utils import objectstore, trace
CONF = cfg.CONF CONF = cfg.CONF
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
auth = HTTPBasicAuth() auth = HTTPBasicAuth()
users = None users = {}
socketio = None socketio = None
flask_app = flask.Flask(
"aprsd",
static_url_path="/static",
static_folder="web/chat/static",
template_folder="web/chat/templates",
)
def signal_handler(sig, frame): def signal_handler(sig, frame):
@ -174,16 +180,11 @@ class WebChatProcessPacketThread(rx.APRSDProcessPacketThread):
) )
class WebChatFlask(flask_classful.FlaskView): def set_config():
def set_config(self):
global users global users
self.users = {}
user = CONF.admin.user
self.users[user] = generate_password_hash(CONF.admin.password)
users = self.users
def _get_transport(self, stats):
def _get_transport(stats):
if CONF.aprs_network.enabled: if CONF.aprs_network.enabled:
transport = "aprs-is" transport = "aprs-is"
aprs_connection = ( aprs_connection = (
@ -212,13 +213,15 @@ class WebChatFlask(flask_classful.FlaskView):
return transport, aprs_connection return transport, aprs_connection
@auth.login_required
def index(self): @auth.login_required
@flask_app.route("/")
def index():
ua_str = request.headers.get("User-Agent") ua_str = request.headers.get("User-Agent")
# this takes about 2 seconds :( # this takes about 2 seconds :(
user_agent = ua_parse(ua_str) user_agent = ua_parse(ua_str)
LOG.debug(f"Is mobile? {user_agent.is_mobile}") LOG.debug(f"Is mobile? {user_agent.is_mobile}")
stats = self._stats() stats = _stats()
if user_agent.is_mobile: if user_agent.is_mobile:
html_template = "mobile.html" html_template = "mobile.html"
@ -230,7 +233,7 @@ class WebChatFlask(flask_classful.FlaskView):
LOG.debug(f"Template {html_template}") LOG.debug(f"Template {html_template}")
transport, aprs_connection = self._get_transport(stats) transport, aprs_connection = _get_transport(stats)
LOG.debug(f"transport {transport} aprs_connection {aprs_connection}") LOG.debug(f"transport {transport} aprs_connection {aprs_connection}")
stats["transport"] = transport stats["transport"] = transport
@ -245,14 +248,17 @@ class WebChatFlask(flask_classful.FlaskView):
version=aprsd.__version__, version=aprsd.__version__,
) )
@auth.login_required
def send_message_status(self): @auth.login_required
@flask_app.route("//send-message-status")
def send_message_status():
LOG.debug(request) LOG.debug(request)
msgs = SentMessages() msgs = SentMessages()
info = msgs.get_all() info = msgs.get_all()
return json.dumps(info) return json.dumps(info)
def _stats(self):
def _stats():
stats_obj = stats.APRSDStats() stats_obj = stats.APRSDStats()
now = datetime.datetime.now() now = datetime.datetime.now()
@ -272,8 +278,10 @@ class WebChatFlask(flask_classful.FlaskView):
return result return result
def stats(self):
return json.dumps(self._stats()) @flask_app.route("/stats")
def get_stats():
return json.dumps(_stats())
class SendMessageNamespace(Namespace): class SendMessageNamespace(Namespace):
@ -377,21 +385,9 @@ def setup_logging(flask_app, loglevel, quiet):
@trace.trace @trace.trace
def init_flask(loglevel, quiet): def init_flask(loglevel, quiet):
global socketio global socketio, flask_app
flask_app = flask.Flask(
"aprsd",
static_url_path="/static",
static_folder="web/chat/static",
template_folder="web/chat/templates",
)
setup_logging(flask_app, loglevel, quiet) setup_logging(flask_app, loglevel, quiet)
server = WebChatFlask()
server.set_config()
flask_app.route("/", methods=["GET"])(server.index)
flask_app.route("/stats", methods=["GET"])(server.stats)
# flask_app.route("/send-message", methods=["GET"])(server.send_message)
flask_app.route("/send-message-status", methods=["GET"])(server.send_message_status)
socketio = SocketIO( socketio = SocketIO(
flask_app, logger=False, engineio_logger=False, flask_app, logger=False, engineio_logger=False,
@ -407,7 +403,7 @@ def init_flask(loglevel, quiet):
"/sendmsg", "/sendmsg",
), ),
) )
return socketio, flask_app return socketio
# main() ### # main() ###
@ -448,6 +444,8 @@ def webchat(ctx, flush, port):
LOG.info(f"APRSD Started version: {aprsd.__version__}") LOG.info(f"APRSD Started version: {aprsd.__version__}")
CONF.log_opt_values(LOG, logging.DEBUG) CONF.log_opt_values(LOG, logging.DEBUG)
user = CONF.admin.user
users[user] = generate_password_hash(CONF.admin.password)
# Initialize the client factory and create # Initialize the client factory and create
# The correct client object ready for use # The correct client object ready for use
@ -466,7 +464,7 @@ def webchat(ctx, flush, port):
packets.WatchList() packets.WatchList()
packets.SeenList() packets.SeenList()
(socketio, app) = 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,
) )
@ -482,7 +480,7 @@ def webchat(ctx, flush, port):
keepalive.start() keepalive.start()
LOG.info("Start socketio.run()") LOG.info("Start socketio.run()")
socketio.run( socketio.run(
app, flask_app,
ssl_context="adhoc", ssl_context="adhoc",
host=CONF.admin.web_ip, host=CONF.admin.web_ip,
port=port, port=port,

View File

@ -187,6 +187,7 @@ def index():
plugin_count=plugin_count, plugin_count=plugin_count,
) )
@auth.login_required @auth.login_required
def messages(): def messages():
track = packets.PacketTrack() track = packets.PacketTrack()
@ -197,9 +198,10 @@ def messages():
return flask.render_template("messages.html", messages=json.dumps(msgs)) return flask.render_template("messages.html", messages=json.dumps(msgs))
@auth.login_required @auth.login_required
@app.route("/packets") @app.route("/packets")
def packets(): def get_packets():
LOG.debug("/packets called") LOG.debug("/packets called")
packet_list = aprsd_rpc_client.RPCClient().get_packet_list() packet_list = aprsd_rpc_client.RPCClient().get_packet_list()
if packet_list: if packet_list:
@ -212,6 +214,7 @@ def packets():
else: else:
return json.dumps([]) return json.dumps([])
@auth.login_required @auth.login_required
@app.route("/plugins") @app.route("/plugins")
def plugins(): def plugins():
@ -221,6 +224,7 @@ def plugins():
return "reloaded" return "reloaded"
@auth.login_required @auth.login_required
@app.route("/save") @app.route("/save")
def save(): def save():
@ -230,7 +234,6 @@ def save():
return json.dumps({"messages": "saved"}) return json.dumps({"messages": "saved"})
class LogUpdateThread(threads.APRSDThread): class LogUpdateThread(threads.APRSDThread):
def __init__(self): def __init__(self):

View File

@ -39,9 +39,9 @@ class TestSendMessageCommand(unittest.TestCase):
CliRunner() CliRunner()
self.config_and_init() self.config_and_init()
socketio, flask_app = webchat.init_flask("DEBUG", False) socketio = webchat.init_flask("DEBUG", False)
self.assertIsInstance(socketio, flask_socketio.SocketIO) self.assertIsInstance(socketio, flask_socketio.SocketIO)
self.assertIsInstance(flask_app, flask.Flask) self.assertIsInstance(webchat.flask_app, flask.Flask)
@mock.patch("aprsd.packets.tracker.PacketTrack.remove") @mock.patch("aprsd.packets.tracker.PacketTrack.remove")
@mock.patch("aprsd.cmds.webchat.socketio") @mock.patch("aprsd.cmds.webchat.socketio")