#!/usr/bin/env python3
import socket, struct, sys, time, os

port = int(sys.argv[1])
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('0.0.0.0', port))
log = open('/tmp/udpecho.log', 'a', buffering=1)
log.write('%s listen %d\n' % (time.strftime('%H:%M:%S'), port))
SIZES = (100, 500, 1000, 1200, 1250, 1280, 1300, 1350, 1400, 1450, 1472)

while True:
    d, a = s.recvfrom(65535)
    log.write('%s recv %5d from %s:%d head=%r\n' % (time.strftime('%H:%M:%S'), len(d), a[0], a[1], d[:12]))
    if d.startswith(b'PINGDOWN'):
        log.write('%s downlink test from %s:%d\n' % (time.strftime('%H:%M:%S'), a[0], a[1]))
        for sz in SIZES:
            payload = struct.pack('>H', sz) + os.urandom(max(0, sz - 2))
            try:
                s.sendto(payload, a)
            except Exception as e:
                log.write('%s send error sz=%d %s\n' % (time.strftime('%H:%M:%S'), sz, e))
            time.sleep(0.05)
        log.write('%s downlink test sent\n' % time.strftime('%H:%M:%S'))
    elif d.startswith(b'UPLINK'):
        sz = struct.unpack('>H', d[2:4])[0] if len(d) >= 4 else -1
        log.write('%s UPLINK_OK declared=%d actual=%d\n' % (time.strftime('%H:%M:%S'), sz, len(d)))
