small fix

This commit is contained in:
Zenaku 2026-06-19 06:42:50 -05:00
parent 309ac7bd02
commit e1142c8d24
3 changed files with 64 additions and 47 deletions

View file

@ -2,6 +2,7 @@ import subprocess
import threading import threading
import time import time
from core.utils.encrypted_proxy import killswitch from core.utils.encrypted_proxy import killswitch
from core.utils.encrypted_proxy.singbox import SingboxRunner
drop_state: dict = {"count": 0} drop_state: dict = {"count": 0}
tunnel_state: dict = {"alive": True} tunnel_state: dict = {"alive": True}
@ -17,14 +18,14 @@ class KillswitchMonitor:
LOG_PREFIX = "hydraveil-drop" LOG_PREFIX = "hydraveil-drop"
def __init__(self): def __init__(self):
self._on_disconnect = None self._on_disconnect = None
self._on_leak = None self._on_leak = None
self._on_displaced = None self._on_displaced = None
self._socks5_port = None self._socks5_port = None
self._session_token = None self._session_token = None
self._running = False self._running = False
self._stop_event = threading.Event() self._stop_event = threading.Event()
self._cause_event = threading.Event() self._cause_event = threading.Event()
self._cause: str | None = None self._cause: str | None = None
self._last_poll_ts: str | None = None self._last_poll_ts: str | None = None
@ -86,16 +87,7 @@ class KillswitchMonitor:
self._trigger(CAUSE_DISCONNECT) self._trigger(CAUSE_DISCONNECT)
return return
try: singbox_alive = SingboxRunner().is_running()
result = subprocess.run(
['pgrep', '-x', 'sing-box'],
capture_output=True,
timeout=3,
)
singbox_alive = result.returncode == 0
except (OSError, subprocess.TimeoutExpired):
singbox_alive = True
tunnel_state["alive"] = singbox_alive tunnel_state["alive"] = singbox_alive
if not singbox_alive: if not singbox_alive:

View file

