From f183873104ebd114b4b073ce1fdb1ffb21901c4e Mon Sep 17 00:00:00 2001 From: Florian Griffon Date: Wed, 28 May 2025 13:57:47 +0300 Subject: [PATCH] fix: gsm_simulator doesn't need to be restarted every time --- .../DryBox/simulator/gsm_simulator.py | 84 ++++++++++++------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/protocol_prototype/DryBox/simulator/gsm_simulator.py b/protocol_prototype/DryBox/simulator/gsm_simulator.py index cb75e2b..e0cc4d3 100644 --- a/protocol_prototype/DryBox/simulator/gsm_simulator.py +++ b/protocol_prototype/DryBox/simulator/gsm_simulator.py @@ -1,4 +1,3 @@ -#gsm_simulator.py import socket import threading import time @@ -9,50 +8,77 @@ FRAME_SIZE = 1000 FRAME_DELAY = 0.02 clients = [] +clients_lock = threading.Lock() def handle_client(client_sock, client_id): print(f"Starting handle_client for Client {client_id}") - while True: - try: - other_client = clients[1 - client_id] if len(clients) == 2 else None + try: + while True: + other_client = None + with clients_lock: + if len(clients) == 2 and client_id < len(clients): + other_client = clients[1 - client_id] print(f"Client {client_id} waiting for data, other_client exists: {other_client is not None}") - data = client_sock.recv(1024) - if not data: - print(f"Client {client_id} disconnected or no data received") + + try: + data = client_sock.recv(1024) + if not data: + print(f"Client {client_id} disconnected or no data received") + break + if other_client: + for i in range(0, len(data), FRAME_SIZE): + frame = data[i:i + FRAME_SIZE] + other_client.send(frame) + time.sleep(FRAME_DELAY) + print(f"Forwarded {len(data)} bytes from Client {client_id} to Client {1 - client_id}") + except socket.error as e: + print(f"Socket error with Client {client_id}: {e}") break - if other_client: - for i in range(0, len(data), FRAME_SIZE): - frame = data[i:i + FRAME_SIZE] - other_client.send(frame) - time.sleep(FRAME_DELAY) - print(f"Forwarded {len(data)} bytes from Client {client_id} to Client {1 - client_id}") - except Exception as e: - print(f"Error with Client {client_id}: {e}") - break - print(f"Closing connection for Client {client_id}") - client_sock.close() + finally: + print(f"Closing connection for Client {client_id}") + with clients_lock: + if client_id < len(clients) and clients[client_id] == client_sock: + clients.pop(client_id) + print(f"Removed Client {client_id} from clients list") + client_sock.close() def start_simulator(): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((HOST, PORT)) server.listen(2) print(f"GSM Simulator listening on {HOST}:{PORT}...") - while len(clients) < 2: - client_sock, addr = server.accept() - client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # Keep connection alive - clients.append(client_sock) - client_id = len(clients) - 1 - print(f"Client {client_id} connected from {addr}") - threading.Thread(target=handle_client, args=(client_sock, client_id), daemon=True).start() - try: while True: - time.sleep(1) + client_sock, addr = server.accept() + client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # Keep connection alive + with clients_lock: + if len(clients) < 2: + clients.append(client_sock) + client_id = len(clients) - 1 + else: + # Replace a closed socket or reject if both slots are active + replaced = False + for i in range(len(clients)): + if clients[i].fileno() == -1: # Check if socket is closed + clients[i] = client_sock + client_id = i + replaced = True + break + if not replaced: + print(f"Rejecting new client from {addr}: max clients (2) reached") + client_sock.close() + continue + print(f"Client {client_id} connected from {addr}") + threading.Thread(target=handle_client, args=(client_sock, client_id), daemon=True).start() except KeyboardInterrupt: print("Shutting down simulator...") - for client in clients: - client.close() + finally: + with clients_lock: + for client in clients: + client.close() + clients.clear() server.close() if __name__ == "__main__":