From 19fd15b9dcd8cee3900e797c95c1245470da3011 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Wed, 15 Oct 2025 18:12:24 +0200 Subject: [PATCH] refactor: deduplicate threads array --- basicswap/basicswap.py | 55 ++++++++++++++++++++- basicswap/bin/run.py | 62 ------------------------ tests/basicswap/extended/test_dash.py | 13 ----- tests/basicswap/extended/test_network.py | 14 +----- tests/basicswap/extended/test_pivx.py | 13 ----- tests/basicswap/test_xmr.py | 13 +---- 6 files changed, 56 insertions(+), 114 deletions(-) diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index c1569e7..fa27225 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -66,12 +66,14 @@ from .chainparams import ( Fiat, ticker_map, ) +from .contrib.websocket_server import WebsocketServer from .db_upgrades import upgradeDatabase, upgradeDatabaseData from .db_util import remove_expired_data +from .http_server import HttpThread from .rpc import escape_rpcauth from .rpc_xmr import make_xmr_rpc2_func -from .ui.util import getCoinName from .ui.app import UIApp +from .ui.util import getCoinName from .util import ( AutomationConstraint, AutomationConstraintTemporary, @@ -644,6 +646,7 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp): self._network.stopNetwork() self._network = None + self.log.info("Stopping threads.") for t in self.threads: if hasattr(t, "stop") and callable(t.stop): t.stop() @@ -1307,6 +1310,43 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp): self._price_fetch_thread.start() self.log.info("Background price fetching started") + if "htmlhost" in self.settings: + self.log.info( + "Starting HTTP server at http://{}:{}".format( + self.settings["htmlhost"], self.settings["htmlport"] + ) + ) + allow_cors: bool = ( + self.settings["allowcors"] + if "allowcors" in self.settings + else cfg.DEFAULT_ALLOW_CORS + ) + thread_http = HttpThread( + self.settings["htmlhost"], + self.settings["htmlport"], + allow_cors, + self, + ) + self.threads.append(thread_http) + thread_http.start() + + if "wshost" in self.settings: + ws_url = "ws://{}:{}".format( + self.settings["wshost"], self.settings["wsport"] + ) + self.log.info(f"Starting WebSocket server at {ws_url}") + + self.ws_server = WebsocketServer( + host=self.settings["wshost"], port=self.settings["wsport"] + ) + self.ws_server.client_port = self.settings.get( + "wsclientport", self.settings["wsport"] + ) + self.ws_server.set_fn_new_client(self.ws_new_client) + self.ws_server.set_fn_client_left(self.ws_client_left) + self.ws_server.set_fn_message_received(self.ws_message_received) + self.ws_server.run_forever(threaded=True) + def stopDaemon(self, coin) -> None: if coin in (Coins.XMR, Coins.DCR, Coins.WOW): return @@ -12904,3 +12944,16 @@ class BasicSwap(BaseApp, BSXNetwork, UIApp): return rv_array return rv + + def ws_new_client(self, client, server): + self.log.debug(f'ws_new_client {client["id"]}') + + def ws_client_left(self, client, server): + if client is None: + return + self.log.debug(f'ws_client_left {client["id"]}') + + def ws_message_received(self, client, server, message): + if len(message) > 200: + message = message[:200] + ".." + self.log.debug(f'ws_message_received {client["id"]} {message}') diff --git a/basicswap/bin/run.py b/basicswap/bin/run.py index 12f3f10..8281e30 100755 --- a/basicswap/bin/run.py +++ b/basicswap/bin/run.py @@ -19,8 +19,6 @@ import basicswap.config as cfg from basicswap import __version__ from basicswap.basicswap import BasicSwap from basicswap.chainparams import chainparams, Coins, isKnownCoinName -from basicswap.contrib.websocket_server import WebsocketServer -from basicswap.http_server import HttpThread from basicswap.network.simplex_chat import startSimplexClient from basicswap.ui.util import getCoinName from basicswap.util.daemon import Daemon @@ -285,25 +283,6 @@ def startXmrWalletDaemon(node_dir, bin_dir, wallet_bin, opts=[]): ) -def ws_new_client(client, server): - if swap_client: - swap_client.log.debug(f'ws_new_client {client["id"]}') - - -def ws_client_left(client, server): - if client is None: - return - if swap_client: - swap_client.log.debug(f'ws_client_left {client["id"]}') - - -def ws_message_received(client, server, message): - if len(message) > 200: - message = message[:200] + ".." - if swap_client: - swap_client.log.debug(f'ws_message_received {client["id"]} {message}') - - def getCoreBinName(coin_id: int, coin_settings, default_name: str) -> str: return coin_settings.get( "core_binname", chainparams[coin_id].get("core_binname", default_name) @@ -372,7 +351,6 @@ def runClient( global swap_client, logger daemons = [] pids = [] - threads = [] settings_path = os.path.join(data_dir, cfg.CONFIG_FILENAME) pids_path = os.path.join(data_dir, ".pids") @@ -623,39 +601,6 @@ def runClient( mainLoop(daemons, update=False) else: swap_client.start() - if "htmlhost" in settings: - swap_client.log.info( - "Starting http server at http://%s:%d" - % (settings["htmlhost"], settings["htmlport"]) - ) - allow_cors = ( - settings["allowcors"] - if "allowcors" in settings - else cfg.DEFAULT_ALLOW_CORS - ) - thread_http = HttpThread( - settings["htmlhost"], - settings["htmlport"], - allow_cors, - swap_client, - ) - threads.append(thread_http) - thread_http.start() - - if "wshost" in settings: - ws_url = "ws://{}:{}".format(settings["wshost"], settings["wsport"]) - swap_client.log.info(f"Starting ws server at {ws_url}") - - swap_client.ws_server = WebsocketServer( - host=settings["wshost"], port=settings["wsport"] - ) - swap_client.ws_server.client_port = settings.get( - "wsclientport", settings["wsport"] - ) - swap_client.ws_server.set_fn_new_client(ws_new_client) - swap_client.ws_server.set_fn_client_left(ws_client_left) - swap_client.ws_server.set_fn_message_received(ws_message_received) - swap_client.ws_server.run_forever(threaded=True) logger.info("Exit with Ctrl + c.") mainLoop(daemons) @@ -671,13 +616,6 @@ def runClient( traceback.print_exc() swap_client.finalise() - swap_client.log.info("Stopping HTTP threads.") - for t in threads: - try: - t.stop() - t.join() - except Exception as e: # noqa: F841 - traceback.print_exc() closed_pids = [] for d in daemons: diff --git a/tests/basicswap/extended/test_dash.py b/tests/basicswap/extended/test_dash.py index 72f3b98..92ee00c 100644 --- a/tests/basicswap/extended/test_dash.py +++ b/tests/basicswap/extended/test_dash.py @@ -42,9 +42,6 @@ from basicswap.basicswap_util import ( from basicswap.util.address import ( toWIF, ) -from basicswap.http_server import ( - HttpThread, -) from tests.basicswap.util import ( read_json_api, ) @@ -58,7 +55,6 @@ from tests.basicswap.common import ( wait_for_unspent, wait_for_bid_tx_state, wait_for_in_progress, - TEST_HTTP_HOST, TEST_HTTP_PORT, BASE_PORT, BASE_RPC_PORT, @@ -306,7 +302,6 @@ class Test(unittest.TestCase): cls.daemons = [] cls.swap_clients = [] - cls.http_threads = [] btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)) if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): @@ -417,10 +412,6 @@ class Test(unittest.TestCase): sc.start() - t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) - cls.http_threads.append(t) - t.start() - waitForRPC(dashRpc, delay_event) num_blocks = 500 logging.info("Mining %d dash blocks", num_blocks) @@ -473,15 +464,11 @@ class Test(unittest.TestCase): stop_test = True cls.update_thread.join() cls.coins_update_thread.join() - for t in cls.http_threads: - t.stop() - t.join() for c in cls.swap_clients: c.finalise() stopDaemons(cls.daemons) - cls.http_threads.clear() cls.swap_clients.clear() cls.daemons.clear() diff --git a/tests/basicswap/extended/test_network.py b/tests/basicswap/extended/test_network.py index 5642e5e..2414426 100644 --- a/tests/basicswap/extended/test_network.py +++ b/tests/basicswap/extended/test_network.py @@ -35,9 +35,6 @@ from basicswap.util.address import ( from basicswap.rpc import ( callrpc, ) -from basicswap.http_server import ( - HttpThread, -) from tests.basicswap.util import ( read_json_api, ) @@ -84,7 +81,7 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): "p2p_port": BASE_P2P_PORT + node_id, "zmqhost": "tcp://127.0.0.1", "zmqport": BASE_ZMQ_PORT + node_id, - "htmlhost": "127.0.0.1", + "htmlhost": TEST_HTTP_HOST, "htmlport": TEST_HTTP_PORT + node_id, "network_key": network_key, "network_pubkey": network_pubkey, @@ -185,7 +182,6 @@ class Test(unittest.TestCase): cls.update_thread = None cls.coins_update_thread = None - cls.http_threads = [] cls.swap_clients = [] cls.part_daemons = [] cls.btc_daemons = [] @@ -334,10 +330,6 @@ class Test(unittest.TestCase): sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid) sc.start() - t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) - cls.http_threads.append(t) - t.start() - cls.btc_addr = callnoderpc( 0, "getnewaddress", @@ -388,9 +380,6 @@ class Test(unittest.TestCase): except Exception: logging.info("Failed to join coins_update_thread") - for t in cls.http_threads: - t.stop() - t.join() for c in cls.swap_clients: c.finalise() @@ -399,7 +388,6 @@ class Test(unittest.TestCase): cls.part_daemons.clear() cls.btc_daemons.clear() - cls.http_threads.clear() cls.swap_clients.clear() super(Test, cls).tearDownClass() diff --git a/tests/basicswap/extended/test_pivx.py b/tests/basicswap/extended/test_pivx.py index cd87c82..6b4caa9 100644 --- a/tests/basicswap/extended/test_pivx.py +++ b/tests/basicswap/extended/test_pivx.py @@ -42,9 +42,6 @@ from basicswap.basicswap_util import ( from basicswap.util.address import ( toWIF, ) -from basicswap.http_server import ( - HttpThread, -) from tests.basicswap.util import ( read_json_api, ) @@ -58,7 +55,6 @@ from tests.basicswap.common import ( wait_for_unspent, wait_for_in_progress, wait_for_bid_tx_state, - TEST_HTTP_HOST, TEST_HTTP_PORT, BASE_PORT, BASE_RPC_PORT, @@ -318,7 +314,6 @@ class Test(unittest.TestCase): cls.daemons = [] cls.swap_clients = [] - cls.http_threads = [] btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)) if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): @@ -418,10 +413,6 @@ class Test(unittest.TestCase): sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid) sc.start() - t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) - cls.http_threads.append(t) - t.start() - waitForRPC(pivxRpc, delay_event) num_blocks = 1352 # CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height 1351. logging.info("Mining %d pivx blocks", num_blocks) @@ -471,14 +462,10 @@ class Test(unittest.TestCase): stop_test = True cls.update_thread.join() cls.coins_update_thread.join() - for t in cls.http_threads: - t.stop() - t.join() for c in cls.swap_clients: c.finalise() stopDaemons(cls.daemons) - cls.http_threads.clear() cls.swap_clients.clear() cls.daemons.clear() diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index 3914a0c..88e1ddb 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -50,9 +50,6 @@ from basicswap.rpc_xmr import ( from basicswap.interface.xmr import ( XMR_COIN, ) -from basicswap.http_server import ( - HttpThread, -) from tests.basicswap.util import ( make_boolean, post_json_req, @@ -151,7 +148,7 @@ def prepare_swapclient_dir( "debug": True, "zmqhost": "tcp://127.0.0.1", "zmqport": BASE_ZMQ_PORT + node_id, - "htmlhost": "127.0.0.1", + "htmlhost": TEST_HTTP_HOST, "htmlport": TEST_HTTP_PORT + node_id, "network_key": network_key, "network_pubkey": network_pubkey, @@ -320,7 +317,6 @@ class BaseTest(unittest.TestCase): __test__ = False update_thread = None coins_update_thread = None - http_threads = [] swap_clients = [] part_daemons = [] btc_daemons = [] @@ -707,9 +703,6 @@ class BaseTest(unittest.TestCase): # Import a random seed to keep the existing test behaviour. BTC core rescans even with timestamp: now. sc.ci(Coins.BTC).initialiseWallet(random.randbytes(32)) - t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) - cls.http_threads.append(t) - t.start() # Set future block rewards to nowhere (a random address), so wallet amounts stay constant void_block_rewards_pubkey = cls.getRandomPubkey() if cls.restore_instance: @@ -969,9 +962,6 @@ class BaseTest(unittest.TestCase): cls.coins_update_thread.join() except Exception: logging.info("Failed to join coins_update_thread") - for t in cls.http_threads: - t.stop() - t.join() logging.info("Stopping swap clients") for c in cls.swap_clients: c.finalise() @@ -982,7 +972,6 @@ class BaseTest(unittest.TestCase): stopDaemons(cls.btc_daemons) stopDaemons(cls.ltc_daemons) - cls.http_threads.clear() cls.swap_clients.clear() cls.part_daemons.clear() cls.btc_daemons.clear()