From 961525f3d8381b9cfc717f01c5c44cec83649106 Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Mon, 22 Nov 2004 07:04:31 +0000 Subject: [PATCH] [project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-111] fix extremely unlikely channel counter wrapping Transport's channel counter can overflow after 4 billion some channels are created. make it wrap back around after 16 million instead. also allow the logging channel to be set manually. fix some comments elsewhere. --- paramiko/channel.py | 5 ----- paramiko/primes.py | 4 ++-- paramiko/transport.py | 27 +++++++++++++++++++++++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/paramiko/channel.py b/paramiko/channel.py index 9b7384e..b725a03 100644 --- a/paramiko/channel.py +++ b/paramiko/channel.py @@ -592,11 +592,6 @@ class Channel (object): self._send_eof() - ### overrides - - - - ### calls from Transport diff --git a/paramiko/primes.py b/paramiko/primes.py index 8c7e0a6..f380995 100644 --- a/paramiko/primes.py +++ b/paramiko/primes.py @@ -29,7 +29,7 @@ import util def _generate_prime(bits, randpool): "primtive attempt at prime generation" hbyte_mask = pow(2, bits % 8) - 1 - while 1: + while True: # loop catches the case where we increment n into a higher bit-range x = randpool.get_bytes((bits+7) // 8) if hbyte_mask > 0: @@ -54,7 +54,7 @@ def _roll_random(randpool, n): # power of 2), we have slightly better than 50% odds of getting one that # fits, so i can't guarantee that this loop will ever finish, but the odds # of it looping forever should be infinitesimal. - while 1: + while True: x = randpool.get_bytes(bytes) if hbyte_mask > 0: x = chr(ord(x[0]) & hbyte_mask) + x[1:] diff --git a/paramiko/transport.py b/paramiko/transport.py index 678cb6d..0eb9c7c 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -511,10 +511,13 @@ class BaseTransport (threading.Thread): if not self.active: # don't bother trying to allocate a channel return None + self.lock.acquire() try: - self.lock.acquire() chanid = self.channel_counter - self.channel_counter += 1 + while self.channels.has_key(chanid): + self.channel_counter = (self.channel_counter + 1) & 0xffffff + chanid = self.channel_counter + self.channel_counter = (self.channel_counter + 1) & 0xffffff m = Message() m.add_byte(chr(MSG_CHANNEL_OPEN)) m.add_string(kind) @@ -800,6 +803,19 @@ class BaseTransport (threading.Thread): finally: self.lock.release() + def set_log_channel(self, name): + """ + Set the channel for this transport's logging. The default is + C{"paramiko.transport"} but it can be set to anything you want. + (See the C{logging} module for more info.) + + @param name: new channel name for logging. + @type name: str + + @since: 1.1 + """ + self.logger = logging.getLogger(name) + ### internals... @@ -1437,10 +1453,13 @@ class BaseTransport (threading.Thread): reject = True reason = OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED else: + self.lock.acquire() try: - self.lock.acquire() my_chanid = self.channel_counter - self.channel_counter += 1 + while self.channels.has_key(my_chanid): + self.channel_counter = (self.channel_counter + 1) & 0xffffff + my_chanid = self.channel_counter + self.channel_counter = (self.channel_counter + 1) & 0xffffff finally: self.lock.release() reason = self.server_object.check_channel_request(kind, my_chanid)