diff --git a/src/plugins/coreplugin/ssh/sshchannel.cpp b/src/plugins/coreplugin/ssh/sshchannel.cpp index 6e1b9c43f52..0d809171a3c 100644 --- a/src/plugins/coreplugin/ssh/sshchannel.cpp +++ b/src/plugins/coreplugin/ssh/sshchannel.cpp @@ -34,6 +34,8 @@ #include +#include + namespace Core { namespace Internal { @@ -46,10 +48,13 @@ namespace { AbstractSshChannel::AbstractSshChannel(quint32 channelId, SshSendFacility &sendFacility) - : m_sendFacility(sendFacility), m_localChannel(channelId), - m_remoteChannel(NoChannel), m_localWindowSize(InitialWindowSize), - m_remoteWindowSize(0), m_state(Inactive) + : m_sendFacility(sendFacility), m_timeoutTimer(new QTimer(this)), + m_localChannel(channelId), m_remoteChannel(NoChannel), + m_localWindowSize(InitialWindowSize), m_remoteWindowSize(0), + m_state(Inactive) { + m_timeoutTimer->setSingleShot(true); + connect(m_timeoutTimer, SIGNAL(timeout()), this, SIGNAL(timeout())); } AbstractSshChannel::~AbstractSshChannel() @@ -74,6 +79,7 @@ void AbstractSshChannel::requestSessionStart() m_sendFacility.sendSessionPacket(m_localChannel, InitialWindowSize, MaxPacketSize); setChannelState(SessionRequested); + m_timeoutTimer->start(ReplyTimeout); } catch (Botan::Exception &e) { m_errorString = QString::fromAscii(e.what()); closeChannel(); @@ -124,6 +130,7 @@ void AbstractSshChannel::handleOpenSuccess(quint32 remoteChannelId, throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Invalid SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet."); } + m_timeoutTimer->stop(); if (remoteMaxPacketSize < MinMaxPacketSize) { throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, @@ -148,6 +155,7 @@ void AbstractSshChannel::handleOpenFailure(const QString &reason) throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Invalid SSH_MSG_CHANNEL_OPEN_FAILURE packet."); } + m_timeoutTimer->stop(); #ifdef CREATOR_SSH_DEBUG qDebug("Channel open request failed for channel %u", m_localChannel); @@ -217,13 +225,16 @@ int AbstractSshChannel::handleChannelOrExtendedChannelData(const QByteArray &dat void AbstractSshChannel::closeChannel() { - if (m_state != CloseRequested && m_state != Closed) { + if (m_state == CloseRequested) { + m_timeoutTimer->stop(); + } else if (m_state != Closed) { if (m_state == Inactive) { setChannelState(Closed); } else { setChannelState(CloseRequested); m_sendFacility.sendChannelEofPacket(m_remoteChannel); m_sendFacility.sendChannelClosePacket(m_remoteChannel); + m_timeoutTimer->start(ReplyTimeout); } } } diff --git a/src/plugins/coreplugin/ssh/sshchannel_p.h b/src/plugins/coreplugin/ssh/sshchannel_p.h index ce86bf3651f..e0362c4642e 100644 --- a/src/plugins/coreplugin/ssh/sshchannel_p.h +++ b/src/plugins/coreplugin/ssh/sshchannel_p.h @@ -34,6 +34,8 @@ #include #include +QT_FORWARD_DECLARE_CLASS(QTimer); + namespace Core { namespace Internal { @@ -78,6 +80,8 @@ public: virtual ~AbstractSshChannel(); + static const int ReplyTimeout = 10000; // milli seconds + signals: void timeout(); @@ -88,6 +92,7 @@ protected: void checkChannelActive(); SshSendFacility &m_sendFacility; + QTimer * const m_timeoutTimer; private: virtual void handleOpenSuccessInternal()=0; diff --git a/src/plugins/coreplugin/ssh/sshremoteprocess.cpp b/src/plugins/coreplugin/ssh/sshremoteprocess.cpp index c9566e9aca9..47dfc12845d 100644 --- a/src/plugins/coreplugin/ssh/sshremoteprocess.cpp +++ b/src/plugins/coreplugin/ssh/sshremoteprocess.cpp @@ -36,6 +36,8 @@ #include +#include + namespace Core { const QByteArray SshRemoteProcess::AbrtSignal("ABRT"); @@ -158,6 +160,7 @@ void SshRemoteProcessPrivate::handleOpenSuccessInternal() m_sendFacility.sendExecPacket(remoteChannel(), m_command); setProcState(ExecRequested); + m_timeoutTimer->start(ReplyTimeout); } void SshRemoteProcessPrivate::handleOpenFailureInternal() @@ -171,6 +174,7 @@ void SshRemoteProcessPrivate::handleChannelSuccess() throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected SSH_MSG_CHANNEL_SUCCESS message."); } + m_timeoutTimer->stop(); setProcState(Running); } @@ -180,7 +184,7 @@ void SshRemoteProcessPrivate::handleChannelFailure() throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected SSH_MSG_CHANNEL_FAILURE message."); } - + m_timeoutTimer->stop(); setProcState(StartFailed); closeChannel(); }