#! /usr/bin/env python3

import socket
import sys
import time

__doc__ = sys.argv[0]+' - A simple UDP Echo server\nSynopsis:\n\t'+sys.argv[0]+''' PORT

Introduction:
\tThis program would read 1024 bytes from an incoming UDP connection,
\tthen reply with time, origin IP, and the same data.

Copyright:
\t(C) Copyleft 2020 S. aureus
\tThis program is licensed under GPLv3 or any later version.'''

__version__ = '1.0'

def udpEcho(port, bind_addr = '0.0.0.0', ctype=socket.AF_INET):
    sock = socket.socket(ctype,socket.SOCK_DGRAM)
    sock.bind((bind_addr,port))
    print('['+str(int(time.time()))+']\tListening to '+bind_addr+':'+str(port)+' for '+('all','IPv4')[ctype==socket.AF_INET]+' UDP packets.')
    while True:
        data, addr = sock.recvfrom(1024)
        printaddr = (addr[0][7:],addr[1]) if addr[0][:7] == '::ffff:' else addr
        print('['+str(int(time.time()))+']\tReceived a UDP packet from',printaddr[0]+':'+str(printaddr[1]))
        try:
            sock.sendto(b'time: '+str(int(time.time())).encode('ascii')+b'\nsrc: '+printaddr[0].encode('ascii')+b':'+str(addr[1]).encode('ascii')+b'\ndata: '+data,addr)
        except KeyboardInterrupt:
            break
        except Exception as e:
            print('['+str(int(time.time()))+']\tSocket send to '+addr[0]+':'+str(addr[1])+' failed with Exception: '+str(e))

def main(argv):
    if len(argv) == 0 or argv[0] in ('-h','--help','-?'):
        print(__doc__)
    elif argv[0] in ('-v','--version'):
        print(sys.argv[0]+' version: '+__version__)
    else:
        p = int(argv[0])
        if sys.version_info[0] != 3 or sys.version_info[1] < 8:
            ## NAIVE Guessing
            socket.has_dualstack_ipv6 = lambda : socket.has_ipv6
        if socket.has_dualstack_ipv6():
            udpEcho(p,'::',socket.AF_INET6)
        else:
            udpEcho(p)

if __name__ == '__main__':
    main(sys.argv[1:])
