943
943
class SocketDelay(object):
944
944
"""A socket decorator to make TCP appear slower.
946
This changes recv, send, and sendall to add a fixed latency to each
947
python call. It will therefore behave differently to the real underlying
948
TCP stack which may only pay the latency price on each actual roundtrip
949
rather than each packet initiated. We can come closer to the real
950
behaviour by only charging latency for each roundtrip we detect - that is
951
when recv is called, toggle a flag, and insert latency again only when
952
send has been called in the middle. For now though, showing more latency
953
than we have is probably acceptable.
955
Not all methods are implemented, this is deliberate as this class is not
956
a replacement for the builtin sockets layer. fileno is not implemented to
957
prevent the proxy being bypassed.
946
This changes recv, send, and sendall to add a fixed latency to each python
947
call if a new roundtrip is detected. That is, when a recv is called and the
948
flag new_roundtrip is set, latency is charged. Every send and send_all
951
In addition every send, sendall and recv sleeps a bit per character send to
954
The function used to sleep moves a counter forwards to not make the tests
955
slower. It could be made more clever, by adding the time that was passing
956
between sleep calls to the simulated time too.
958
Not all methods are implemented, this is deliberate as this class is not a
959
replacement for the builtin sockets layer. fileno is not implemented to
960
prevent the proxy being bypassed.
960
def __init__(self, sock, latency):
965
def __init__(self, sock, latency, time_per_char=0.0001,
962
968
self.latency = latency
969
self.really_sleep = really_sleep
970
self.time_per_char = time_per_char
971
self.new_roundtrip = False
974
if self.really_sleep:
976
SocketDelay.simulated_time += s
965
979
return self.sock.close()
968
return SocketDelay(self.sock.dup(), self.latency)
982
return SocketDelay(self.sock.dup(), self.latency, self.time_per_char,
970
985
def getpeername(self, *args):
971
986
return self.sock.getpeername(*args)
982
997
def recv(self, *args):
983
998
data = self.sock.recv(*args)
985
time.sleep(self.latency)
999
if data and self.new_roundtrip:
1000
self.new_roundtrip = False
1001
self.sleep(self.latency)
1002
self.sleep(len(data) * self.time_per_char)
988
def sendall(self, *args):
989
time.sleep(self.latency)
990
return self.sock.sendall(*args)
1005
def sendall(self, data, flags=0):
1006
if not self.new_roundtrip:
1007
self.new_roundtrip = True
1008
self.sleep(self.latency)
1009
self.sleep(len(data) * self.time_per_char)
1010
return self.sock.sendall(data, flags)
992
def send(self, *args):
993
time.sleep(self.latency)
994
return self.sock.send(*args)
1012
def send(self, data, flags=0):
1013
if not self.new_roundtrip:
1014
self.new_roundtrip = True
1015
self.sleep(self.latency)
1016
bytes_sent = self.sock.send(data, flags)
1017
self.sleep(bytes_sent * self.time_per_char)
996
1020
def setblocking(self, *args):
997
1021
return self.sock.setblocking(*args)