Commit d6e85d55 authored by Christian Kandeler's avatar Christian Kandeler

SSH: Take more care when closing channels.

We can't just pretend a channel is already gone after we request it to
close; it's only closed when the server has sent the acknowledgement.

Change-Id: Ib6e8b9bf77635995259885af13755f5fc0e825a9
Reviewed-by: default avatarTobias Hunger <tobias.hunger@nokia.com>
parent 1e71dccc
...@@ -176,16 +176,23 @@ void SshChannelManager::insertChannel(AbstractSshChannel *priv, ...@@ -176,16 +176,23 @@ void SshChannelManager::insertChannel(AbstractSshChannel *priv,
m_sessions.insert(priv, pub); m_sessions.insert(priv, pub);
} }
int SshChannelManager::closeAllChannels() int SshChannelManager::closeAllChannels(CloseAllMode mode)
{ {
const int count = m_channels.count(); const int count = m_channels.count();
for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it) for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it)
it.value()->closeChannel(); it.value()->closeChannel();
m_channels.clear(); if (mode == CloseAllAndReset) {
m_sessions.clear(); m_channels.clear();
m_sessions.clear();
}
return count; return count;
} }
int SshChannelManager::channelCount() const
{
return m_channels.count();
}
void SshChannelManager::removeChannel(ChannelIterator it) void SshChannelManager::removeChannel(ChannelIterator it)
{ {
Q_ASSERT(it != m_channels.end() && "Unexpected channel lookup failure."); Q_ASSERT(it != m_channels.end() && "Unexpected channel lookup failure.");
......
...@@ -55,7 +55,10 @@ public: ...@@ -55,7 +55,10 @@ public:
QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command); QSharedPointer<SshRemoteProcess> createRemoteProcess(const QByteArray &command);
QSharedPointer<SshRemoteProcess> createRemoteShell(); QSharedPointer<SshRemoteProcess> createRemoteShell();
QSharedPointer<SftpChannel> createSftpChannel(); QSharedPointer<SftpChannel> createSftpChannel();
int closeAllChannels(); int channelCount() const;
enum CloseAllMode { CloseAllRegular, CloseAllAndReset };
int closeAllChannels(CloseAllMode mode);
void handleChannelRequest(const SshIncomingPacket &packet); void handleChannelRequest(const SshIncomingPacket &packet);
void handleChannelOpen(const SshIncomingPacket &packet); void handleChannelOpen(const SshIncomingPacket &packet);
......
...@@ -194,13 +194,18 @@ QSharedPointer<SftpChannel> SshConnection::createSftpChannel() ...@@ -194,13 +194,18 @@ QSharedPointer<SftpChannel> SshConnection::createSftpChannel()
int SshConnection::closeAllChannels() int SshConnection::closeAllChannels()
{ {
try { try {
return d->m_channelManager->closeAllChannels(); return d->m_channelManager->closeAllChannels(Internal::SshChannelManager::CloseAllRegular);
} catch (const Botan::Exception &e) { } catch (const Botan::Exception &e) {
qDebug("%s: %s", Q_FUNC_INFO, e.what()); qDebug("%s: %s", Q_FUNC_INFO, e.what());
return -1; return -1;
} }
} }
int SshConnection::channelCount() const
{
return d->m_channelManager->channelCount();
}
namespace Internal { namespace Internal {
SshConnectionPrivate::SshConnectionPrivate(SshConnection *conn, SshConnectionPrivate::SshConnectionPrivate(SshConnection *conn,
...@@ -680,7 +685,7 @@ void SshConnectionPrivate::closeConnection(SshErrorCode sshError, ...@@ -680,7 +685,7 @@ void SshConnectionPrivate::closeConnection(SshErrorCode sshError,
m_keepAliveTimer.stop(); m_keepAliveTimer.stop();
disconnect(&m_keepAliveTimer, 0, this, 0); disconnect(&m_keepAliveTimer, 0, this, 0);
try { try {
m_channelManager->closeAllChannels(); m_channelManager->closeAllChannels(SshChannelManager::CloseAllAndReset);
m_sendFacility.sendDisconnectPacket(sshError, serverErrorString); m_sendFacility.sendDisconnectPacket(sshError, serverErrorString);
} catch (Botan::Exception &) {} // Nothing sensible to be done here. } catch (Botan::Exception &) {} // Nothing sensible to be done here.
if (m_error != SshNoError) if (m_error != SshNoError)
......
...@@ -107,6 +107,8 @@ public: ...@@ -107,6 +107,8 @@ public:
// -1 if an error occurred, number of channels closed otherwise. // -1 if an error occurred, number of channels closed otherwise.
int closeAllChannels(); int closeAllChannels();
int channelCount() const;
signals: signals:
void connected(); void connected();
void disconnected(); void disconnected();
......
...@@ -97,6 +97,8 @@ public: ...@@ -97,6 +97,8 @@ public:
continue; continue;
if (connection->thread() != QThread::currentThread()) { if (connection->thread() != QThread::currentThread()) {
if (connection->channelCount() != 0)
continue;
QMetaObject::invokeMethod(this, "switchToCallerThread", QMetaObject::invokeMethod(this, "switchToCallerThread",
Qt::BlockingQueuedConnection, Qt::BlockingQueuedConnection,
Q_ARG(SshConnection *, connection), Q_ARG(SshConnection *, connection),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment