Commit 6c2dc54b authored by Avery Pennarun's avatar Avery Pennarun

More latency fixes: use a PING/PONG pair to limit queue length.

It seems ssh is kind of stupid and uses a really big SO_SNDBUF (hundreds of
kbytes).  Thus, we can't depend on the socket's output buffer to limit our
latency down to something reasonable.  Instead, limit the amount of data we
can send in a single round trip.
parent 5d139092
...@@ -43,5 +43,5 @@ def main(): ...@@ -43,5 +43,5 @@ def main():
for s in handlers: for s in handlers:
if s.socks & ready: if s.socks & ready:
s.callback() s.callback()
mux.callback()
mux.check_fullness() mux.check_fullness()
mux.callback()
...@@ -215,6 +215,7 @@ class Mux(Handler): ...@@ -215,6 +215,7 @@ class Mux(Handler):
self.want = 0 self.want = 0
self.inbuf = '' self.inbuf = ''
self.outbuf = [] self.outbuf = []
self.fullness = 0
self.too_full = False self.too_full = False
self.send(0, CMD_PING, 'chicken') self.send(0, CMD_PING, 'chicken')
...@@ -231,20 +232,24 @@ class Mux(Handler): ...@@ -231,20 +232,24 @@ class Mux(Handler):
return sum(len(b) for b in self.outbuf) return sum(len(b) for b in self.outbuf)
def check_fullness(self): def check_fullness(self):
self.too_full = (self.amount_queued() > 32768) if self.fullness > 65536:
ob = [] self.too_full = True
for b in self.outbuf: #ob = []
(s1,s2,c) = struct.unpack('!ccH', b[:4]) #for b in self.outbuf:
ob.append(c) # (s1,s2,c) = struct.unpack('!ccH', b[:4])
log('outbuf: %d %r\n' % (self.amount_queued(), ob,)) # ob.append(c)
#log('outbuf: %d %r\n' % (self.amount_queued(), ob))
def send(self, channel, cmd, data): def send(self, channel, cmd, data):
data = str(data) data = str(data)
assert(len(data) <= 65535) assert(len(data) <= 65535)
p = struct.pack('!ccHHH', 'S', 'S', channel, cmd, len(data)) + data p = struct.pack('!ccHHH', 'S', 'S', channel, cmd, len(data)) + data
self.outbuf.append(p) self.outbuf.append(p)
debug2(' > channel=%d cmd=%s len=%d\n' debug2(' > channel=%d cmd=%s len=%d (fullness=%d)\n'
% (channel, cmd_to_name[cmd], len(data))) % (channel, cmd_to_name[cmd], len(data), self.fullness))
if self.fullness < 32768 and self.fullness+len(data) > 32768:
self.send(0, CMD_PING, 'rttest')
self.fullness += len(data)
def got_packet(self, channel, cmd, data): def got_packet(self, channel, cmd, data):
debug2('< channel=%d cmd=%s len=%d\n' debug2('< channel=%d cmd=%s len=%d\n'
...@@ -253,6 +258,8 @@ class Mux(Handler): ...@@ -253,6 +258,8 @@ class Mux(Handler):
self.send(0, CMD_PONG, data) self.send(0, CMD_PONG, data)
elif cmd == CMD_PONG: elif cmd == CMD_PONG:
debug2('received PING response\n') debug2('received PING response\n')
self.too_full = False
self.fullness = 0
elif cmd == CMD_EXIT: elif cmd == CMD_EXIT:
self.ok = False self.ok = False
elif cmd == CMD_CONNECT: elif cmd == CMD_CONNECT:
...@@ -267,6 +274,7 @@ class Mux(Handler): ...@@ -267,6 +274,7 @@ class Mux(Handler):
self.wsock.setblocking(False) self.wsock.setblocking(False)
if self.outbuf and self.outbuf[0]: if self.outbuf and self.outbuf[0]:
wrote = _nb_clean(os.write, self.wsock.fileno(), self.outbuf[0]) wrote = _nb_clean(os.write, self.wsock.fileno(), self.outbuf[0])
debug2('wrote: %d/%d\n' % (wrote, len(self.outbuf[0])))
if wrote: if wrote:
self.outbuf[0] = self.outbuf[0][wrote:] self.outbuf[0] = self.outbuf[0][wrote:]
while self.outbuf and not self.outbuf[0]: while self.outbuf and not self.outbuf[0]:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment