# natserver.py import os from socket import * from time import strftime import select import sys import thread DEBUG = True # Print usage information def usage() : print "Usage:" print " python natserver.py " # Serve client connections (if server 1 or 2) def servemain(bounceaddr, serveraddr) : # Set up the sockets try : udpsock = socket(AF_INET, SOCK_DGRAM) udpsock.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) udpsock.bind(serveraddr) except error, (errno, strerror) : if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "Could not open socket: %s" % (strerror) sys.stdout.flush() sys.exit(1) try : udpsock.setblocking(0) except error : pass # Loop forever receiving messages and sending pings while 1 : if DEBUG: print >> sys.stderr, serveraddr, "Waiting for connection..." try : ready_to_read, ready_to_write, errors = select.select([udpsock],[],[]) except (KeyboardInterrupt, SystemExit): if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "Exiting ..." sys.exit(1) except select.error, (errno, strerror) : if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "I/O error: %s" % (strerror) sys.exit(1) for i in ready_to_read : if DEBUG: print >> sys.stderr, "Incoming connection..." # Serve udp connections if i == udpsock : BUFSIZ = 1024 try: data, clientaddr = udpsock.recvfrom(BUFSIZ) print >> sys.stderr, strftime("%Y/%m/%d %H:%M:%S"), "...connected from:", clientaddr except error, (errno, strerr) : if DEBUG: print >> sys.stderr, strerr break if data == "ping1" : # The client is running Test I if DEBUG: print >> sys.stderr, "received ping1" reply = "%s:%s" % (clientaddr[0], clientaddr[1]) try: udpsock.sendto(reply, clientaddr) except: break if data == "ping2": # The client is running Test II if DEBUG: print >> sys.stderr, "received ping2" reply = "%s:%s" % (clientaddr[0], clientaddr[1]) try: udpsock.sendto(reply, bounceaddr) except: break if DEBUG: print >> sys.stderr, "bounce request is", reply print >> sys.stderr, "bounce request sent to ", (bounceaddr) if data == "ping3" : # The client is running Test III if DEBUG: print >> sys.stderr, "received ping3" # Create a new socket and bind it to a different port try : #serveraddr2 = (gethostbyname(gethostname()), int(sys.argv[1]) + 5) serveraddr2 = (serveraddr[0], serveraddr[1] + 5) udpsock2 = socket(AF_INET, SOCK_DGRAM) udpsock2.bind(serveraddr2) if DEBUG: print >> sys.stderr, "new socket bind at ", serveraddr2 except error, (errno, strerror) : if udpsock2 : udpsock2.close() if DEBUG: print >> sys.stderr, "Could not open socket: %s" % (strerror) break # Send an echo back to the client using the new socket reply = "%s:%s " % (clientaddr[0], clientaddr[1]) print >> sys.stderr, "send an echo back to the client using the new socket... reply=", reply, "clientaddr=", clientaddr udpsock2.sendto(reply, clientaddr) udpsock2.close() else: if DEBUG: print >> sys.stderr, "data is: ", data try : host, port = data.split(":") except (ValueError) : break try : bouncedest = (host, int(port)) except ValueError : break try: udpsock.sendto(data, bouncedest) except: break if DEBUG: print >> sys.stderr, "Bounceping sent to", bouncedest udpsock.close() # Serve bounce connections def bouncemain(serveraddr) : # Set up the sockets try : udpsock = socket(AF_INET, SOCK_DGRAM) udpsock.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) udpsock.bind(serveraddr) except error, (errno, strerror) : if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "Could not open socket: %s" % (strerror) sys.exit(1) try : udpsock.setblocking(0) except error : pass # Loop forever receiving messages and sending pings while 1 : if DEBUG: print >> sys.stderr, serveraddr, "Waiting for connection..." try : ready_to_read, ready_to_write, errors = select.select([udpsock],[],[]) except (KeyboardInterrupt, SystemExit): if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "Exiting ..." sys.exit(1) except select.error, (errno, strerror) : if udpsock : udpsock.close() if DEBUG: print >> sys.stderr, "I/O error: %s" % (strerror) sys.exit(1) for i in ready_to_read : if DEBUG: print >> sys.stderr, "Incoming connection..." # Serve udp connections if i == udpsock : BUFSIZ = 1024 data, clientaddr = udpsock.recvfrom(BUFSIZ) print >> sys.stderr, strftime("%Y/%m/%d %H:%M:%S"), "...connected from: ", clientaddr if DEBUG: print >> sys.stderr, "data is: ", data try : host, port = data.split(":") except (ValueError) : break try : bouncedest = (host, int(port)) except ValueError : break try: udpsock.sendto(data, bouncedest) except: break if DEBUG: print >> sys.stderr, "Bounceping sent to", bouncedest udpsock.close() if __name__=="__main__" : # Server initialization if len(sys.argv) != (4) : usage() sys.exit(1) bounceaddr = None serveraddr = None try : bounceaddr = (sys.argv[2], int(sys.argv[3])) except ValueError, strerror : if DEBUG: print >> sys.stderr, "ValueError: ", strerror usage() sys.exit(1) try : #serveraddr = (gethostbyname(gethostname()), int(sys.argv[1])) serveraddr = ("0.0.0.0", int(sys.argv[1])) except ValueError, strerror : if DEBUG: print >> sys.stderr, "ValueError: ", strerror usage() sys.exit(1) # Run the appropriate server code while True: try: if DEBUG: print >> sys.stderr, strftime("%Y/%m/%d %H:%M:%S"), "Stun server started" #thread.start_new_thread(servemain, (bounceaddr, serveraddr) ) #bouncemain(serveraddr) servemain(bounceaddr, serveraddr) except (KeyboardInterrupt, SystemExit): if DEBUG: print >> sys.stderr, "Exiting ..." sys.exit(1) #except: #if DEBUG: #print >> sys.stderr, "Unexpected error:", sys.exc_info()[0]