# Laurent GUERBY 20120304
# on server 91.224.148.1
# while true; do date;python iperf.py -s 5555 ; sleep 1; done
# on client source route from 192.168.88.221
# T=t1; for i in 5 8 ; do for j in 400 1200; do N=z-$T-$i-$j.csv; python iperf.py -a 192.168.88.221 -c 91.224.148.1:5555 -d ${i}.0e6 -l $j -n 2000 >& $N; tail -5 $N; sleep 1; done;done

import time
import os
import sys
import socket
import select
import struct
import random

N=256*256*256*256-1
S=160000
random.seed(0)
random_s="".join([struct.pack("I",random.randint(0,N)) for i in xrange(S/4)])

host=None
port=None
addr=""
mode=None
RBUFL=10000
BYE="BYE"
PL=1200 # packet of 1200 bytes content
TR=1.0e6 # Mbit/s
NP=1000 # number of packets

opt_l=sys.argv[1:]
while len(opt_l)>0:
    opt=opt_l.pop(0)
    if opt=="-c":
        host,port=opt_l.pop(0).split(":")
        port=int(port)
        peer=(host,port)
        mode="client"
    elif opt=="-s":
        host=None
        port=int(opt_l.pop(0))
        mode="server"
    elif opt=="-a":
        addr=opt_l.pop(0)
    elif opt=="-d":
        TR=float(opt_l.pop(0))
    elif opt=="-l":
        PL=int(opt_l.pop(0))
    elif opt=="-n":
        NP=int(opt_l.pop(0))

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sleep_delay=PL*8.0/TR
PLOVER=16+20+8 # 8*2 byte seq and stamp, 20 byte IP header, 8 byte UDP header
PL2=PL-PLOVER

print mode,host,port,addr,sleep_delay*1.0e6,PL,TR


info_l=[]

if mode=="server":
    s.bind((addr, port))
    p,peer=s.recvfrom(RBUFL)
    PL,TR,NP=struct.unpack("IfI",p)
    sleep_delay=PL*8.0/TR
    PL2=PL-PLOVER
    print peer,sleep_delay,PL,TR,NP
    seq_n=0
    rand_i=0
    t0=time.time()
    for i in xrange(NP):
        tt=time.time()
        t1=int((tt-0)*1.0e6)
        seq_n+=1
        buf=struct.pack("QQ%ds"%PL2,seq_n,t1,random_s[:PL2])
        s.sendto(buf,peer)
        time.sleep(min(max(0.0,t0+(i+1)*sleep_delay-time.time()),sleep_delay)) # to tt+sleep_delay
    for i in xrange(10):
        s.sendto(BYE,peer)
        time.sleep(0.2)
    
elif mode=="client":
    s.bind((addr, 0))
    s.sendto(struct.pack("IfI",PL,TR,NP),peer)
    t0=time.time()
    while True:
        r = select.select([s],[],[])[0][0]
        if r==s:
            t1=int((time.time()-0)*1.0e6)
            buf,peer2=s.recvfrom(RBUFL)
            if buf==BYE: break
            seq_n,t1p,sd=struct.unpack("QQ%ds"%PL2,buf)
            info_l.append((t1,seq_n,t1p,t1-t1p))
        else:
            print "bad select"
 
    min_t=min([x[3] for x in info_l])
    for t1,seq_n,t1p,td in info_l:
        print "%d,%d,%d,%d,%d"%(t1,seq_n,t1p,td,td-min_t)
    dt=(info_l[-1][0]-info_l[0][0])*1.0e-6
    np=len(info_l)
    print np*PL*8.0/dt,float(np)/dt,TR/PL/8.0,np,PL,TR,NP
