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