#!/usr/bin/env python
# Address Family Independent 'Echo server program'
# http://docs.python.org/lib/socket-example.html
#
# AI_ADDRCONFIG returns addresses this machine has
# support for. If this machine is dual stack -v4|v6
# then it turns on IPv4 -> IPv6 mapping -- which is
# supported on ms vista, *bsd, linux, aix, solaris
# hp-ux but NOT on ms windows/xp
#
# tested with : python 2.5/linux

import socket
import sys
import time

HOST = None               # use all available Ip Address's locally configured
PORT = 50007              # Unassigned port /etc/services
DUALSTACK=True            # Accept clients from ip v4 and v6
s = None

def get_af_name(afn):
    if afn == socket.AF_INET:
        return "AF_INET"
    if afn == socket.AF_INET6:
        return "AF_INET6"
    return "%d" % afn

if socket.has_ipv6:
    print "INFO: system supports IPv6"

for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE|socket.AI_ADDRCONFIG):
    af, socktype, proto, canonname, sa = res
    try:
	s = socket.socket(af, socktype, proto)
    except socket.error, msg:
	s = None
	print "WARN: no support for family type %d" % af
	continue
    try:
        if af == socket.AF_INET6:
            v6_only = s.getsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY)
            if v6_only and DUALSTACK:
                s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
	s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	s.bind(sa)
	s.listen(1)
        print "INFO: listening on af=%s port=%d V6ONLY=%d" % (get_af_name(af), PORT, v6_only)
    except socket.error, msg:
	print "ERROR: (setsockopt)/ bind/listen for af=%d failed, %s" % (af, msg)
	s.close()
	s = None
	continue
    break

if s is None:
    print 'ERROR: connect to port %d failed' % PORT
    sys.exit(1)

while True:
    print "INFO: Type ctrl-c to exit"
    conn, addr = s.accept()
    now = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
    print '%s Connected to %s' % (now, addr)
    data = ""
    print "INFO: reading up to 1024 bytes" 
    data += conn.recv(1024)
    conn.shutdown(socket.SHUT_RD)
    print "INFO: sending reply" 
    conn.send(data)
    conn.shutdown(socket.SHUT_WR)
    conn.close()

