1
# Copyright 2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Patched SSH session for the Launchpad server."""
11
from twisted.conch.ssh import channel, session
14
class PatchedSSHSession(session.SSHSession, object):
15
"""Session adapter that corrects bugs in Conch.
17
This object provides no custom logic for Launchpad, it just addresses some
18
simple bugs in the base `session.SSHSession` class that are not yet fixed
22
def closeReceived(self):
23
# Without this, the client hangs when it's finished transferring.
24
# XXX: JonathanLange 2009-01-05: This does not appear to have a
25
# corresponding bug in Twisted. We should test that the above comment
26
# is indeed correct and then file a bug upstream.
29
def loseConnection(self):
30
# XXX: JonathanLange 2008-03-31: This deliberately replaces the
31
# implementation of session.SSHSession.loseConnection. The default
32
# implementation will try to call loseConnection on the client
33
# transport even if it's None. I don't know *why* it is None, so this
34
# doesn't necessarily address the root cause.
35
# See http://twistedmatrix.com/trac/ticket/2754.
36
transport = getattr(self.client, 'transport', None)
37
if transport is not None:
38
transport.loseConnection()
39
# This is called by session.SSHSession.loseConnection. SSHChannel is
40
# the base class of SSHSession.
41
channel.SSHChannel.loseConnection(self)
43
def stopWriting(self):
44
"""See `session.SSHSession.stopWriting`.
46
When the client can't keep up with us, we ask the child process to
49
# XXX: MichaelHudson 2008-06-27: Being cagey about whether
50
# self.client.transport is entirely paranoia inspired by the comment
51
# in `loseConnection` above. It would be good to know if and why it is
52
# necessary. See http://twistedmatrix.com/trac/ticket/2754.
53
transport = getattr(self.client, 'transport', None)
54
if transport is not None:
55
# For SFTP connections, 'transport' is actually a _DummyTransport
56
# instance. Neither _DummyTransport nor the protocol it wraps
57
# (filetransfer.FileTransferServer) support pausing.
58
pauseProducing = getattr(transport, 'pauseProducing', None)
59
if pauseProducing is not None:
62
def startWriting(self):
63
"""See `session.SSHSession.startWriting`.
65
The client is ready for data again, so ask the child to start
68
# XXX: MichaelHudson 2008-06-27: Being cagey about whether
69
# self.client.transport is entirely paranoia inspired by the comment
70
# in `loseConnection` above. It would be good to know if and why it is
71
# necessary. See http://twistedmatrix.com/trac/ticket/2754.
72
transport = getattr(self.client, 'transport', None)
73
if transport is not None:
74
# For SFTP connections, 'transport' is actually a _DummyTransport
75
# instance. Neither _DummyTransport nor the protocol it wraps
76
# (filetransfer.FileTransferServer) support pausing.
77
resumeProducing = getattr(transport, 'resumeProducing', None)
78
if resumeProducing is not None: