vssh 3.6.6__tar.gz → 3.6.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vssh
3
- Version: 3.6.6
3
+ Version: 3.6.8
4
4
  Summary: Secure SSH/SCP tool with Tailscale failover, P2P transport, and MCP server
5
5
  Author-email: MeshPOP <mpop@mpop.dev>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vssh"
7
- version = "3.6.6"
7
+ version = "3.6.8"
8
8
  description = "Secure SSH/SCP tool with Tailscale failover, P2P transport, and MCP server"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vssh
3
- Version: 3.6.6
3
+ Version: 3.6.8
4
4
  Summary: Secure SSH/SCP tool with Tailscale failover, P2P transport, and MCP server
5
5
  Author-email: MeshPOP <mpop@mpop.dev>
6
6
  License: MIT
@@ -4017,7 +4017,7 @@ Env: VSSH_SECRET
4017
4017
  result['info'] = json.loads(buf.decode())
4018
4018
  except (json.JSONDecodeError, ValueError, UnicodeDecodeError) as e:
4019
4019
  pass # e silenced
4020
- s.close()
4020
+ s.close() # Always close — was only in full_mode, causing 13 dangling sockets on regular status
4021
4021
  except OSError:
4022
4022
  pass # safe to ignore
4023
4023
  return result
@@ -4030,7 +4030,25 @@ Env: VSSH_SECRET
4030
4030
 
4031
4031
  online = 0
4032
4032
  total = 0
4033
- # Run checks in parallel for speed
4033
+ # Pre-warm WireGuard tunnels BEFORE status checks.
4034
+ # Fires short-timeout TCP probes to all peers simultaneously → triggers
4035
+ # WireGuard handshakes, then waits 1.2 s for them to finish.
4036
+ # By the time real checks run, all tunnels are warm → zero handshakes
4037
+ # during status → no disruption of the caller's active session.
4038
+ _peer_ips = [ip for ip in _servers.values() if ip and ip != _my_vpn_ip]
4039
+ def _prewarm(ip):
4040
+ try:
4041
+ _pw = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4042
+ _pw.settimeout(0.15)
4043
+ _pw.connect((ip, PORT))
4044
+ _pw.close()
4045
+ except Exception:
4046
+ pass
4047
+ with concurrent.futures.ThreadPoolExecutor(max_workers=len(_peer_ips) or 1) as _wp:
4048
+ list(_wp.map(_prewarm, _peer_ips))
4049
+ time.sleep(1.2) # wait for WireGuard handshakes to complete
4050
+
4051
+ # Run checks in parallel for speed — tunnels are warm, no handshakes
4034
4052
  results = []
4035
4053
  with concurrent.futures.ThreadPoolExecutor(max_workers=14) as pool:
4036
4054
  futures = {pool.submit(_check_node, n, ip): n for n, ip in sorted(_servers.items()) if ip}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes