vssh 3.6.8__tar.gz → 3.7.1__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.8
3
+ Version: 3.7.1
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.8"
7
+ version = "3.7.1"
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.8
3
+ Version: 3.7.1
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
@@ -96,7 +96,7 @@ def _load_tailscale_map() -> dict:
96
96
  ips = [ip for ip in peer.get('TailscaleIPs', []) if ':' not in ip]
97
97
  if name and ips:
98
98
  ts_host[name] = ips[0]
99
- for srv_ip in ['10.99.85.143', '158.247.247.115']:
99
+ for srv_ip in WIRE_SERVERS:
100
100
  try:
101
101
  with _ur.urlopen(f'http://{srv_ip}:8790/peers', timeout=3) as r:
102
102
  for p in json.loads(r.read()).get('peers', []):
@@ -159,8 +159,9 @@ def vssh_connect(host: str, timeout: float = 5.0) -> socket.socket:
159
159
  pass # Timeout — WireGuard may be re-handshaking, retry once
160
160
 
161
161
  if not _wire_refused:
162
- # Retry: wait 1s for WireGuard handshake to complete, then retry
163
- time.sleep(1.0)
162
+ # Retry: wait 300ms for WireGuard handshake to complete, then retry
163
+ # (WireGuard handshake typically completes in <200ms; 1s was too slow)
164
+ time.sleep(0.3)
164
165
  try:
165
166
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
166
167
  sock.settimeout(min(timeout, 5.0)) # 5s: handshake should be done by now
@@ -527,7 +528,22 @@ def check_transfer_safety(host: str) -> bool:
527
528
 
528
529
 
529
530
  # Wire VPN coordinator servers for name resolution
530
- WIRE_SERVERS = ["10.99.85.143", "158.247.247.115", "10.99.74.131", "10.99.249.158"]
531
+ # Dynamically read from /etc/wire/config.json (server_url field)
532
+ # Falls back to hardcoded list only if config is missing
533
+ def _load_wire_servers() -> list:
534
+ import json as _json, re as _re
535
+ try:
536
+ with open("/etc/wire/config.json") as _f:
537
+ _cfg = _json.load(_f)
538
+ _url = _cfg.get("server_url", "")
539
+ _m = _re.match(r'https?://([^:/]+)', _url)
540
+ if _m:
541
+ return [_m.group(1)]
542
+ except (OSError, ValueError, KeyError):
543
+ pass
544
+ return []
545
+
546
+ WIRE_SERVERS = _load_wire_servers()
531
547
  _name_cache = {} # name -> vpn_ip
532
548
  _name_cache_time = 0
533
549
 
@@ -2479,6 +2495,8 @@ def pty_session(host: str, name: str = ''):
2479
2495
  if not data:
2480
2496
  raise EOFError
2481
2497
  sock.sendall(data)
2498
+ except BlockingIOError:
2499
+ pass # send buffer full, drop keystroke (rare)
2482
2500
  except (EOFError, BrokenPipeError):
2483
2501
  raise EOFError
2484
2502
  elif r == sock:
@@ -2500,7 +2518,7 @@ def pty_session(host: str, name: str = ''):
2500
2518
  if old_settings:
2501
2519
  try:
2502
2520
  import termios as _termios
2503
- _termios.tcsetattr(sys.stdin.fileno(), _termios.TCSADRAIN, old_settings)
2521
+ _termios.tcsetattr(sys.stdin.fileno(), _termios.TCSAFLUSH, old_settings)
2504
2522
  except Exception:
2505
2523
  pass # safe to ignore
2506
2524
  sock.close()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes