95 lines
2.6 KiB
Python
95 lines
2.6 KiB
Python
import socket
|
|
import time
|
|
import threading
|
|
|
|
BROADCAST_IP = "127.0.0.1"
|
|
PORT = 4444
|
|
|
|
BEACON_INTERVAL = 10 # seconds
|
|
BASE_CALLSIGN = "KI5QKX-10"
|
|
NETWORK_NAME = "HAMNET-HOUSTON"
|
|
|
|
# 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, (BROADCAST_IP, PORT))
|
|
print(f"Sent beacon: {beacon.decode('utf-8')}")
|
|
time.sleep(BEACON_INTERVAL)
|
|
|
|
def main():
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
# sock.bind((BROADCAST_IP, PORT))
|
|
|
|
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()
|