import socket import time import threading import ax25 import ax25.socket BASE_CALLSIGN = "KI5QKX-10" NETWORK_NAME = "HAMNET-HOUSTON" BEACON_INTERVAL = 10 # seconds BEACON_CALLSIGN = "CRAPR-0" # Fake IP pool IP_POOL = [ "44.127.254.12", "44.127.254.13", "44.127.254.14", "44.127.254.15" ] LEASE_TIME = 3600 # seconds NETMASK = "24" GATEWAY = "44.127.254.1" DNS_SERVER = "44.127.254.1" active_leases = {} def build_beacon(): return f"0.1|CRAP_BEACON|{BASE_CALLSIGN}|{NETWORK_NAME}" def build_accept(client_callsign, ip_address): return f"0.1|CRAP_ACCEPT|{client_callsign}|{NETWORK_NAME}|{ip_address}/{NETMASK}|{GATEWAY}|{DNS_SERVER}|{LEASE_TIME}" def handle_request(data, addr, sock): parts = data.split('|') if parts[1] == "CRAP_BEACON": return if len(parts) < 4: print(f"Received malformed message from {addr}: {data}") return if parts[1] != "CRAP_REQUEST": print(f"Ignoring non-request message: {data}") return client_callsign = parts[2] network_requested = parts[3] if network_requested != NETWORK_NAME: print(f"Client {client_callsign} requested wrong network ({network_requested}). Ignored.") return print(f"Received join request from {client_callsign} ({addr}).") # Assign IP if client_callsign in active_leases: assigned_ip = active_leases[client_callsign] print(f"Client {client_callsign} already has IP {assigned_ip}.") elif IP_POOL: assigned_ip = IP_POOL.pop(0) active_leases[client_callsign] = assigned_ip print(f"Assigned IP {assigned_ip} to {client_callsign}.") else: print(f"No available IPs for {client_callsign}!") return # Send ACCEPT accept_message = build_accept(client_callsign, assigned_ip) sock.sendto(accept_message.encode('utf-8'), addr) print(f"Sent CRAP_ACCEPT to {client_callsign}.") def beacon_loop(sock): while True: beacon = build_beacon().encode('utf-8') sock.sendto(beacon, (BEACON_CALLSIGN,)) print(f"Sent beacon: {beacon.decode('utf-8')}") time.sleep(BEACON_INTERVAL) def main(): # sock = socket.socket(socket.AF_AX25, socket.SOCK_DGRAM) # Old python networking way sock = ax25.socket.Socket() sock.bind((BASE_CALLSIGN,)) # Bind to our station callsign print(f"Base Station {BASE_CALLSIGN} starting up on {NETWORK_NAME}...") # Start beaconing in a separate thread threading.Thread(target=beacon_loop, args=(sock,), daemon=True).start() while True: data, addr = sock.recvfrom(1024) decoded = data.decode('utf-8') handle_request(decoded, addr, sock) if __name__ == "__main__": main()