From d8113534ead067dd595e0803250fd2bee80cd92d Mon Sep 17 00:00:00 2001 From: JesterDev <105895386+jstrdev@users.noreply.github.com> Date: Mon, 19 Oct 2026 19:32:31 +0200 Subject: [PATCH] v1.18.3 --- LEEME.txt | 8 +++++++- README_EN.txt | 6 +++++- app.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- index.html | 19 ++++++++++++++++--- 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/LEEME.txt b/LEEME.txt index d75de6f..4b69140 100644 --- a/LEEME.txt +++ b/LEEME.txt @@ -1,4 +1,4 @@ -PS5 DIRECTO 1.18.2 +PS5 DIRECTO 1.18.3 ================== (English: see README_EN.txt) @@ -168,6 +168,12 @@ de quien es la culpa cuando va lento. Tambien hay uno solo PC -> PS5 en Ajustes. +NOVEDADES 1.18.3 +- Arreglado "Failed to fetch" y la cola que aparecía y desaparecía: en Windows + podían quedar dos PS5 Directo escuchando en el mismo puerto (por ejemplo al + abrirlo dos veces seguidas). Ahora solo puede haber uno abierto. +- Si la conexión con el programa falla un instante, se reintenta sola. + NOVEDADES 1.18.2 - Crea automáticamente un acceso directo "PS5 Directo" en el escritorio (y en "Enviar a") con el icono del programa. Si lo borras no vuelve a aparecer; si apuntaba a diff --git a/README_EN.txt b/README_EN.txt index e9be772..2f9a026 100644 --- a/README_EN.txt +++ b/README_EN.txt @@ -1,4 +1,4 @@ -PS5 DIRECTO 1.18.2 — USER GUIDE (English) +PS5 DIRECTO 1.18.3 — USER GUIDE (English) ========================================= Paste links (or drag files from your PC) and the tool does the rest: @@ -220,6 +220,10 @@ Settings and queue are stored in %USERPROFILE%\.ps5directo WHAT'S NEW ---------- +1.18.3 - Fixed "Failed to fetch" and the queue appearing and disappearing: on + Windows two PS5 Directo could end up listening on the same port (e.g. + when opened twice in a row). Now only one can be open. Brief + connection hiccups are retried automatically. 1.18.2 - Creates a "PS5 Directo" shortcut on the desktop (and in "Send to") with the program's icon. If you delete it, it won't come back; if it pointed to an old copy, it's fixed. The taskbar shows the new icon. diff --git a/app.py b/app.py index 528f091..eff1f46 100644 --- a/app.py +++ b/app.py @@ -22,7 +22,7 @@ HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import engine as E # noqa: E402 -VERSION = "1.18.2" +VERSION = "1.18.3" # Repositorio de GitHub donde se publican las versiones (usuario/nombre). Si lo rellenas, # todas las copias buscan actualizaciones ahi sin tener que configurar nada. DEFAULT_REPO = "jstrdev/ps5directo" @@ -2893,10 +2893,48 @@ def locate_files(files, budget=12.0, max_depth=6): return found +class Server(ThreadingHTTPServer): + """En Windows, SO_REUSEADDR deja que DOS programas escuchen en el mismo puerto y las + peticiones se reparten al azar entre los dos ("Failed to fetch", la cola que aparece y + desaparece). Aqui el puerto es exclusivo.""" + allow_reuse_address = os.name != "nt" + daemon_threads = True + + def server_bind(self): + if os.name == "nt" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"): + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) + super().server_bind() + + +LOCK_PORT = 8776 +_instance_lock = [] + + +def take_instance_lock(wait=0.0): + """Solo un PS5 Directo a la vez: se queda con un puerto fijo mientras funciona. + Devuelve False si otro ya lo tiene (tras esperar hasta `wait` segundos).""" + end = time.time() + wait + while True: + s = socket.socket() + try: + if os.name == "nt" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"): + s.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) + s.bind(("127.0.0.1", LOCK_PORT)) + _instance_lock.append(s) + return True + except OSError: + s.close() + if time.time() >= end: + return False + time.sleep(0.25) + + def pick_port(): for port in (8777, 8778, 8779, 0): s = socket.socket() try: + if os.name == "nt" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"): + s.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) s.bind(("127.0.0.1", port)) p = s.getsockname()[1] s.close() @@ -3103,6 +3141,16 @@ def main(): ses = running_session(full=True) if ses and replace_other_version(ses): ses = None + if not ses and not take_instance_lock(wait=30 if "--after-update" in sys.argv else 4): + # otro PS5 Directo esta arrancando ahora mismo (doble clic, por ejemplo): uso ese + for _ in range(40): + ses = running_session(full=True) + if ses: + break + time.sleep(0.25) + if not ses: + print("Ya hay otro PS5 Directo abierto") + sys.exit(3) if ses: ses = ses[:2] if paths: @@ -3120,7 +3168,7 @@ def main(): for target in (transfer_worker, extract_worker): threading.Thread(target=target, daemon=True).start() port = pick_port() - srv = ThreadingHTTPServer(("127.0.0.1", port), Handler) + srv = Server(("127.0.0.1", port), Handler) try: os.makedirs(DATA_DIR, exist_ok=True) with open(SESSION_FILE, "w", encoding="utf-8") as f: diff --git a/index.html b/index.html index 479b660..83d0fb3 100644 --- a/index.html +++ b/index.html @@ -407,7 +407,7 @@ tr:hover .rowact{opacity:1}