Initial port of 3709d2e02bf67ccc272e1f2311e5db125a922ba0 from 'ssh'
Re #17
This commit is contained in:
parent
edddc61fb5
commit
8f9b37add4
|
@ -1505,6 +1505,10 @@ class Transport (threading.Thread):
|
||||||
# indefinitely, creating a GC cycle and not letting Transport ever be
|
# indefinitely, creating a GC cycle and not letting Transport ever be
|
||||||
# GC'd. it's a bug in Thread.)
|
# GC'd. it's a bug in Thread.)
|
||||||
|
|
||||||
|
# Hold reference to 'sys' so we can test sys.modules to detect
|
||||||
|
# interpreter shutdown.
|
||||||
|
self.sys = sys
|
||||||
|
|
||||||
# active=True occurs before the thread is launched, to avoid a race
|
# active=True occurs before the thread is launched, to avoid a race
|
||||||
_active_threads.append(self)
|
_active_threads.append(self)
|
||||||
if self.server_mode:
|
if self.server_mode:
|
||||||
|
@ -1512,94 +1516,102 @@ class Transport (threading.Thread):
|
||||||
else:
|
else:
|
||||||
self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & 0xffffffffL))
|
self._log(DEBUG, 'starting thread (client mode): %s' % hex(long(id(self)) & 0xffffffffL))
|
||||||
try:
|
try:
|
||||||
self.packetizer.write_all(self.local_version + '\r\n')
|
try:
|
||||||
self._check_banner()
|
self.packetizer.write_all(self.local_version + '\r\n')
|
||||||
self._send_kex_init()
|
self._check_banner()
|
||||||
self._expect_packet(MSG_KEXINIT)
|
self._send_kex_init()
|
||||||
|
self._expect_packet(MSG_KEXINIT)
|
||||||
|
|
||||||
while self.active:
|
while self.active:
|
||||||
if self.packetizer.need_rekey() and not self.in_kex:
|
if self.packetizer.need_rekey() and not self.in_kex:
|
||||||
self._send_kex_init()
|
self._send_kex_init()
|
||||||
try:
|
try:
|
||||||
ptype, m = self.packetizer.read_message()
|
ptype, m = self.packetizer.read_message()
|
||||||
except NeedRekeyException:
|
except NeedRekeyException:
|
||||||
continue
|
|
||||||
if ptype == MSG_IGNORE:
|
|
||||||
continue
|
|
||||||
elif ptype == MSG_DISCONNECT:
|
|
||||||
self._parse_disconnect(m)
|
|
||||||
self.active = False
|
|
||||||
self.packetizer.close()
|
|
||||||
break
|
|
||||||
elif ptype == MSG_DEBUG:
|
|
||||||
self._parse_debug(m)
|
|
||||||
continue
|
|
||||||
if len(self._expected_packet) > 0:
|
|
||||||
if ptype not in self._expected_packet:
|
|
||||||
raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype))
|
|
||||||
self._expected_packet = tuple()
|
|
||||||
if (ptype >= 30) and (ptype <= 39):
|
|
||||||
self.kex_engine.parse_next(ptype, m)
|
|
||||||
continue
|
continue
|
||||||
|
if ptype == MSG_IGNORE:
|
||||||
if ptype in self._handler_table:
|
continue
|
||||||
self._handler_table[ptype](self, m)
|
elif ptype == MSG_DISCONNECT:
|
||||||
elif ptype in self._channel_handler_table:
|
self._parse_disconnect(m)
|
||||||
chanid = m.get_int()
|
|
||||||
chan = self._channels.get(chanid)
|
|
||||||
if chan is not None:
|
|
||||||
self._channel_handler_table[ptype](chan, m)
|
|
||||||
elif chanid in self.channels_seen:
|
|
||||||
self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid)
|
|
||||||
else:
|
|
||||||
self._log(ERROR, 'Channel request for unknown channel %d' % chanid)
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.packetizer.close()
|
self.packetizer.close()
|
||||||
elif (self.auth_handler is not None) and (ptype in self.auth_handler._handler_table):
|
break
|
||||||
self.auth_handler._handler_table[ptype](self.auth_handler, m)
|
elif ptype == MSG_DEBUG:
|
||||||
|
self._parse_debug(m)
|
||||||
|
continue
|
||||||
|
if len(self._expected_packet) > 0:
|
||||||
|
if ptype not in self._expected_packet:
|
||||||
|
raise SSHException('Expecting packet from %r, got %d' % (self._expected_packet, ptype))
|
||||||
|
self._expected_packet = tuple()
|
||||||
|
if (ptype >= 30) and (ptype <= 39):
|
||||||
|
self.kex_engine.parse_next(ptype, m)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ptype in self._handler_table:
|
||||||
|
self._handler_table[ptype](self, m)
|
||||||
|
elif ptype in self._channel_handler_table:
|
||||||
|
chanid = m.get_int()
|
||||||
|
chan = self._channels.get(chanid)
|
||||||
|
if chan is not None:
|
||||||
|
self._channel_handler_table[ptype](chan, m)
|
||||||
|
elif chanid in self.channels_seen:
|
||||||
|
self._log(DEBUG, 'Ignoring message for dead channel %d' % chanid)
|
||||||
|
else:
|
||||||
|
self._log(ERROR, 'Channel request for unknown channel %d' % chanid)
|
||||||
|
self.active = False
|
||||||
|
self.packetizer.close()
|
||||||
|
elif (self.auth_handler is not None) and (ptype in self.auth_handler._handler_table):
|
||||||
|
self.auth_handler._handler_table[ptype](self.auth_handler, m)
|
||||||
|
else:
|
||||||
|
self._log(WARNING, 'Oops, unhandled type %d' % ptype)
|
||||||
|
msg = Message()
|
||||||
|
msg.add_byte(chr(MSG_UNIMPLEMENTED))
|
||||||
|
msg.add_int(m.seqno)
|
||||||
|
self._send_message(msg)
|
||||||
|
except SSHException, e:
|
||||||
|
self._log(ERROR, 'Exception: ' + str(e))
|
||||||
|
self._log(ERROR, util.tb_strings())
|
||||||
|
self.saved_exception = e
|
||||||
|
except EOFError, e:
|
||||||
|
self._log(DEBUG, 'EOF in transport thread')
|
||||||
|
#self._log(DEBUG, util.tb_strings())
|
||||||
|
self.saved_exception = e
|
||||||
|
except socket.error, e:
|
||||||
|
if type(e.args) is tuple:
|
||||||
|
emsg = '%s (%d)' % (e.args[1], e.args[0])
|
||||||
else:
|
else:
|
||||||
self._log(WARNING, 'Oops, unhandled type %d' % ptype)
|
emsg = e.args
|
||||||
msg = Message()
|
self._log(ERROR, 'Socket exception: ' + emsg)
|
||||||
msg.add_byte(chr(MSG_UNIMPLEMENTED))
|
self.saved_exception = e
|
||||||
msg.add_int(m.seqno)
|
except Exception, e:
|
||||||
self._send_message(msg)
|
self._log(ERROR, 'Unknown exception: ' + str(e))
|
||||||
except SSHException, e:
|
self._log(ERROR, util.tb_strings())
|
||||||
self._log(ERROR, 'Exception: ' + str(e))
|
self.saved_exception = e
|
||||||
self._log(ERROR, util.tb_strings())
|
_active_threads.remove(self)
|
||||||
self.saved_exception = e
|
for chan in self._channels.values():
|
||||||
except EOFError, e:
|
chan._unlink()
|
||||||
self._log(DEBUG, 'EOF in transport thread')
|
if self.active:
|
||||||
#self._log(DEBUG, util.tb_strings())
|
self.active = False
|
||||||
self.saved_exception = e
|
self.packetizer.close()
|
||||||
except socket.error, e:
|
if self.completion_event != None:
|
||||||
if type(e.args) is tuple:
|
self.completion_event.set()
|
||||||
emsg = '%s (%d)' % (e.args[1], e.args[0])
|
if self.auth_handler is not None:
|
||||||
else:
|
self.auth_handler.abort()
|
||||||
emsg = e.args
|
for event in self.channel_events.values():
|
||||||
self._log(ERROR, 'Socket exception: ' + emsg)
|
event.set()
|
||||||
self.saved_exception = e
|
try:
|
||||||
except Exception, e:
|
self.lock.acquire()
|
||||||
self._log(ERROR, 'Unknown exception: ' + str(e))
|
self.server_accept_cv.notify()
|
||||||
self._log(ERROR, util.tb_strings())
|
finally:
|
||||||
self.saved_exception = e
|
self.lock.release()
|
||||||
_active_threads.remove(self)
|
self.sock.close()
|
||||||
for chan in self._channels.values():
|
except:
|
||||||
chan._unlink()
|
# Don't raise spurious 'NoneType has no attribute X' errors when we
|
||||||
if self.active:
|
# wake up during interpreter shutdown. Or rather -- raise
|
||||||
self.active = False
|
# everything *if* sys.modules (used as a convenient sentinel)
|
||||||
self.packetizer.close()
|
# appears to still exist.
|
||||||
if self.completion_event != None:
|
if self.sys.modules is not None:
|
||||||
self.completion_event.set()
|
raise
|
||||||
if self.auth_handler is not None:
|
|
||||||
self.auth_handler.abort()
|
|
||||||
for event in self.channel_events.values():
|
|
||||||
event.set()
|
|
||||||
try:
|
|
||||||
self.lock.acquire()
|
|
||||||
self.server_accept_cv.notify()
|
|
||||||
finally:
|
|
||||||
self.lock.release()
|
|
||||||
self.sock.close()
|
|
||||||
|
|
||||||
|
|
||||||
### protocol stages
|
### protocol stages
|
||||||
|
|
Loading…
Reference in New Issue