summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvery Pennarun <apenwarr@gmail.com>2010-05-02 05:39:17 -0400
committerAvery Pennarun <apenwarr@gmail.com>2010-05-02 05:39:17 -0400
commit6c2dc54b9e93338904495106e34f32eacfb19d94 (patch)
treea907d1b795b5857f24cbc3cc0fafa76f6de552ce
parent5d1390927d7ac323ca33acc9ed91c1a7738bf752 (diff)
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.
-rw-r--r--server.py2
-rw-r--r--ssnet.py24
2 files changed, 17 insertions, 9 deletions
diff --git a/server.py b/server.py
index 7a1c679..09b62d1 100644
--- a/server.py
+++ b/server.py
@@ -43,5 +43,5 @@ def main():
for s in handlers:
if s.socks & ready:
s.callback()
- mux.callback()
mux.check_fullness()
+ mux.callback()
diff --git a/ssnet.py b/ssnet.py
index 964bd34..7afa884 100644
--- a/ssnet.py
+++ b/ssnet.py
@@ -215,6 +215,7 @@ class Mux(Handler):
self.want = 0
self.inbuf = ''
self.outbuf = []
+ self.fullness = 0
self.too_full = False
self.send(0, CMD_PING, 'chicken')
@@ -231,20 +232,24 @@ class Mux(Handler):
return sum(len(b) for b in self.outbuf)
def check_fullness(self):
- self.too_full = (self.amount_queued() > 32768)
- ob = []
- for b in self.outbuf:
- (s1,s2,c) = struct.unpack('!ccH', b[:4])
- ob.append(c)
- log('outbuf: %d %r\n' % (self.amount_queued(), ob,))
+ if self.fullness > 65536:
+ self.too_full = True
+ #ob = []
+ #for b in self.outbuf:
+ # (s1,s2,c) = struct.unpack('!ccH', b[:4])
+ # ob.append(c)
+ #log('outbuf: %d %r\n' % (self.amount_queued(), ob))
def send(self, channel, cmd, data):
data = str(data)
assert(len(data) <= 65535)
p = struct.pack('!ccHHH', 'S', 'S', channel, cmd, len(data)) + data
self.outbuf.append(p)
- debug2(' > channel=%d cmd=%s len=%d\n'
- % (channel, cmd_to_name[cmd], len(data)))
+ debug2(' > channel=%d cmd=%s len=%d (fullness=%d)\n'
+ % (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):
debug2('< channel=%d cmd=%s len=%d\n'
@@ -253,6 +258,8 @@ class Mux(Handler):
self.send(0, CMD_PONG, data)
elif cmd == CMD_PONG:
debug2('received PING response\n')
+ self.too_full = False
+ self.fullness = 0
elif cmd == CMD_EXIT:
self.ok = False
elif cmd == CMD_CONNECT:
@@ -267,6 +274,7 @@ class Mux(Handler):
self.wsock.setblocking(False)
if self.outbuf and 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:
self.outbuf[0] = self.outbuf[0][wrote:]
while self.outbuf and not self.outbuf[0]: