Rabbit Remote Control 0.1.0-de
Loading...
Searching...
No Matches
ChannelSSHTerminal.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include "ChannelSSHTerminal.h"
4#include <QLoggingCategory>
5
6static Q_LOGGING_CATEGORY(log, "Plugin.SSH.Channel")
7
9 : CChannelSSH{pBackend, pPara, true, pBackend}
10{
11 qDebug(log) << Q_FUNC_INFO;
12}
13
14CChannelSSHTerminal::~CChannelSSHTerminal()
15{
16 qDebug(log) << Q_FUNC_INFO;
17}
18
19qint64 CChannelSSHTerminal::readData(char *data, qint64 maxlen)
20{
21 qint64 nRet = 0;
22 if(!m_Channel || !ssh_channel_is_open(m_Channel))
23 return -1;
24 nRet = ssh_channel_read(m_Channel, data, maxlen, 0);
25 m_nBytesAvailable -= nRet;
26 //qDebug(log) << Q_FUNC_INFO << nRet << maxlen << m_nBytesAvailable;
27 return nRet;
28}
29
30qint64 CChannelSSHTerminal::writeData(const char *data, qint64 maxlen)
31{
32 qint64 nRet = 0;
33 if(!m_Channel || !ssh_channel_is_open(m_Channel))
34 return -1;
35 if(maxlen > 0)
36 nRet = ssh_channel_write(m_Channel, data, maxlen);
37 //qDebug(log) << Q_FUNC_INFO << nRet << maxlen;
38 return nRet;
39}
40
41int CChannelSSHTerminal::OnOpen(ssh_session session)
42{
43 int nRet = 0;
44 QString szErr;
45
46 m_Channel = ssh_channel_new(session);
47 if (m_Channel == NULL) {
48 szErr = QString("Don't create channel: ") + ssh_get_error(session);
49 qCritical(log) << szErr;
50 setErrorString(szErr);
51 return -1;
52 }
53 nRet = ssh_channel_open_session(m_Channel);
54 if (nRet != SSH_OK) {
55 szErr = QString("Error opening channel: ") + ssh_get_error(session);
56 qCritical(log) << szErr;
57 setErrorString(szErr);
58 return -1;
59 }
60 nRet = ssh_channel_request_pty(m_Channel);
61 if (nRet != SSH_OK) {
62 szErr = QString("Error request pty: ") + ssh_get_error(session);
63 qCritical(log) << szErr;
64 setErrorString(szErr);
65 return nRet;
66 }
67 nRet = ssh_channel_change_pty_size(m_Channel, m_nColumn, m_nRow);
68 if (nRet != SSH_OK) {
69 szErr = QString("Error change pty size: ") + ssh_get_error(session);
70 qCritical(log) << szErr;
71 setErrorString(szErr);
72 return nRet;
73 }
74 qDebug(log) << "row:" << m_nRow << "; column:" << m_nColumn;
75 nRet = ssh_channel_request_shell(m_Channel);
76 if (nRet != SSH_OK) {
77 szErr = QString("Requesting shell: ") + ssh_get_error(session);
78 qCritical(log) << szErr;
79 setErrorString(szErr);
80 return -1;
81 }
82
83 return 0;
84}
85
86void CChannelSSHTerminal::OnClose()
87{
88 if(m_Channel) {
89 if(ssh_channel_is_open(m_Channel)) {
90 ssh_channel_close(m_Channel);
91 }
92 ssh_channel_free(m_Channel);
93 m_Channel = NULL;
94 }
95}
96
97void CChannelSSHTerminal::SetSize(int row, int column)
98{
99 m_nRow = row;
100 m_nColumn = column;
101}
102
103int CChannelSSHTerminal::OnProcess(int tm)
104{
105 int nRet = 0;
106
107 m_nBytesAvailable = 0;
108 if(!m_Channel || !ssh_channel_is_open(m_Channel)
109 || ssh_channel_is_eof(m_Channel)) {
110 QString szErr = "The channel is not open";
111 qCritical(log) << szErr;
112 setErrorString(szErr);
113 return -1;
114 }
115
116 struct timeval timeout = {0, tm};
117 ssh_channel channels[2], channel_out[2];
118 channels[0] = m_Channel;
119 channels[1] = nullptr;
120
121 fd_set set;
122 FD_ZERO(&set);
123 socket_t fd = SSH_INVALID_SOCKET;
124 if(m_pEvent)
125 fd = m_pEvent->GetFd();
126 if(SSH_INVALID_SOCKET != fd)
127 FD_SET(fd, &set);
128
129 //qDebug(log) << "ssh_select:" << fd;
130 nRet = ssh_select(channels, channel_out, fd + 1, &set, &timeout);
131 //qDebug(log) << "ssh_select end:" << nRet;
132 if(EINTR == nRet)
133 return 0;
134
135 if(SSH_OK != nRet) {
136 QString szErr;
137 szErr = "ssh_channel_select failed: " + QString::number(nRet);
138 szErr += ssh_get_error(m_Session);
139 qCritical(log) << szErr;
140 setErrorString(szErr);
141 return -3;
142 }
143
144 if(SSH_INVALID_SOCKET != fd && FD_ISSET(fd, &set)) {
145 //qDebug(log) << "fires event";
146 if(m_pEvent) {
147 nRet = m_pEvent->Reset();
148 if(nRet) return -4;
149 }
150 }
151
152 if(!channel_out[0]) {
153 //qDebug(log) << "The channel is not select";
154 return 0;
155 }
156
157 if(ssh_channel_is_eof(m_Channel)) {
158 qWarning(log) << "Channel is eof";
159 setErrorString(tr("The channel is eof"));
160 // Stop
161 return -1;
162 }
163
164 // Get channel data length
165 nRet = ssh_channel_poll(m_Channel, 0);
166 //qDebug(log) << "Get channel data length:" << nRet;
167 if(SSH_ERROR == nRet)
168 {
169 QString szErr;
170 szErr = "ssh_channel_poll failed. nRet:";
171 szErr += QString::number(nRet);
172 szErr += ssh_get_error(m_Session);
173 setErrorString(szErr);
174 qCritical(log) << szErr;
175 return -6;
176 } else if(SSH_EOF == nRet) {
177 // Stop
178 return -1;
179 } else if(0 > nRet) {
180 QString szErr;
181 szErr = "ssh_channel_poll failed. nRet:";
182 szErr += QString::number(nRet);
183 szErr += ssh_get_error(m_Session);
184 setErrorString(szErr);
185 qCritical(log) << szErr;
186 // Error
187 return -7;
188 } else if(0 == nRet) {
189 //qDebug(log) << "The channel has not data";
190 return 0;
191 }
192
193 m_nBytesAvailable = nRet;
194 emit readyRead();
195
196 return 0;
197}
198
199qint64 CChannelSSHTerminal::bytesAvailable() const
200{
201 return m_nBytesAvailable;
202}
Backend interface.
Definition Backend.h:42