OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / src / libs / utils / ssh / sshchannelmanager.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **************************************************************************/
32
33 #include "sshchannelmanager_p.h"
34
35 #include "sftpchannel.h"
36 #include "sftpchannel_p.h"
37 #include "sshincomingpacket_p.h"
38 #include "sshremoteprocess.h"
39 #include "sshremoteprocess_p.h"
40 #include "sshsendfacility_p.h"
41
42 #include <QtCore/QList>
43
44 namespace Utils {
45 namespace Internal {
46
47 SshChannelManager::SshChannelManager(SshSendFacility &sendFacility,
48     QObject *parent)
49     : QObject(parent), m_sendFacility(sendFacility), m_nextLocalChannelId(0)
50 {
51 }
52
53 void SshChannelManager::handleChannelRequest(const SshIncomingPacket &packet)
54 {
55     lookupChannel(packet.extractRecipientChannel())
56         ->handleChannelRequest(packet);
57 }
58
59 void SshChannelManager::handleChannelOpen(const SshIncomingPacket &)
60 {
61     throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
62         "Server tried to open channel on client.");
63 }
64
65 void SshChannelManager::handleChannelOpenFailure(const SshIncomingPacket &packet)
66 {
67    const SshChannelOpenFailure &failure = packet.extractChannelOpenFailure();
68    ChannelIterator it = lookupChannelAsIterator(failure.localChannel);
69    try {
70        it.value()->handleOpenFailure(failure.reasonString);
71    } catch (SshServerException &e) {
72        removeChannel(it);
73        throw e;
74    }
75    removeChannel(it);
76 }
77
78 void SshChannelManager::handleChannelOpenConfirmation(const SshIncomingPacket &packet)
79 {
80    const SshChannelOpenConfirmation &confirmation
81        = packet.extractChannelOpenConfirmation();
82    lookupChannel(confirmation.localChannel)->handleOpenSuccess(confirmation.remoteChannel,
83        confirmation.remoteWindowSize, confirmation.remoteMaxPacketSize);
84 }
85
86 void SshChannelManager::handleChannelSuccess(const SshIncomingPacket &packet)
87 {
88     lookupChannel(packet.extractRecipientChannel())->handleChannelSuccess();
89 }
90
91 void SshChannelManager::handleChannelFailure(const SshIncomingPacket &packet)
92 {
93     lookupChannel(packet.extractRecipientChannel())->handleChannelFailure();
94 }
95
96 void SshChannelManager::handleChannelWindowAdjust(const SshIncomingPacket &packet)
97 {
98     const SshChannelWindowAdjust adjust = packet.extractWindowAdjust();
99     lookupChannel(adjust.localChannel)->handleWindowAdjust(adjust.bytesToAdd);
100 }
101
102 void SshChannelManager::handleChannelData(const SshIncomingPacket &packet)
103 {
104     const SshChannelData &data = packet.extractChannelData();
105     lookupChannel(data.localChannel)->handleChannelData(data.data);
106 }
107
108 void SshChannelManager::handleChannelExtendedData(const SshIncomingPacket &packet)
109 {
110     const SshChannelExtendedData &data = packet.extractChannelExtendedData();
111     lookupChannel(data.localChannel)->handleChannelExtendedData(data.type, data.data);
112 }
113
114 void SshChannelManager::handleChannelEof(const SshIncomingPacket &packet)
115 {
116     AbstractSshChannel * const channel
117         = lookupChannel(packet.extractRecipientChannel(), true);
118     if (channel)
119         channel->handleChannelEof();
120 }
121
122 void SshChannelManager::handleChannelClose(const SshIncomingPacket &packet)
123 {
124     const quint32 channelId = packet.extractRecipientChannel();
125
126     ChannelIterator it = lookupChannelAsIterator(channelId, true);
127     if (it != m_channels.end()) {
128         it.value()->handleChannelClose();
129         removeChannel(it);
130     }
131 }
132
133 SshChannelManager::ChannelIterator SshChannelManager::lookupChannelAsIterator(quint32 channelId,
134     bool allowNotFound)
135 {
136     ChannelIterator it = m_channels.find(channelId);
137     if (it == m_channels.end() && !allowNotFound) {
138         throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
139             "Invalid channel id.",
140             tr("Invalid channel id %1").arg(channelId));
141     }
142     return it;
143 }
144
145 AbstractSshChannel *SshChannelManager::lookupChannel(quint32 channelId,
146     bool allowNotFound)
147 {
148     ChannelIterator it = lookupChannelAsIterator(channelId, allowNotFound);
149     return it == m_channels.end() ? 0 : it.value();
150 }
151
152 Utils::SshRemoteProcess::Ptr SshChannelManager::createRemoteProcess(const QByteArray &command)
153 {
154     SshRemoteProcess::Ptr proc(new SshRemoteProcess(command, m_nextLocalChannelId++, m_sendFacility));
155     insertChannel(proc->d, proc);
156     return proc;
157 }
158
159 Utils::SftpChannel::Ptr SshChannelManager::createSftpChannel()
160 {
161     SftpChannel::Ptr sftp(new SftpChannel(m_nextLocalChannelId++, m_sendFacility));
162     insertChannel(sftp->d, sftp);
163     return sftp;
164 }
165
166 void SshChannelManager::insertChannel(AbstractSshChannel *priv,
167     const QSharedPointer<QObject> &pub)
168 {
169     connect(priv, SIGNAL(timeout()), this, SIGNAL(timeout()));
170     m_channels.insert(priv->localChannelId(), priv);
171     m_sessions.insert(priv, pub);
172 }
173
174 void SshChannelManager::closeAllChannels()
175 {
176     for (ChannelIterator it = m_channels.begin(); it != m_channels.end(); ++it)
177         it.value()->closeChannel();
178     m_channels.clear();
179     m_sessions.clear();
180 }
181
182 void SshChannelManager::removeChannel(ChannelIterator it)
183 {
184     Q_ASSERT(it != m_channels.end() && "Unexpected channel lookup failure.");
185     const int removeCount = m_sessions.remove(it.value());
186     Q_ASSERT(removeCount == 1 && "Session for channel not found.");
187     m_channels.erase(it);
188 }
189
190 } // namespace Internal
191 } // namespace Utils