feat: Tunnel Manager

linuztx committed May 15, 2025 at 09:08 UTC 43b3af5902c974ee3d719cfa4370fef616fc7cb0
1 file changed +74
python/helpers/tunnel_manager.py new
+74
@@ -0,0 +1,74 @@
1 +from flaredantic import FlareTunnel, FlareConfig
2 +import threading
3 +
4 +# Singleton to manage the tunnel instance
5 +class TunnelManager:
6 + _instance = None
7 + _lock = threading.Lock()
8 +
9 + @classmethod
10 + def get_instance(cls):
11 + with cls._lock:
12 + if cls._instance is None:
13 + cls._instance = cls()
14 + return cls._instance
15 +
16 + def __init__(self):
17 + self.tunnel = None
18 + self.tunnel_url = None
19 + self.is_running = False
20 +
21 + def start_tunnel(self, port=5000):
22 + """Start a new tunnel or return the existing one's URL"""
23 + if self.is_running and self.tunnel_url:
24 + return self.tunnel_url
25 +
26 + # Create and start a new tunnel
27 + config = FlareConfig(
28 + port=port,
29 + verbose=True,
30 + timeout=60 # Increase timeout from default 30 to 60 seconds
31 + )
32 +
33 + try:
34 + # Start tunnel in a separate thread to avoid blocking
35 + def run_tunnel():
36 + try:
37 + self.tunnel = FlareTunnel(config)
38 + self.tunnel.start()
39 + self.tunnel_url = self.tunnel.tunnel_url
40 + self.is_running = True
41 + except Exception as e:
42 + print(f"Error in tunnel thread: {str(e)}")
43 +
44 + tunnel_thread = threading.Thread(target=run_tunnel)
45 + tunnel_thread.daemon = True
46 + tunnel_thread.start()
47 +
48 + # Wait for tunnel to start (max 15 seconds instead of 5)
49 + for _ in range(150): # Increased from 50 to 150 iterations
50 + if self.tunnel_url:
51 + break
52 + import time
53 + time.sleep(0.1)
54 +
55 + return self.tunnel_url
56 + except Exception as e:
57 + print(f"Error starting tunnel: {str(e)}")
58 + return None
59 +
60 + def stop_tunnel(self):
61 + """Stop the running tunnel"""
62 + if self.tunnel and self.is_running:
63 + try:
64 + self.tunnel.stop()
65 + self.is_running = False
66 + self.tunnel_url = None
67 + return True
68 + except Exception:
69 + return False
70 + return False
71 +
72 + def get_tunnel_url(self):
73 + """Get the current tunnel URL if available"""
74 + return self.tunnel_url if self.is_running else None
\ No newline at end of file