feat: early abort on LAN

This commit is contained in:
aclist 2026-02-17 00:35:33 +09:00
parent 7766b4c5c2
commit 59120825dc
3 changed files with 51 additions and 15 deletions

View File

@ -6,6 +6,7 @@ import re
import requests
import socket
import subprocess
import threading
import typing # noqa
from dataclasses import dataclass
@ -56,7 +57,10 @@ def get_netmask() -> str:
return netmask
def test_ip(suffix: int, port: int) -> dict | None:
# TODO: rename
def test_ip(suffix: int, port: int, event: threading.Event) -> dict | None:
if event.is_set():
return
netmask = get_netmask()
hostname = f"{netmask}.{str(suffix)}"
ping = ["ping", "-c1", "-i", "0.1", "-w", "1"]

View File

@ -436,34 +436,45 @@ class Controller(GObject.GObject):
parsed = Servers.parse_json(serv)
self.push_data_success(parsed, FilterMode.INITIAL)
def dump_lan(self, port: int) -> None:
# TODO: strings
@call_on_thread("scanning LAN ports")
def dump_lan(self, port: int, early_abort: bool) -> None:
serv = []
event = threading.Event()
with ThreadPoolExecutor() as executor:
futures = [executor.submit(Servers.test_ip, i, port) for i in range(1, 256)]
futures = [
executor.submit(Servers.test_ip, i, port, event) for i in range(1, 256)
]
for future in as_completed(futures):
try:
res = future.result(timeout=3)
res = future.result(timeout=0.5)
if res is not None and early_abort is True:
event.set()
self.cleanup_func = StoredFunc(self.cleanup_on_failure)
return
if res is None:
continue
serv.panned(res)
if len(serv) == 0:
serv.append(res)
except Exception as e:
logger.critical(e)
self.cleanup_func = StoredFunc(self.cleanup_on_failure)
return
if len(serv) == 0:
self.cleanup_func = StoredFunc(self.cleanup_on_failure)
return
parsed = Servers.parse_json(serv)
self.push_data_success(parsed, FilterMode.INITIAL)
def dump_api(self) -> None:
key = self.query_config(Preferences.STEAM)
job = Servers.query_api
params = Servers.params
serv = []
#i = 0
# i = 0
with ThreadPoolExecutor() as executor:
futures = [executor.submit(job, key, APPID_DAYZ, param) for param in params]
for future in as_completed(futures):
try:
#i += 1
# i += 1
GLib.idle_add(lambda: self.wait_dialog.increment())
res = future.result(timeout=3)
if res.status != 200 or not res.parsed:
@ -477,6 +488,7 @@ class Controller(GObject.GObject):
return
# NOTE: This step is allowed to fail, since this metadata is incidental
print("now checking exp servers")
res = Servers.query_api(key, APPID_DAYZ_EXP, "")
if res.status == 200 and res.parsed is True:
j = res.json

View File

@ -31,32 +31,52 @@ class LanPanel(Gtk.Frame):
label = BoldLabel(lan_panel.heading)
self.set_label_widget(label)
radio1 = Gtk.RadioButton.new_with_label(None, lan_panel.default_button)
self.radio1 = Gtk.RadioButton.new_with_label(None, lan_panel.default_button)
radio2 = Gtk.RadioButton.new_with_label_from_widget(
radio1, lan_panel.custom_button
self.radio1, lan_panel.custom_button
)
self.entry = PortEntry(controller)
self.scan = Gtk.Button(label=lan_panel.scan_button)
self.scan.connect("clicked", self._on_scan_clicked)
# TODO: strings
self.early_abort = Gtk.CheckButton("Stop scanning on first hit")
self.early_abort.set_active(True)
self.early_abort.set_tooltip_text(
"Unless you have multiple DayZ servers on your LAN,\nleave this checked to get results faster"
)
self.entry.connect("string_validated", self._on_port_validated)
self.emitter.connect(
"request_lan_entry_focus", lambda _: self.entry.grab_focus()
)
radio1.connect("toggled", self._on_radio_toggled)
self.radio1.connect("toggled", self._on_radio_toggled)
self.grid = Gtk.Grid(margin=10, vexpand=False, column_spacing=15, row_spacing=5)
self.grid.attach(radio1, 0, 0, COLS, ROWS)
self.grid.attach_next_to(radio2, radio1, Gtk.PositionType.RIGHT, COLS, ROWS)
self.grid.attach(self.radio1, 0, 0, COLS, ROWS)
self.grid.attach_next_to(
radio2, self.radio1, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.grid.attach_next_to(self.entry, radio2, Gtk.PositionType.RIGHT, COLS, ROWS)
self.grid.attach_next_to(
self.scan, self.entry, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.grid.attach_next_to(
self.early_abort, self.scan, Gtk.PositionType.RIGHT, COLS, ROWS
)
self.add(self.grid)
self.entry.set_sensitive(False)
def _on_scan_clicked(self, button: Gtk.Button) -> None:
if self.radio1.get_active():
port = 27016
else:
port = self.entry.get_text()
abort = self.early_abort.get_active()
self.controller.dump_lan(int(port), abort)
def _on_radio_toggled(self, button: Gtk.RadioButton) -> None:
state = button.get_active()
self.entry.set_sensitive(not state)