fix some certificate
This commit is contained in:
@@ -12,6 +12,7 @@ import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from cert_installer import install_ca, is_ca_trusted
|
||||
@@ -75,6 +76,70 @@ def parse_args():
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def _windows_listener_details(host: str, port: int) -> tuple[str, str] | None:
|
||||
"""Best-effort lookup of the process listening on host:port on Windows."""
|
||||
if os.name != "nt":
|
||||
return None
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["netstat", "-ano", "-p", "tcp"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
port_suffix = f":{port}"
|
||||
host_variants = {
|
||||
f"{host}:{port}",
|
||||
f"0.0.0.0:{port}",
|
||||
f"[::]:{port}",
|
||||
f"[::1]:{port}",
|
||||
f"::{port}",
|
||||
}
|
||||
|
||||
pid = None
|
||||
for line in result.stdout.splitlines():
|
||||
parts = line.split()
|
||||
if len(parts) < 5 or parts[0] != "TCP":
|
||||
continue
|
||||
local_addr, state, candidate_pid = parts[1], parts[3].upper(), parts[4]
|
||||
if state != "LISTENING":
|
||||
continue
|
||||
if local_addr in host_variants or local_addr.endswith(port_suffix):
|
||||
pid = candidate_pid
|
||||
break
|
||||
|
||||
if not pid:
|
||||
return None
|
||||
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["tasklist", "/FI", f"PID eq {pid}", "/FO", "CSV", "/NH"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
line = proc.stdout.strip().splitlines()[0]
|
||||
name = line.split(",")[0].strip('"') if line else "unknown"
|
||||
except Exception:
|
||||
name = "unknown"
|
||||
|
||||
return pid, name
|
||||
|
||||
|
||||
def _is_addr_in_use_error(exc: OSError) -> bool:
|
||||
text = str(exc).lower()
|
||||
return (
|
||||
getattr(exc, "errno", None) in {48, 98, 10048}
|
||||
or getattr(exc, "winerror", None) == 10048
|
||||
or "address already in use" in text
|
||||
or "only one usage of each socket address" in text
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
config_path = args.config
|
||||
@@ -196,6 +261,20 @@ def main():
|
||||
|
||||
try:
|
||||
asyncio.run(ProxyServer(config).start())
|
||||
except OSError as e:
|
||||
if _is_addr_in_use_error(e):
|
||||
host = config.get("listen_host", "127.0.0.1")
|
||||
port = config.get("listen_port", 8080)
|
||||
log.error("Cannot listen on %s:%d because that address is already in use.", host, port)
|
||||
details = _windows_listener_details(host, port)
|
||||
if details:
|
||||
pid, name = details
|
||||
log.error("Port %d is currently held by PID %s (%s).", port, pid, name)
|
||||
log.error(
|
||||
"Stop the other process or choose another port, for example: python main.py -p 9090"
|
||||
)
|
||||
sys.exit(1)
|
||||
raise
|
||||
except KeyboardInterrupt:
|
||||
log.info("Stopped")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user