-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathssh_client.h
More file actions
152 lines (124 loc) · 4.03 KB
/
Copy pathssh_client.h
File metadata and controls
152 lines (124 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once
#include <QByteArray>
#include <QMap>
#include <QObject>
#include <QString>
#include <QTimer>
#include <libssh/libssh.h>
#include <memory>
class SSHClient : public QObject {
Q_OBJECT
public:
using PtyFilterCallback = std::function< QByteArray(const QByteArray &) >;
enum class AuthMethod
{
Password,
PublicKey,
KeyboardInteractive
};
enum class TunnelType
{
Local,
Remote
};
struct TunnelConfig
{
TunnelType type;
QString bindAddress;
uint16_t bindPort;
QString destAddress;
uint16_t destPort;
};
enum class PtyOutputMode
{
Raw, // No filtering
StripAll, // Remove all escape sequences
Basic, // Keep basic formatting (colors, bold, etc)
Custom // Use custom filter function
};
struct CommandOptions
{
bool mergeOutput = true;
bool ptyEnabled = false;
int columns = 80;
int rows = 24;
QString term = "xterm";
PtyOutputMode outputMode = PtyOutputMode::Raw;
};
struct PersistentChannel
{
ssh_channel channel;
bool active;
CommandOptions options;
bool hasExited;
int exitStatus;
};
private:
static constexpr int CHANNEL_BUFFER_SIZE = 4096;
static constexpr int CHANNEL_CHECK_INTERVAL = 100; // ms
struct Channel
{
ssh_channel channel;
TunnelConfig config;
};
ssh_session m_session;
QMap< QString, Channel > m_activeChannels;
QTimer m_channelCheckTimer;
QString m_currentHostname;
QString m_currentUsername;
bool m_isAuthenticated;
std::unique_ptr< PersistentChannel > m_persistentChannel;
ssh_channel m_shellChannel = nullptr;
PtyFilterCallback m_ptyFilter;
bool verifyHostKey();
void cleanupSession();
void initializeSession();
void checkPersistentChannel();
QByteArray filterPtyOutput(const QByteArray &data);
QByteArray stripAnsiSequences(const QByteArray &data, bool keepBasicFormatting);
public:
explicit SSHClient(QObject *parent = nullptr);
~SSHClient();
// Connection management
bool connectToHost(const QString &hostname, const QString &username, uint16_t port = 22);
void disconnect();
// Authentication methods
bool authenticateWithPassword(const QString &password);
bool authenticateWithPublicKey(const QString &privateKeyPath, const QString &passphrase = QString());
bool authenticateWithKeyboardInteractive();
// Tunneling
bool createTunnel(const TunnelConfig &config);
void closeTunnel(const QString &bindAddress, uint16_t bindPort);
// Command execution
bool executeCommand(const QString &command);
bool isConnected() const;
bool isAuthenticated() const;
ssh_session session() const;
bool openCommandChannel(const CommandOptions &options = CommandOptions());
bool isCommandChannelOpen() const;
void closeCommandChannel();
bool executeInChannel(const QString &command);
bool writeToChannel(const QByteArray &data);
bool resizeChannel(int columns, int rows);
void setPtyFilter(PtyFilterCallback filter);
QByteArray cleanTerminalOutput(const QByteArray &data);
signals:
void connected();
void disconnected();
void error(const QString &message);
void authenticationFailed();
void authenticationSucceeded();
void keyboardInteractivePrompt(const QString &name, const QString &instruction, const QStringList &prompts);
void tunnelEstablished(const QString &bindAddress, uint16_t bindPort);
void tunnelClosed(const QString &bindAddress, uint16_t bindPort);
void dataReceived(const QByteArray &data);
void channelOpened();
void channelClosed(int exitStatus);
void channelOutputReceived(const QByteArray &data, bool isStderr);
void channelError(const QString &error);
public slots:
void sendKeyboardInteractiveResponse(const QStringList &responses);
void sendData(const QByteArray &data);
private slots:
void checkChannels();
};