This commit is contained in:
Bartosz 2025-04-13 09:07:21 +01:00
parent 6155955cca
commit ae26af0f99
7 changed files with 143 additions and 83 deletions

View File

@ -1,4 +1,14 @@
# Use official Python image
FROM python:3.9-slim
# Set working directory
WORKDIR /app
COPY gsm_simulator.py /app
# Copy the simulator script
COPY gsm_simulator.py .
# Expose the port
EXPOSE 12345
# Run the simulator
CMD ["python", "gsm_simulator.py"]

View File

@ -1,94 +1,58 @@
import socket
import threading
import random
import time
class GSMSimulator:
def __init__(self, host='0.0.0.0', port=5555):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((host, port))
self.server_socket.listen(2)
self.clients = {}
print("GSM Simulator started. Waiting for connections...")
HOST = "0.0.0.0"
PORT = 12345
FRAME_SIZE = 1000
FRAME_DELAY = 0.02
def simulate_signal_strength(self):
return random.uniform(0, 1)
clients = []
def handle_client(self, client_socket, address):
def handle_client(client_sock, client_id):
print(f"Starting handle_client for Client {client_id}")
while True:
try:
client_socket.settimeout(5)
role = client_socket.recv(1024).decode().strip()
if role not in ["CALLER", "RECEIVER"]:
print(f"Invalid role received from {address}: {role}")
client_socket.close()
return
self.clients[role] = client_socket
print(f"{role} connected from {address}")
if role == "CALLER":
self.handle_caller(client_socket)
elif role == "RECEIVER":
self.handle_receiver(client_socket)
except Exception as e:
print(f"Error handling client {address}: {e}")
finally:
if role in self.clients:
del self.clients[role]
client_socket.close()
def handle_caller(self, caller_socket):
print("Caller connected, waiting for receiver...")
while "RECEIVER" not in self.clients:
time.sleep(1)
receiver_socket = self.clients["RECEIVER"]
print("Receiver found, sending RINGING...")
receiver_socket.send("RINGING".encode())
while True:
try:
data = caller_socket.recv(1024).decode().strip()
if not data:
print("Caller disconnected unexpectedly.")
receiver_socket.send("CALL_END".encode())
break
if data == "CALL_END":
print("Call terminated by caller.")
receiver_socket.send("CALL_END".encode())
break
signal = self.simulate_signal_strength()
if signal < 0.2:
print("Call dropped due to low signal strength.")
caller_socket.send("CALL_DROPPED".encode())
receiver_socket.send("CALL_DROPPED".encode())
break
print(f"Relaying to receiver: {data} (Signal: {signal:.2f})")
receiver_socket.send(data.encode())
time.sleep(0.1) # Small delay to ensure data is sent properly
except Exception as e:
print(f"Error in caller loop: {e}")
receiver_socket.send("CALL_END".encode())
other_client = clients[1 - client_id] if len(clients) == 2 else None
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")
break
def handle_receiver(self, receiver_socket):
print("Receiver connected, waiting for data...")
try:
while True:
data = receiver_socket.recv(1024)
if not data:
print("Receiver disconnected.")
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 in receiver loop: {e}")
print(f"Error with Client {client_id}: {e}")
break
print(f"Closing connection for Client {client_id}")
client_sock.close()
def run(self):
def start_simulator():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
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:
client_socket, address = self.server_socket.accept()
print(f"New connection from {address}")
thread = threading.Thread(target=self.handle_client, args=(client_socket, address))
thread.start()
time.sleep(1)
except KeyboardInterrupt:
print("Shutting down simulator...")
for client in clients:
client.close()
server.close()
if __name__ == "__main__":
gsm = GSMSimulator()
gsm.run()
start_simulator()

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,86 @@
import socket
import os
import time
import subprocess
# Configuration
HOST = "localhost"
PORT = 12345
INPUT_FILE = "input.wav"
OUTPUT_FILE = "received.wav"
def encrypt_data(data):
return data # Replace with your encryption protocol
def decrypt_data(data):
return data # Replace with your decryption protocol
def run_protocol(send_mode=True):
"""Connect to the simulator and send/receive data."""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
print(f"Connected to simulator at {HOST}:{PORT}")
if send_mode:
# Sender mode: Encode audio with toast
os.system(f"toast -p -l {INPUT_FILE}") # Creates input.wav.gsm
input_gsm_file = f"{INPUT_FILE}.gsm"
if not os.path.exists(input_gsm_file):
print(f"Error: {input_gsm_file} not created")
sock.close()
return
with open(input_gsm_file, "rb") as f:
voice_data = f.read()
encrypted_data = encrypt_data(voice_data)
sock.send(encrypted_data)
print(f"Sent {len(encrypted_data)} bytes")
os.remove(input_gsm_file) # Clean up
else:
# Receiver mode: Wait for and receive data
print("Waiting for data from sender...")
received_data = b""
sock.settimeout(5.0)
try:
while True:
print("Calling recv()...")
data = sock.recv(1024)
print(f"Received {len(data)} bytes")
if not data:
print("Connection closed by sender or simulator")
break
received_data += data
except socket.timeout:
print("Timed out waiting for data")
if received_data:
with open("received.gsm", "wb") as f:
f.write(decrypt_data(received_data))
print(f"Wrote {len(received_data)} bytes to received.gsm")
# Decode with untoast, then convert to WAV with sox
result = subprocess.run(["untoast", "received.gsm"], capture_output=True, text=True)
print(f"untoast return code: {result.returncode}")
print(f"untoast stderr: {result.stderr}")
if result.returncode == 0:
if os.path.exists("received"):
# Convert raw PCM to WAV (8 kHz, mono, 16-bit)
subprocess.run(["sox", "-t", "raw", "-r", "8000", "-e", "signed", "-b", "16", "-c", "1", "received",
OUTPUT_FILE])
os.remove("received")
print(f"Received and saved {len(received_data)} bytes to {OUTPUT_FILE}")
else:
print("Error: 'received' file not created by untoast")
else:
print(f"untoast failed: {result.stderr}")
else:
print("No data received from simulator")
sock.close()
if __name__ == "__main__":
mode = input("Enter 'send' to send data or 'receive' to receive data: ").strip().lower()
run_protocol(send_mode=(mode == "send"))

Binary file not shown.