apply threading and ax.25 to client
This commit is contained in:
parent
bef2415ee7
commit
523c4ac958
@ -1,82 +1,114 @@
|
||||
import socket
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
import threading
|
||||
import os
|
||||
import logging
|
||||
import logging.handlers
|
||||
import socket
|
||||
import ax25
|
||||
import ax25.ports
|
||||
import ax25.socket
|
||||
|
||||
# Settings
|
||||
CLIENT_CALLSIGN = "N0CALL-7"
|
||||
BEACON_CALLSIGN = "KI5QKX-10" # We expect the server to be beaconing from here
|
||||
|
||||
# Setup logging
|
||||
os.makedirs("logs", exist_ok=True)
|
||||
logger = logging.getLogger("craprniac_client")
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
log_handler = logging.handlers.TimedRotatingFileHandler(
|
||||
"logs/craprniac_client.log",
|
||||
when="midnight",
|
||||
interval=1,
|
||||
backupCount=7
|
||||
)
|
||||
log_handler.setFormatter(logging.Formatter(
|
||||
"%(asctime)s [%(levelname)s] %(message)s"
|
||||
))
|
||||
logger.addHandler(log_handler)
|
||||
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(logging.Formatter(
|
||||
"%(asctime)s [%(levelname)s] %(message)s"
|
||||
))
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
# Globals for network state
|
||||
configured = False
|
||||
lease_expiration = None
|
||||
|
||||
def parse_message(data):
|
||||
parts = data.split('|')
|
||||
return parts
|
||||
|
||||
# Packet builders
|
||||
def build_request(network_name):
|
||||
return f"0.1|CRAP_REQUEST|{CLIENT_CALLSIGN}|{network_name}"
|
||||
return f"0.1|CRAP_REQUEST|{CLIENT_CALLSIGN}|{network_name}".encode('utf-8')
|
||||
|
||||
# Apply network configuration (mock)
|
||||
def apply_network_config(assigned_ip, gateway, dns, lease_time):
|
||||
global configured, lease_expiration
|
||||
print("\n[Network Configuration]")
|
||||
print(f" Bringing up interface: ax0")
|
||||
print(f" Assigned IP address: {assigned_ip}")
|
||||
print(f" Default Gateway: {gateway}")
|
||||
print(f" DNS Server: {dns}")
|
||||
print(f" Lease Time: {lease_time} seconds")
|
||||
print(" Interface ax0 configured successfully! 🚀")
|
||||
print("----------------------------------------")
|
||||
|
||||
logger.info(f"Applying network config:")
|
||||
logger.info(f" Assigned IP: {assigned_ip}")
|
||||
logger.info(f" Gateway: {gateway}")
|
||||
logger.info(f" DNS Server: {dns}")
|
||||
logger.info(f" Lease Time: {lease_time} seconds")
|
||||
configured = True
|
||||
lease_expiration = time.time() + int(lease_time)
|
||||
|
||||
def main():
|
||||
# Reset network configuration (mock)
|
||||
def reset_network_config():
|
||||
global configured, lease_expiration
|
||||
logger.info("Resetting network configuration (lease expired)")
|
||||
configured = False
|
||||
lease_expiration = None
|
||||
|
||||
sock = socket.socket(socket.AF_AX25, socket.SOCK_DGRAM)
|
||||
sock.bind((CLIENT_CALLSIGN,)) # Bind to our own callsign
|
||||
|
||||
print(f"Client {CLIENT_CALLSIGN} listening for CRAPRNIAC beacons...")
|
||||
# Main Client Logic
|
||||
def main():
|
||||
# Setup DGRAM socket to listen for beacons
|
||||
beacon_sock = ax25.socket.Socket(socket.SOCK_DGRAM)
|
||||
beacon_sock.bind(CLIENT_CALLSIGN)
|
||||
|
||||
logger.info(f"Client {CLIENT_CALLSIGN} started and waiting for beacons...")
|
||||
|
||||
while True:
|
||||
# Check lease expiration
|
||||
if configured and lease_expiration and time.time() >= lease_expiration:
|
||||
print("\n[Lease Expired]")
|
||||
print(" Tearing down interface ax0...")
|
||||
print(" Ready to rejoin network.")
|
||||
print("----------------------------------------")
|
||||
configured = False
|
||||
lease_expiration = None
|
||||
try:
|
||||
if configured and lease_expiration and time.time() >= lease_expiration:
|
||||
reset_network_config()
|
||||
|
||||
data, addr = sock.recvfrom(1024)
|
||||
decoded = data.decode('utf-8')
|
||||
parts = parse_message(decoded)
|
||||
data, src_callsign = beacon_sock.recvfrom(1024) # recvfrom, not recv
|
||||
parts = data.decode('utf-8').split('|')
|
||||
|
||||
if len(parts) < 2:
|
||||
continue
|
||||
|
||||
if parts[1] == "CRAP_BEACON":
|
||||
if not configured:
|
||||
if len(parts) < 2:
|
||||
continue
|
||||
|
||||
if parts[1] == "CRAP_BEACON" and not configured:
|
||||
base_callsign = parts[2]
|
||||
network_name = parts[3]
|
||||
print(f"\nHeard beacon from {base_callsign} ({addr}):")
|
||||
print(f" Network: {network_name}")
|
||||
print("Sending join request...")
|
||||
request = build_request(network_name).encode('utf-8')
|
||||
sock.sendto(request, (base_callsign,))
|
||||
|
||||
elif parts[1] == "CRAP_ACCEPT":
|
||||
client_callsign = parts[2]
|
||||
network_name = parts[3]
|
||||
assigned_ip = parts[4]
|
||||
gateway = parts[5]
|
||||
dns = parts[6]
|
||||
lease_time = parts[7]
|
||||
print(f"\nReceived CRAP_ACCEPT:")
|
||||
print(f" Assigned IP: {assigned_ip}")
|
||||
print(f" Gateway: {gateway}")
|
||||
print(f" DNS Server: {dns}")
|
||||
print(f" Lease Time: {lease_time} seconds")
|
||||
logger.info(f"Received beacon from {base_callsign} (network {network_name})")
|
||||
|
||||
apply_network_config(assigned_ip, gateway, dns, lease_time)
|
||||
# Now create a connection socket for CRAP_REQUEST
|
||||
session_sock = ax25.socket.Socket() # SOCK_STREAM by default
|
||||
session_sock.bind(CLIENT_CALLSIGN)
|
||||
session_sock.connect(base_callsign)
|
||||
session_sock.send(build_request(network_name))
|
||||
logger.info(f"Sent CRAP_REQUEST to {base_callsign}")
|
||||
|
||||
response = session_sock.recv(1024)
|
||||
parts = response.decode('utf-8').split('|')
|
||||
|
||||
if parts[1] == "CRAP_ACCEPT":
|
||||
assigned_ip = parts[4]
|
||||
gateway = parts[5]
|
||||
dns = parts[6]
|
||||
lease_time = parts[7]
|
||||
logger.info(f"Received CRAP_ACCEPT from {base_callsign}")
|
||||
apply_network_config(assigned_ip, gateway, dns, lease_time)
|
||||
|
||||
session_sock.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Client error: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user