#!/usr/bin/env python # python client bob LISTEN # arecord -D hw:0 -t raw | python proj/voip/client alice CALL bob | aplay -D hw:0 -t raw - # client -u bob --wait # client -u alice --call bob import socket import sys import re import select import getopt import time import os import fcntl opt = {} def readline(sock): line = "" while True: select.select([sock], [], [], 1) ## needed? ret = sock.recv(1) line += ret if ret == '\n': break return line def get_public_ip_port(sock): sock.sendto("hello", (opt["headerhost"], opt["headerport"])) data, addr = sock.recvfrom(1024) words = data.split(" ") # print "get_public_ip_port ", repr(data) return (words[1], int(words[2])) def udpsweep(sock, ip, low, high): for i in range(low, high): sock.sendto("destination " + ip + " " + str(i)+"\n", (ip, i)) def do_chat(udpsock, peerhost, peerport): if "echo" in opt: while True: data, addr = udpsock.recvfrom(4000) udpsock.sendto(data, (peerhost, peerport)) if "ping" in opt: while True: (i, o, e) = select.select([udpsock], [], [], 1) if udpsock in i: data,addr = udpsock.recvfrom(1024) words = data.split(" ") if words[0] == "ping": start = float(words[1]) end = time.time() print "Received "+str(len(data)) + " bytes in " + str((end-start)*1000) + " msec at " + str(time.time()) else: payload = "ping " + repr(time.time())+ " " + "A"*1500 payload = payload[0:opt["pingsize"]] # at least 32 udpsock.sendto(payload, (peerhost, peerport)) mic = open(opt["in"], 'r') speaker = open(opt["out"], 'w') micbuf = "" speakerbuf = "" while True: outputs = [] if len(speakerbuf) > 0: outputs += [speaker] if len(micbuf) > 0: outputs += [udpsock] (i, o, e) = select.select([mic,udpsock], outputs, [], 1.5) if mic in i: micbuf += os.read(mic.fileno(), 256) if speaker in o and len(speakerbuf) > 0: nwritten = os.write(speaker.fileno(), speakerbuf) speakerbuf = speakerbuf[nwritten:] if udpsock in o and len(micbuf) > 0: udpsock.sendto(micbuf[0:1024], (peerhost, peerport)) micbuf = micbuf[1024:] if udpsock in i: data,addr = udpsock.recvfrom(3000) speakerbuf += data def managerping(): relaysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) relaysock.connect((opt["managerhost"], opt["managerport"])) while True: start = time.time() relaysock.send(("PING "+"A"*1024)[0:opt["pingsize"]-1] + "\n") readline(relaysock) end = time.time() print "Received " + str(opt["pingsize"]) + " bytes in " + str((end-start)*1000) + " msec at " + str(time.time()) time.sleep(1) def chat(): udpsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udpsock.bind(('', 8080)) relaysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) relaysock.connect((opt["managerhost"], opt["managerport"])) relaysock.send("USER "+opt["user"]+"\n") relaysock.send("PASS "+opt["password"]+"\n") if "wait" in opt: line = readline(relaysock) # 100 peer CALL ip port port2 words = line.split(" ") peerhost = words[3] pub = get_public_ip_port(udpsock) relaysock.send("MSG "+words[1]+" TRANSFER "+pub[0]+" "+str(pub[1])+" "+str(pub[1]+opt["portrangelen"])+"\n") readline(relaysock) # SWEEP udpsweep(udpsock, peerhost, int(words[4]), int(words[5])) line = readline(relaysock) # 100 peer PORT port peerport = int(line.split(" ")[3]) else: pub = get_public_ip_port(udpsock) relaysock.send("MSG "+opt["call"]+" CALL "+pub[0]+" "+str(pub[1])+" "+str(pub[1]+opt["portrangelen"])+"\n") line = readline(relaysock) words = line.split(" ") peerhost = words[3] udpsweep(udpsock, peerhost, int(words[4]), int(words[5])) relaysock.send("MSG "+opt["call"]+" SWEEP\n") data, addr = udpsock.recvfrom(1024) print "Received ", repr(data), repr(addr) relaysock.send("MSG "+opt["call"]+" PORT "+data.split(" ")[2]+"\n") peerport = addr[1] # udpsock.sendto("probe 1", (peerhost, peerport)) # data,addr = udpsock.recvfrom(1024) # print "Received ", repr(data), repr(addr) do_chat(udpsock, peerhost, peerport) def usage(): print "example: client -u bob --wait" print " client -u alice --call bob" pass def main(): global opt try: longopts = ["managerhost=","headerhost=","portrangelen=","help","call=","wait","echo","password","in=","out=","ping","pingsize=","managerping"] opts, args = getopt.getopt(sys.argv[1:], "u:h", longopts) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) opt["managerhost"] = "juliano.metsahovi.fi" opt["portrangelen"] = 10 opt["managerport"] = 8080 opt["in"] = "/dev/dsp" opt["out"] = "/dev/dsp" opt["pingsize"] = 64 for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() if o == "-u": opt["user"] = a if o == "--managerhost": opt["managerhost"] = a if o == "--headerhost": opt["headerhost"] = a if o == "--portrangelen": opt["portrangelen"] = int(a) if o == "--call": opt["call"] = a if o == "--wait": opt["wait"] = True if o == "--echo": opt["echo"] = True if o == "--password": opt["password"] = a if o == "--in": if a == "-": a = "/dev/stdin" opt["in"] = a if o == "--out": if a == "-": a = "/dev/stdout" opt["out"] = a if o == "--ping": opt["ping"] = True if o == "--pingsize": opt["pingsize"] = int(a) if opt["pingsize"] < 32: print "pingsize cannot be less than 32" sys.exit() if o == "--managerping": opt["managerping"] = True if "managerping" in opt: managerping() if "user" not in opt: usage() sys.exit() if "call" not in opt and "wait" not in opt: usage() sys.exit() if "headerhost" not in opt: opt["headerhost"] = opt["managerhost"] if "headerport" not in opt: opt["headerport"] = opt["managerport"] if "password" not in opt: opt["password"] = opt["user"] + "secret" print opt chat() main()