|
Packit |
6d2c1b |
#!/usr/bin/python
|
|
Packit |
6d2c1b |
# Written By: Avner BenHanoch
|
|
Packit |
6d2c1b |
# Date: 2011-01-11
|
|
Packit |
6d2c1b |
#
|
|
Packit |
6d2c1b |
"""
|
|
Packit |
6d2c1b |
A client that use ctrl socket for instructing server to sleep than it send
|
|
Packit |
6d2c1b |
payload on data socket during sleep time.
|
|
Packit |
6d2c1b |
It compares the time the TCP window was blocked to the requested sleep time
|
|
Packit |
6d2c1b |
It exit with success iff these times are close enough
|
|
Packit |
6d2c1b |
In addition, this code tests select on 1 write fd using zero/fixed/infinity timeout
|
|
Packit |
6d2c1b |
"""
|
|
Packit |
6d2c1b |
import socket
|
|
Packit |
6d2c1b |
import select
|
|
Packit |
6d2c1b |
import time
|
|
Packit |
6d2c1b |
import sys
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
HOST = 'alf6' # The remote host
|
|
Packit |
6d2c1b |
if len (sys.argv) > 1: HOST = sys.argv[1]
|
|
Packit |
6d2c1b |
PPORT = 50007 # pyload port
|
|
Packit |
6d2c1b |
CPORT = PPORT + 1 # ctrl port
|
|
Packit |
6d2c1b |
SIZE = 1024 # size of send buf
|
|
Packit |
6d2c1b |
PAYLOAD = '0' * SIZE # payload for send
|
|
Packit |
6d2c1b |
SECSLEEP = 2 # seconds for requesting server to sleep without recveing data
|
|
Packit |
6d2c1b |
SECGRACE = 0.2 # seconds GRACE for mismatch in sleep request vs. actual blocking time
|
|
Packit |
6d2c1b |
WRITEABLE_INDICATION = 100 * 1024 # see block_till_writeable() function below
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
def print_info (msg):
|
|
Packit |
6d2c1b |
print "INFO: ", msg
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
readfds=[]
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
# for the sake of this test, socket is defined writeable if we could
|
|
Packit |
6d2c1b |
# successfully use it for sending 'WRITEABLE_INDICATION' bytes of data
|
|
Packit |
6d2c1b |
def block_till_writeable (sock):
|
|
Packit |
6d2c1b |
sent = 0
|
|
Packit |
6d2c1b |
ret = 0
|
|
Packit |
6d2c1b |
while sent < WRITEABLE_INDICATION:
|
|
Packit |
6d2c1b |
print_info(">>> before select infinity (send-ret=%d, sent=%d)" % (ret, sent))
|
|
Packit |
6d2c1b |
readready,writeready,exceptready = select.select(readfds,[sock],[])
|
|
Packit |
6d2c1b |
if sock in writeready:
|
|
Packit |
6d2c1b |
print_info("<<< after select infinity, sock is writeable (sent=%d)" % sent)
|
|
Packit |
6d2c1b |
ret = sock.send(PAYLOAD)
|
|
Packit |
6d2c1b |
sent += ret
|
|
Packit |
6d2c1b |
else:
|
|
Packit |
6d2c1b |
raise Exception("no writeable socket after select infinity")
|
|
Packit |
6d2c1b |
#sys.stdin.read(1)
|
|
Packit |
6d2c1b |
return sent
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#ctrl socket
|
|
Packit |
6d2c1b |
csocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
Packit |
6d2c1b |
csocket.connect((HOST, CPORT))
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#payload socket
|
|
Packit |
6d2c1b |
psocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
Packit |
6d2c1b |
psocket.connect((HOST, PPORT))
|
|
Packit |
6d2c1b |
psocket.setblocking(0)
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#instruct peer to sleep
|
|
Packit |
6d2c1b |
print_info("instructing peer to sleep %f seconds and flooding it with data" % SECSLEEP)
|
|
Packit |
6d2c1b |
csocket.send(str(SECSLEEP)) #ctrl
|
|
Packit |
6d2c1b |
# flood sleeping peer with data
|
|
Packit |
6d2c1b |
size = 0
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
print_info(">>> before select (size=%d)" % size)
|
|
Packit |
6d2c1b |
readready,writeready,exceptready = select.select(readfds,[psocket],[], 0)
|
|
Packit |
6d2c1b |
print_info("<<< after select (size=%d)" % size)
|
|
Packit |
6d2c1b |
while psocket in writeready:
|
|
Packit |
6d2c1b |
ret = psocket.send(PAYLOAD)
|
|
Packit |
6d2c1b |
size += ret
|
|
Packit |
6d2c1b |
if size > 300*1024:
|
|
Packit |
6d2c1b |
raise Exception("socket is always writeable (size=%d)" % size)
|
|
Packit |
6d2c1b |
print_info(">>> before select (send-ret=%d, size=%d)" % (ret, size))
|
|
Packit |
6d2c1b |
readready,writeready,exceptready = select.select(readfds,[psocket],[], 0)
|
|
Packit |
6d2c1b |
print_info("<<< after select (size=%d)" % size)
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#wait till payload socket is ready for write
|
|
Packit |
6d2c1b |
t1 = time.time()
|
|
Packit |
6d2c1b |
print_info("---->>> TCP window was closed after sending %d bytes. Waiting till window is open..." % size )
|
|
Packit |
6d2c1b |
res = block_till_writeable(psocket)
|
|
Packit |
6d2c1b |
t2 = time.time()
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
#check results
|
|
Packit |
6d2c1b |
blocked = t2 - t1
|
|
Packit |
6d2c1b |
diff = abs(SECSLEEP - blocked)
|
|
Packit |
6d2c1b |
print_info ("<<<---- blocked time=%f; requested block=%f" % (blocked, SECSLEEP) )
|
|
Packit |
6d2c1b |
if SECGRACE >= diff:
|
|
Packit |
6d2c1b |
print_info("SUCCESS in test: grace of %f >= diff of %f" % (SECGRACE,diff) )
|
|
Packit |
6d2c1b |
ret = 0
|
|
Packit |
6d2c1b |
else:
|
|
Packit |
6d2c1b |
print_info("FAIL in test: grace of %f < diff of %f" % (SECGRACE,diff) )
|
|
Packit |
6d2c1b |
ret = 255
|
|
Packit |
6d2c1b |
print_info ("[total bytes sent = %d]" % (size + res) )
|
|
Packit |
6d2c1b |
|
|
Packit |
6d2c1b |
psocket.close()
|
|
Packit |
6d2c1b |
csocket.close()
|
|
Packit |
6d2c1b |
sys.exit (ret)
|