104 lines
4.2 KiB
Python
104 lines
4.2 KiB
Python
import socket
|
|
|
|
from logica.red.servidor import APP_FIRMA, PUERTO_BROADCAST
|
|
|
|
|
|
def descubrir_servidores(timeout_sin_nuevos=10, callback=None, on_seen=None, stop_event=None):
|
|
"""Escucha broadcasts UDP para encontrar servidores disponibles.
|
|
|
|
- callback(ip, puerto): llamado cuando se descubre un servidor nuevo.
|
|
- on_seen(ip, puerto): llamado en cada broadcast valido (nuevos y ya conocidos).
|
|
- timeout_sin_nuevos: segundos sin nuevos servidores antes de parar (default 10).
|
|
- stop_event: threading.Event para cancelar la busqueda desde fuera.
|
|
Retorna una lista de tuplas (ip, puerto).
|
|
"""
|
|
import time
|
|
print(f"[DEBUG CLI] Iniciando descubrimiento UDP en puerto {PUERTO_BROADCAST} (timeout_sin_nuevos={timeout_sin_nuevos}s)")
|
|
servidores = []
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
if hasattr(socket, "SO_REUSEPORT"):
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
|
sock.settimeout(1)
|
|
try:
|
|
sock.bind(("", PUERTO_BROADCAST))
|
|
print(f"[DEBUG CLI] Socket UDP enlazado a '':{PUERTO_BROADCAST}")
|
|
except OSError as e:
|
|
print(f"[DEBUG CLI] Error al enlazar UDP: {e}")
|
|
sock.close()
|
|
return servidores
|
|
|
|
ultimo_encontrado = time.time()
|
|
try:
|
|
while True:
|
|
if stop_event and stop_event.is_set():
|
|
print(f"[DEBUG CLI] Busqueda cancelada externamente")
|
|
break
|
|
if time.time() - ultimo_encontrado >= timeout_sin_nuevos:
|
|
print(f"[DEBUG CLI] {timeout_sin_nuevos}s sin nuevos servidores, finalizando")
|
|
break
|
|
try:
|
|
datos, direccion = sock.recvfrom(1024)
|
|
mensaje = datos.decode("utf-8")
|
|
print(f"[DEBUG CLI] Paquete UDP recibido de {direccion}: {mensaje!r}")
|
|
if verificar_firma(mensaje):
|
|
partes = mensaje.split("|")
|
|
if len(partes) == 2:
|
|
puerto_servidor = int(partes[1])
|
|
ip = direccion[0]
|
|
if on_seen:
|
|
on_seen(ip, puerto_servidor)
|
|
entrada = (ip, puerto_servidor)
|
|
if entrada not in servidores:
|
|
servidores.append(entrada)
|
|
ultimo_encontrado = time.time()
|
|
print(f"[DEBUG CLI] Servidor descubierto: {ip}:{puerto_servidor}")
|
|
if callback:
|
|
callback(ip, puerto_servidor)
|
|
else:
|
|
print(f"[DEBUG CLI] Firma no valida, ignorado")
|
|
except socket.timeout:
|
|
pass
|
|
finally:
|
|
sock.close()
|
|
|
|
print(f"[DEBUG CLI] Descubrimiento finalizado: {len(servidores)} servidor(es)")
|
|
return servidores
|
|
|
|
|
|
def conectar_servidor(ip, puerto, clave_acceso):
|
|
"""Conecta al servidor y envia la clave de autenticacion.
|
|
|
|
La clave debe tener el formato: puerto#contraseña_alfabetica
|
|
"""
|
|
print(f"[DEBUG CLI] Conectando TCP a {ip}:{puerto}")
|
|
print(f"[DEBUG CLI] Clave a enviar: {clave_acceso!r}")
|
|
cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
cliente.settimeout(10)
|
|
|
|
try:
|
|
cliente.connect((ip, puerto))
|
|
print(f"[DEBUG CLI] Conexion TCP establecida")
|
|
cliente.sendall(clave_acceso.encode("utf-8"))
|
|
print(f"[DEBUG CLI] Clave enviada, esperando respuesta...")
|
|
respuesta = cliente.recv(1024).decode("utf-8")
|
|
print(f"[DEBUG CLI] Respuesta recibida: {respuesta!r}")
|
|
except (OSError, socket.timeout) as e:
|
|
print(f"[DEBUG CLI] Error en conexion/autenticacion: {e}")
|
|
cliente.close()
|
|
return None, ""
|
|
|
|
if respuesta.startswith("OK"):
|
|
cliente.settimeout(None)
|
|
extra = respuesta[2:]
|
|
print(f"[DEBUG CLI] Autenticacion exitosa, datos extra: {extra!r}")
|
|
return cliente, extra
|
|
else:
|
|
print(f"[DEBUG CLI] Autenticacion fallida: {respuesta!r}")
|
|
cliente.close()
|
|
return None, ""
|
|
|
|
|
|
def verificar_firma(mensaje):
|
|
"""Verifica que el mensaje recibido contenga la firma de la aplicacion."""
|
|
return APP_FIRMA in mensaje |