-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClient.cpp
164 lines (141 loc) · 5.07 KB
/
Client.cpp
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
153
154
155
156
157
158
159
160
161
162
163
164
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
#include <sys/ioctl.h>
#include <pty.h>
#include <iostream>
#include "Client.h"
Spatch::Ssh::Client::Client(Spatch::Configuration::Config &conf, const std::shared_ptr<Spatch::Configuration::User> u, ssh_channel channel, ssh_event event)
: _conf(conf), _user(u), _connection(nullptr), _shell(conf, *this), _channel(channel), _session(ssh_channel_get_session(channel)), _event(event)
{
openpty(&_masterpty, &_slavepty, NULL, NULL, NULL);
_callbacks.channel_data_function = channelCallback;
_callbacks.userdata = this;
ssh_callbacks_init(&_callbacks);
ssh_set_channel_callbacks(_channel, &_callbacks);
if(ssh_event_add_session(_event, _session) != SSH_OK)
return ;
if(ssh_event_add_fd(_event, _masterpty, POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL, fdMasterCallback, this) != SSH_OK)
return ;
if(ssh_event_add_fd(_event, _slavepty, POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL, fdSlaveCallback, this) != SSH_OK)
return ;
_shell.onWelcome();
}
Spatch::Ssh::Client::~Client()
{
ssh_event_remove_fd(_event, _masterpty);
ssh_event_remove_fd(_event, _slavepty);
ssh_event_remove_session(_event, _session);
ssh_channel_free(_channel);
ssh_disconnect(_session);
ssh_free(_session);
}
bool Spatch::Ssh::Client::isEOF() const
{
return ssh_channel_is_eof(_channel);
}
bool Spatch::Ssh::Client::isClose() const
{
return ssh_channel_is_closed(_channel);
}
void Spatch::Ssh::Client::proxify(std::shared_ptr<Spatch::Configuration::Access> access, const std::string &command)
{
if (access == nullptr)
{
_connection = nullptr;
_shell.printPrompt();
}
else
{
_connection = std::make_shared<Spatch::Ssh::Connection>(*this, access->getServer()->getIp(), access->getServer()->getPort(), _event);
if (access->getCredentialType() == Spatch::Configuration::Access::CredentialType::Provided)
_connection->connect(access->getCredential()->getUsername(), access->getCredential()->getPassword(), command);
else if (access->getCredentialType() == Spatch::Configuration::Access::CredentialType::UserCred)
_connection->connect(_user->getUsername(), _user->getPassword(), command);
else
_connection->connect(command);
}
}
const std::shared_ptr<Spatch::Ssh::Connection> Spatch::Ssh::Client::getProxifiyConnection() const
{
return nullptr;
}
int Spatch::Ssh::Client::masterPtyToChannel(int revents)
{
char buf[2048];
int sz = 0;
if(!_channel)
{
close(_masterpty);
return 0;
}
if(revents & POLLIN)
{
sz = read(_masterpty, buf, 2048);
if(sz > 0)
return (ssh_channel_write(_channel, buf, sz));
}
if(revents & POLLHUP)
return (ssh_channel_close(_channel));
return 0;
}
int Spatch::Ssh::Client::onSlaveEvent(int revents)
{
if(!_channel)
{
close(_masterpty);
return 0;
}
if(revents & POLLIN)
{
if (!_connection)
return (_shell.onRead());
}
if(revents & POLLHUP)
return (ssh_channel_close(_channel));
return 0;
}
int Spatch::Ssh::Client::writeToChannel(const void *data, uint32_t len)
{
return (ssh_channel_write(_channel, data, len));
}
int Spatch::Ssh::Client::channelToMasterPty(void *data, uint32_t len)
{
if (!_connection)
return(write(_masterpty, data, len));
else
return (_connection->writeToChannel(data, len));
}
int Spatch::Ssh::Client::getSlaveFd() const
{
return _slavepty;
}
const std::shared_ptr<Spatch::Configuration::User> Spatch::Ssh::Client::getUser() const
{
return _user;
}
/*
* C Type Callbacks private static member function
*/
int Spatch::Ssh::Client::fdMasterCallback(socket_t fd, int revents, void *userdata)
{
Spatch::Ssh::Client *client = static_cast<Spatch::Ssh::Client *>(userdata);
return(client->masterPtyToChannel(revents));
}
int Spatch::Ssh::Client::fdSlaveCallback(socket_t fd, int revents, void *userdata)
{
Spatch::Ssh::Client *client = static_cast<Spatch::Ssh::Client *>(userdata);
return (client->onSlaveEvent(revents));
}
int Spatch::Ssh::Client::channelCallback(ssh_session session,
ssh_channel channel,
void *data,
uint32_t len,
int is_stderr,
void *userdata)
{
Spatch::Ssh::Client *client = static_cast<Spatch::Ssh::Client *>(userdata);
return(client->channelToMasterPty(data, len));
}