1139
class SocketDelay(object):
1140
"""A socket decorator to make TCP appear slower.
1142
This changes recv, send, and sendall to add a fixed latency to each python
1143
call if a new roundtrip is detected. That is, when a recv is called and the
1144
flag new_roundtrip is set, latency is charged. Every send and send_all
1147
In addition every send, sendall and recv sleeps a bit per character send to
1150
Not all methods are implemented, this is deliberate as this class is not a
1151
replacement for the builtin sockets layer. fileno is not implemented to
1152
prevent the proxy being bypassed.
1156
_proxied_arguments = dict.fromkeys([
1157
"close", "getpeername", "getsockname", "getsockopt", "gettimeout",
1158
"setblocking", "setsockopt", "settimeout", "shutdown"])
1160
def __init__(self, sock, latency, bandwidth=1.0,
1163
:param bandwith: simulated bandwith (MegaBit)
1164
:param really_sleep: If set to false, the SocketDelay will just
1165
increase a counter, instead of calling time.sleep. This is useful for
1166
unittesting the SocketDelay.
1169
self.latency = latency
1170
self.really_sleep = really_sleep
1171
self.time_per_byte = 1 / (bandwidth / 8.0 * 1024 * 1024)
1172
self.new_roundtrip = False
1175
if self.really_sleep:
1178
SocketDelay.simulated_time += s
1180
def __getattr__(self, attr):
1181
if attr in SocketDelay._proxied_arguments:
1182
return getattr(self.sock, attr)
1183
raise AttributeError("'SocketDelay' object has no attribute %r" %
1187
return SocketDelay(self.sock.dup(), self.latency, self.time_per_byte,
1190
def recv(self, *args):
1191
data = self.sock.recv(*args)
1192
if data and self.new_roundtrip:
1193
self.new_roundtrip = False
1194
self.sleep(self.latency)
1195
self.sleep(len(data) * self.time_per_byte)
1198
def sendall(self, data, flags=0):
1199
if not self.new_roundtrip:
1200
self.new_roundtrip = True
1201
self.sleep(self.latency)
1202
self.sleep(len(data) * self.time_per_byte)
1203
return self.sock.sendall(data, flags)
1205
def send(self, data, flags=0):
1206
if not self.new_roundtrip:
1207
self.new_roundtrip = True
1208
self.sleep(self.latency)
1209
bytes_sent = self.sock.send(data, flags)
1210
self.sleep(bytes_sent * self.time_per_byte)
1139
1214
class SFTPServer(Server):
1140
1215
"""Common code for SFTP server facilities."""
1157
1233
"""StubServer uses this to log when a new server is created."""
1158
1234
self.logs.append(message)
1236
def _run_server_entry(self, sock):
1237
"""Entry point for all implementations of _run_server.
1239
If self.add_latency is > 0.000001 then sock is given a latency adding
1242
if self.add_latency > 0.000001:
1243
sock = SocketDelay(sock, self.add_latency)
1244
return self._run_server(sock)
1160
1246
def _run_server(self, s):
1161
1247
ssh_server = paramiko.Transport(s)
1162
1248
key_file = pathjoin(self._homedir, 'test_rsa.key')