summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobey Pointer <robey@lag.net>2004-06-10 17:55:17 +0000
committerRobey Pointer <robey@lag.net>2004-06-10 17:55:17 +0000
commitcba104ce3f83ef7844ae9598502a974a36ce8682 (patch)
treeecd2eaad0d39fb72ed7fcfae77fdc1d308ca9b26
parent1144a5d3d9232535d722d9ccded40ad28dbf341d (diff)
[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-58]
some Channel fixes for max packet size & blocking on zero window some clean-ups and fixes to channels: * when send() is blocked on a zero-width window, check that the channel is still open. this was causing some lockups. * set a lower bound to the "maximum packet size" we accept from the remote host. if they tell us anything less than 1KB, assume they meant 1KB. (it's not reasonable to fragment below that.) * leave a little padding instead of cutting right up to the maximum packet size: some space will be taken up by protocol overhead. * turn off some of the debug log lines unless "ultra_debug" is on (nobody cares about the feed info)
-rw-r--r--paramiko/channel.py37
1 files changed, 26 insertions, 11 deletions
diff --git a/paramiko/channel.py b/paramiko/channel.py
index 2f5968d7..b5fbde27 100644
--- a/paramiko/channel.py
+++ b/paramiko/channel.py
@@ -15,7 +15,7 @@
# details.
#
# You should have received a copy of the GNU Lesser General Public License
-# along with Foobar; if not, write to the Free Software Foundation, Inc.,
+# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
"""
@@ -52,6 +52,9 @@ class Channel (object):
is exactly like a normal network socket, so it shouldn't be too surprising.
"""
+ # lower bound on the max packet size we'll accept from the remote host
+ MIN_PACKET_SIZE = 1024
+
def __init__(self, chanid):
"""
Create a new channel. The channel is not associated with any
@@ -71,6 +74,7 @@ class Channel (object):
self.in_buffer = ''
self.timeout = None
self.closed = False
+ self.ultra_debug = False
self.lock = threading.Lock()
self.in_buffer_cv = threading.Condition(self.lock)
self.out_buffer_cv = threading.Condition(self.lock)
@@ -390,10 +394,10 @@ class Channel (object):
by L{settimeout}.
"""
size = 0
- if self.closed or self.eof_sent:
- return size
try:
self.lock.acquire()
+ if self.closed or self.eof_sent:
+ return 0
if self.out_window_size == 0:
# should we block?
if self.timeout == 0.0:
@@ -401,6 +405,8 @@ class Channel (object):
# loop here in case we get woken up but a different thread has filled the buffer
timeout = self.timeout
while self.out_window_size == 0:
+ if self.closed or self.eof_sent:
+ return 0
then = time.time()
self.out_buffer_cv.wait(timeout)
if timeout != None:
@@ -413,14 +419,16 @@ class Channel (object):
size = len(s)
if self.out_window_size < size:
size = self.out_window_size
- if self.out_max_packet_size < size:
- size = self.out_max_packet_size
+ if self.out_max_packet_size - 64 < size:
+ size = self.out_max_packet_size - 64
m = Message()
m.add_byte(chr(MSG_CHANNEL_DATA))
m.add_int(self.remote_chanid)
m.add_string(s[:size])
self.transport._send_message(m)
self.out_window_size -= size
+ if self.ultra_debug:
+ self._log(DEBUG, 'window down to %d' % self.out_window_size)
finally:
self.lock.release()
return size
@@ -612,12 +620,14 @@ class Channel (object):
# threshold of bytes we receive before we bother to send a window update
self.in_window_threshold = window_size // 10
self.in_window_sofar = 0
+ self._log(DEBUG, 'Max packet in: %d bytes' % max_packet_size)
def _set_remote_channel(self, chanid, window_size, max_packet_size):
self.remote_chanid = chanid
self.out_window_size = window_size
- self.out_max_packet_size = max_packet_size
+ self.out_max_packet_size = max(max_packet_size, self.MIN_PACKET_SIZE)
self.active = 1
+ self._log(DEBUG, 'Max packet out: %d bytes' % max_packet_size)
def _request_success(self, m):
self._log(DEBUG, 'Sesch channel %d request ok' % self.chanid)
@@ -630,13 +640,15 @@ class Channel (object):
s = m.get_string()
try:
self.lock.acquire()
- self._log(DEBUG, 'fed %d bytes' % len(s))
+ if self.ultra_debug:
+ self._log(DEBUG, 'fed %d bytes' % len(s))
if self.pipe_wfd != None:
self._feed_pipe(s)
else:
self.in_buffer += s
self.in_buffer_cv.notifyAll()
- self._log(DEBUG, '(out from feed)')
+ if self.ultra_debug:
+ self._log(DEBUG, '(out from feed)')
finally:
self.lock.release()
@@ -644,7 +656,8 @@ class Channel (object):
nbytes = m.get_int()
try:
self.lock.acquire()
- self._log(DEBUG, 'window up %d' % nbytes)
+ if self.ultra_debug or True:
+ self._log(DEBUG, 'window up %d' % nbytes)
self.out_window_size += nbytes
self.out_buffer_cv.notifyAll()
finally:
@@ -832,10 +845,12 @@ class Channel (object):
# already holding the lock!
if self.closed or self.eof_received or not self.active:
return
- self._log(DEBUG, 'addwindow %d' % n)
+ if self.ultra_debug:
+ self._log(DEBUG, 'addwindow %d' % n)
self.in_window_sofar += n
if self.in_window_sofar > self.in_window_threshold:
- self._log(DEBUG, 'addwindow send %d' % self.in_window_sofar)
+ if self.ultra_debug:
+ self._log(DEBUG, 'addwindow send %d' % self.in_window_sofar)
m = Message()
m.add_byte(chr(MSG_CHANNEL_WINDOW_ADJUST))
m.add_int(self.remote_chanid)