@ -5,30 +5,34 @@ from core.observers.ClientObserver import ClientObserver
from core.observers.ConnectionObserver import ConnectionObserver from core.observers.ConnectionObserver import ConnectionObserver
from core.observers.InvoiceObserver import InvoiceObserver from core.observers.InvoiceObserver import InvoiceObserver
from core.observers.ProfileObserver import ProfileObserver from core.observers.ProfileObserver import ProfileObserver
from cli.ui import Spinner, label_ok, label_error, label_warn, label_connected, label_disconnect, progress_bar, label_killswitch, label_dns from cli.ui import (
Spinner, label_ok, label_error, label_warn,
label_connected, label_disconnect, label_killswitch,
label_dns, label_ipv6, label_ipv4, progress_bar,
)
from cli.helpers import sanitize_profile from cli.helpers import sanitize_profile
from cli.killswitch_monitor import drop_state from cli.killswitch_monitor import drop_state, tunnel_state
import pprint import pprint
application_version_observer = ApplicationVersionObserver() application_version_observer = ApplicationVersionObserver()
client_observer = ClientObserver() client_observer = ClientObserver()
connection_observer = ConnectionObserver() connection_observer = ConnectionObserver()
invoice_observer = InvoiceObserver() invoice_observer = InvoiceObserver()
profile_observer = ProfileObserver() profile_observer = ProfileObserver()
_spinner = None _spinner = None
_monitor = None _monitor = None
_timer_state = None _timer_state = None
application_version_observer.subscribe('downloading', lambda event: print(f'Downloading {ApplicationController.get(event.subject.application_code).name}, version {event.subject.version_number}...')) application_version_observer.subscribe('downloading', lambda event: print(f'Downloading {ApplicationController.get(event.subject.application_code).name}, version {event.subject.version_number}...'))
application_version_observer.subscribe('download_progressing', lambda event: print(f'Current progress: {event.meta.get("progress"):.2f}%', flush=True, end='\r')) application_version_observer.subscribe('download_progressing',lambda event: print(f'Current progress: {event.meta.get("progress"):.2f}%', flush=True, end='\r'))
application_version_observer.subscribe('downloaded', lambda event: print('\n')) application_version_observer.subscribe('downloaded', lambda event: print('\n'))
client_observer.subscribe('synchronizing', lambda event: print('Synchronizing...\n')) client_observer.subscribe('synchronizing', lambda event: print('Synchronizing...\n'))
client_observer.subscribe('updating', lambda event: print('Updating client...')) client_observer.subscribe('updating', lambda event: print('Updating client...'))
client_observer.subscribe('update_progressing', lambda event: print(f'Current progress: {event.meta.get("progress"):.2f}%', flush=True, end='\r')) client_observer.subscribe('update_progressing', lambda event: print(f'Current progress: {event.meta.get("progress"):.2f}%', flush=True, end='\r'))
client_observer.subscribe('updated', lambda event: print('\n')) client_observer.subscribe('updated', lambda event: print('\n'))
def _on_connecting(event): def _on_connecting(event):
@ -41,7 +45,7 @@ def _on_connecting(event):
_timer_state['reconnecting'] = connecting_spinner() _timer_state['reconnecting'] = connecting_spinner()
attempt = event.subject.get("attempt_count", "?") attempt = event.subject.get("attempt_count", "?")
total = event.subject.get("maximum_number_of_attempts", "?") total = event.subject.get("maximum_number_of_attempts", "?")
_spinner = Spinner(f"[net] verify_ip attempt {attempt}/{total}...") _spinner = Spinner(f"Connecting... attempt {attempt}/{total}")
_spinner.start() _spinner.start()
@ -55,20 +59,27 @@ def _on_connected(event):
_timer_state['reconnecting'] = None _timer_state['reconnecting'] = None
if _timer_state: if _timer_state:
_timer_state['_retrying'] = False _timer_state['_retrying'] = False
d = event.subject or {} d = event.subject or {}
label_connected(f"proxy={d.get('proxy_ip','?')} tunnel={d.get('tunnel_if','?')} port={d.get('socks5_port','?')}") tunnel_if = d.get('tunnel_if', '?')
server_ip = d.get('server_ip')
socks5_port = d.get('socks5_port', '?')
label_connected(f"tunnel={tunnel_if} port={socks5_port}")
label_killswitch(killswitch.status()) label_killswitch(killswitch.status())
label_dns( label_dns(
enabled=d.get('dns_enabled', True), enabled=d.get('dns_enabled', True),
active=d.get('dns_active', False), active=d.get('dns_active', False),
) )
label_ipv6(blocked=True)
if server_ip:
label_ipv4(server_ip=server_ip, reachable=True)
if _monitor is not None: if _monitor is not None:
_monitor.set_connection_data( _monitor.set_connection_data(socks5_port=d.get('socks5_port'))
socks5_port=d.get('socks5_port'),
)
if _timer_state is not None: if _timer_state is not None:
from cli.ui import session_timer from cli.ui import session_timer
from cli.killswitch_monitor import tunnel_state
_timer_state['stop'] = session_timer(drop_state=drop_state, tunnel_state=tunnel_state) _timer_state['stop'] = session_timer(drop_state=drop_state, tunnel_state=tunnel_state)
@ -138,11 +149,11 @@ connection_observer.subscribe('tor_bootstrapping', _on_tor_bootstrapping
connection_observer.subscribe('tor_bootstrap_progressing', _on_tor_bootstrap_progressing) connection_observer.subscribe('tor_bootstrap_progressing', _on_tor_bootstrap_progressing)
connection_observer.subscribe('tor_bootstrapped', _on_tor_bootstrapped) connection_observer.subscribe('tor_bootstrapped', _on_tor_bootstrapped)
invoice_observer.subscribe('retrieved', lambda event: print(f'\n{pprint.pp(event.subject)}\n')) invoice_observer.subscribe('retrieved', lambda event: print(f'\n{pprint.pp(event.subject)}\n'))
invoice_observer.subscribe('processing', lambda event: print('A payment has been detected and is being verified...\n')) invoice_observer.subscribe('processing', lambda event: print('A payment has been detected and is being verified...\n'))
invoice_observer.subscribe('settled', lambda event: print('The payment has been successfully verified.\n')) invoice_observer.subscribe('settled', lambda event: print('The payment has been successfully verified.\n'))
profile_observer.subscribe('created', lambda event: pprint.pp((sanitize_profile(event.subject), 'Created'))) profile_observer.subscribe('created', lambda event: pprint.pp((sanitize_profile(event.subject), 'Created')))
profile_observer.subscribe('destroyed', lambda event: pprint.pp((sanitize_profile(event.subject), 'Destroyed'))) profile_observer.subscribe('destroyed', lambda event: pprint.pp((sanitize_profile(event.subject), 'Destroyed')))
profile_observer.subscribe('disabled', lambda event: pprint.pp((sanitize_profile(event.subject), 'Disabled')) if event.meta.get('explicitly') else None) profile_observer.subscribe('disabled', lambda event: pprint.pp((sanitize_profile(event.subject), 'Disabled')) if event.meta.get('explicitly') else None)
profile_observer.subscribe('enabled', lambda event: pprint.pp((sanitize_profile(event.subject), 'Enabled'))) profile_observer.subscribe('enabled', lambda event: pprint.pp((sanitize_profile(event.subject), 'Enabled')))

View file

@ -20,6 +20,7 @@ BBLUE = "\033[1;34m"
BCYAN = "\033[1;36m" BCYAN = "\033[1;36m"
BWHITE = "\033[1;37m" BWHITE = "\033[1;37m"
def label_ok(msg: str): def label_ok(msg: str):
print(f" {BGREEN}[ OK ]{RESET} {msg}") print(f" {BGREEN}[ OK ]{RESET} {msg}")
@ -159,8 +160,21 @@ def label_killswitch(armed: bool):
print(f" {BRED}[ KS ]{RESET} Kill switch {BRED}INACTIVE — connection unprotected{RESET}") print(f" {BRED}[ KS ]{RESET} Kill switch {BRED}INACTIVE — connection unprotected{RESET}")
def session_timer(drop_state: dict | None = None, tunnel_state: dict | None = None) -> threading.Event: def label_ipv6(blocked: bool):
if blocked:
print(f" {BGREEN}[ IPv6 ]{RESET} IPv6 blocked")
else:
print(f" {BYELLOW}[ IPv6 ]{RESET} IPv6 {BYELLOW}not blocked{RESET}")
def label_ipv4(server_ip: str, reachable: bool):
if reachable:
print(f" {BGREEN}[ IPv4 ]{RESET} Server {BGREEN}{server_ip}{RESET} reachable")
else:
print(f" {BRED}[ IPv4 ]{RESET} Server {BRED}{server_ip}{RESET} unreachable")
def session_timer(drop_state: dict | None = None, tunnel_state: dict | None = None) -> threading.Event:
stop_event = threading.Event() stop_event = threading.Event()
start = time.time() start = time.time()
@ -173,7 +187,7 @@ def session_timer(drop_state: dict | None = None, tunnel_state: dict | None = No
time_str = f"{h:02d}:{m:02d}:{s:02d}" time_str = f"{h:02d}:{m:02d}:{s:02d}"
alive = True if tunnel_state is None else tunnel_state.get("alive", True) alive = True if tunnel_state is None else tunnel_state.get("alive", True)
dot_color = BGREEN if alive else BRED dot_color = BGREEN if alive else BRED
status_word = "Protected" if alive else "Disconnected" status_word = "Protected" if alive else "Disconnected"
if drop_state is not None: if drop_state is not None: