1068
class SocketDelay(object):
1069
"""A socket decorator to make TCP appear slower.
1071
This changes recv, send, and sendall to add a fixed latency to each python
1072
call if a new roundtrip is detected. That is, when a recv is called and the
1073
flag new_roundtrip is set, latency is charged. Every send and send_all
1076
In addition every send, sendall and recv sleeps a bit per character send to
1079
Not all methods are implemented, this is deliberate as this class is not a
1080
replacement for the builtin sockets layer. fileno is not implemented to
1081
prevent the proxy being bypassed.
1085
_proxied_arguments = dict.fromkeys([
1086
"close", "getpeername", "getsockname", "getsockopt", "gettimeout",
1087
"setblocking", "setsockopt", "settimeout", "shutdown"])
1089
def __init__(self, sock, latency, bandwidth=1.0,
1092
:param bandwith: simulated bandwith (MegaBit)
1093
:param really_sleep: If set to false, the SocketDelay will just
1094
increase a counter, instead of calling time.sleep. This is useful for
1095
unittesting the SocketDelay.
1098
self.latency = latency
1099
self.really_sleep = really_sleep
1100
self.time_per_byte = 1 / (bandwidth / 8.0 * 1024 * 1024)
1101
self.new_roundtrip = False
1104
if self.really_sleep:
1107
SocketDelay.simulated_time += s
1109
def __getattr__(self, attr):
1110
if attr in SocketDelay._proxied_arguments:
1111
return getattr(self.sock, attr)
1112
raise AttributeError("'SocketDelay' object has no attribute %r" %
1116
return SocketDelay(self.sock.dup(), self.latency, self.time_per_byte,
1119
def recv(self, *args):
1120
data = self.sock.recv(*args)
1121
if data and self.new_roundtrip:
1122
self.new_roundtrip = False
1123
self.sleep(self.latency)
1124
self.sleep(len(data) * self.time_per_byte)
1127
def sendall(self, data, flags=0):
1128
if not self.new_roundtrip:
1129
self.new_roundtrip = True
1130
self.sleep(self.latency)
1131
self.sleep(len(data) * self.time_per_byte)
1132
return self.sock.sendall(data, flags)
1134
def send(self, data, flags=0):
1135
if not self.new_roundtrip:
1136
self.new_roundtrip = True
1137
self.sleep(self.latency)
1138
bytes_sent = self.sock.send(data, flags)
1139
self.sleep(bytes_sent * self.time_per_byte)
1068
1143
class SFTPServer(Server):
1069
1144
"""Common code for SFTP server facilities."""
1086
1162
"""StubServer uses this to log when a new server is created."""
1087
1163
self.logs.append(message)
1165
def _run_server_entry(self, sock):
1166
"""Entry point for all implementations of _run_server.
1168
If self.add_latency is > 0.000001 then sock is given a latency adding
1171
if self.add_latency > 0.000001:
1172
sock = SocketDelay(sock, self.add_latency)
1173
return self._run_server(sock)
1089
1175
def _run_server(self, s):
1090
1176
ssh_server = paramiko.Transport(s)
1091
1177
key_file = pathjoin(self._homedir, 'test_rsa.key')