GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/cxx_sshclients.cpp
Date: 2026-03-20 22:56:14
Exec Total Coverage
Lines: 67 181 37.0%
Functions: 15 38 39.5%
Branches: 30 168 17.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/net/sshclients.hpp"
29 #include "gate/exceptions.hpp"
30
31 namespace gate
32 {
33 namespace net
34 {
35
36 2 SshClient::~SshClient() noexcept
37 {
38 1 gate_sshclient_disconnect(&this->impl);
39 1 gate_sshclient_release(&this->impl);
40 1 }
41 1 gate_sshclient_t* SshClient::c_impl()
42 {
43 1 return &this->impl;
44 }
45 1 SshClient::SshClient(String const& server, uint16_t port, String const& user, String const& password)
46 {
47 1 result_t result = gate_sshclient_create(&this->impl, server.c_impl(), port);
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
49 1 result = gate_sshclient_connect(&this->impl, user.c_impl(), password.c_impl(), 0);
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
51 {
52 gate_sshclient_release(&this->impl);
53 GATEXX_RAISE_EXCEPTION(result, NULL, 0);
54 }
55 1 }
56
57 SshClient::SshClient(String const& server, uint16_t port, String const& user,
58 String const& publicKey, String const& privateKey, String const& passPhrase)
59 {
60 result_t result = gate_sshclient_create(&this->impl, server.c_impl(), port);
61 GATEXX_CHECK_EXCEPTION(result);
62 result = gate_sshclient_connect_keys(&this->impl, user.c_impl(),
63 publicKey.c_impl(), privateKey.c_impl(), passPhrase.c_impl(), 0);
64 if (GATE_FAILED(result))
65 {
66 gate_sshclient_release(&this->impl);
67 GATEXX_RAISE_EXCEPTION(result, NULL, 0);
68 }
69 }
70
71
72 1 Ref<SshClient> SshClient::create(String const& server, uint16_t port, String const& user, String const& password)
73 {
74
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 Ptr<SshClient> ptr(new SshClient(server, port, user, password));
75
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 Ref<SshClient> ref(gate::moveRef(ptr));
76 2 return ref;
77 }
78
79 Ref<SshClient> SshClient::create(String const& server, uint16_t port, String const& user,
80 String const& publicKey, String const& privateKey, String const& passPhrase)
81 {
82 Ptr<SshClient> ptr(new SshClient(server, port, user, publicKey, privateKey, passPhrase));
83 Ref<SshClient> ref(gate::moveRef(ptr));
84 return ref;
85 }
86
87
88 1 SshFtp::SshFtp(SshClientRef connectedClient)
89 1 : client(connectedClient)
90 {
91
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!client)
92 {
93 GATEXX_RAISE_ERROR(results::NullPointer);
94 }
95
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_sshclient_open_sftp(client->c_impl(), &this->impl);
96
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
97 1 }
98 1 SshFtp::~SshFtp() noexcept
99 {
100 1 gate_sshclient_close_sftp(&this->impl);
101 1 }
102
103 void SshFtp::createDirectory(String const& path)
104 {
105 result_t result = gate_sshclient_sftp_mkdir(&this->impl, path.c_impl());
106 GATEXX_CHECK_EXCEPTION(result);
107 }
108 void SshFtp::removeDirectory(String const& path)
109 {
110 result_t result = gate_sshclient_sftp_rmdir(&this->impl, path.c_impl());
111 GATEXX_CHECK_EXCEPTION(result);
112 }
113 void SshFtp::deleteFile(String const& path)
114 {
115 result_t result = gate_sshclient_sftp_unlink(&this->impl, path.c_impl());
116 GATEXX_CHECK_EXCEPTION(result);
117 }
118 void SshFtp::move(String const& path, String const& newPath)
119 {
120 result_t result = gate_sshclient_sftp_rename(&this->impl, path.c_impl(), newPath.c_impl());
121 GATEXX_CHECK_EXCEPTION(result);
122 }
123
124 1 File::Properties SshFtp::getProperties(String const& path)
125 {
126 gate_file_properties_t props;
127
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t result = gate_sshclient_sftp_stat(&this->impl, path.c_impl(), &props);
128
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
129
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return File::Properties(props);
130 }
131
132 struct GATE_API_LOCAL SshFtp_listEntries_data
133 {
134 File::callback_t const* callback;
135 void* userparam;
136 };
137
138 static gate_bool_t GATE_CALL SshFtp_listEntries_cb(gate_file_entry_t const* entry, void* userparam)
139 {
140 SshFtp_listEntries_data* data = static_cast<SshFtp_listEntries_data*>(userparam);
141 File::Entry fileEntry((*entry));
142 bool_t continueListing = true;
143 File::callback_t cb = *(data->callback);
144 GATEXX_TRY_IGNORE({
145 cb(&fileEntry, data->userparam, &continueListing);
146 });
147 return continueListing;
148 }
149
150 void SshFtp::listEntries(String const& dirpath, File::callback_t const& callback, void* userparam)
151 {
152 SshFtp_listEntries_data data;
153 data.callback = &callback;
154 data.userparam = userparam;
155
156 result_t result = gate_sshclient_sftp_listdir(&this->impl, dirpath.c_impl(), &SshFtp_listEntries_cb, &data);
157 GATEXX_CHECK_EXCEPTION(result);
158 }
159
160 1 File::pathmap_t SshFtp::listEntryPaths(String const& dirpath)
161 {
162 1 File::pathmap_t ret;
163 gate_sshclient_sftp_handle_t sftpHandle;
164
165
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 result_t result = gate_sshclient_sftp_opendir(&this->impl, dirpath.c_impl(), &sftpHandle);
166
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
167
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 while (GATE_SUCCEEDED(result))
168 {
169
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 File::Entry fileEntry;
170
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 result = gate_sshclient_sftp_readdir(&sftpHandle, &fileEntry);
171
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 GATE_BREAK_IF_FAILED(result);
172
3/6
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
18 ret.add(fileEntry.getPath(), fileEntry.getName());
173 }
174
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_sshclient_sftp_close(&sftpHandle);
175
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result != GATE_RESULT_NODATA)
177 {
178 GATEXX_CHECK_EXCEPTION(result);
179 }
180 2 return ret;
181 }
182
183 1 gate_sshclient_sftp_t* SshFtp::c_impl()
184 {
185 1 return &this->impl;
186 }
187
188 1 SshClientRef SshFtp::getClient() const
189 {
190 1 return this->client;
191 }
192
193
194
195 1 SshFtpFile::SshFtpFile(SshFtp& sftp, String const& path, enumint_t streamOpenFlags)
196 1 : client(sftp.getClient())
197 {
198
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 result_t result = gate_sshclient_sftp_open(sftp.c_impl(), path.c_impl(), streamOpenFlags, &this->impl);
199
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
200 1 }
201 1 SshFtpFile::~SshFtpFile() noexcept
202 {
203 1 gate_sshclient_sftp_close(&this->impl);
204 1 }
205
206 1 size_t SshFtpFile::read(char* buffer, gate_size_t capacity)
207 {
208 1 gate_size_t received = 0;
209
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_read(&this->impl, buffer, capacity, &received);
210
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
211 1 return received;
212 }
213 size_t SshFtpFile::write(char const* buffer, gate_size_t length)
214 {
215 gate_size_t written = 0;
216 result_t result = gate_sshclient_sftp_write(&this->impl, buffer, length, &written);
217 GATEXX_CHECK_EXCEPTION(result);
218 return written;
219 }
220 1 void SshFtpFile::seek(gate_uint64_t position)
221 {
222 1 result_t result = gate_sshclient_sftp_seek(&this->impl, position);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
224 1 }
225 1 uint64_t SshFtpFile::tell()
226 {
227 1 gate_uint64_t pos = 0;
228
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_tell(&this->impl, &pos);
229
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
230 1 return pos;
231 }
232
233 gate_sshclient_sftp_handle_t* SshFtpFile::c_impl()
234 {
235 return &this->impl;
236 }
237 SshClientRef SshFtpFile::getClient() const
238 {
239 return this->client;
240 }
241
242
243 enumint_t const SshCommandChannel::StreamType_Default = GATE_SSHCLIENT_STREAMTYPE_DEFAULT;
244 enumint_t const SshCommandChannel::StreamType_Error = GATE_SSHCLIENT_STREAMTYPE_ERROR;
245
246 SshCommandChannel::SshCommandChannel(SshClientRef const& connectedClient)
247 : client(connectedClient),
248 impl(NULL)
249 {
250 result_t result = gate_sshclient_channel_open(this->client->c_impl(), &this->impl);
251 GATEXX_CHECK_EXCEPTION(result);
252 }
253 SshCommandChannel::~SshCommandChannel() noexcept
254 {
255 gate_sshclient_channel_free(&this->impl);
256 }
257
258 void SshCommandChannel::execute(String const& command)
259 {
260 result_t result = gate_sshclient_channel_exec(&this->impl, command.c_impl());
261 GATEXX_CHECK_EXCEPTION(result);
262 }
263 bool_t SshCommandChannel::canRead(enumint_t streamType)
264 {
265 gate_bool_t value = false;
266 result_t result = gate_sshclient_channel_canread(&this->impl, streamType, &value);
267 GATEXX_CHECK_EXCEPTION(result);
268 return value;
269 }
270 size_t SshCommandChannel::read(char* buffer, gate_size_t capacity, enumint_t streamType)
271 {
272 gate_size_t retrieved = 0;
273 result_t result = gate_sshclient_channel_read(&this->impl, streamType, buffer, capacity, &retrieved);
274 GATEXX_CHECK_EXCEPTION(result);
275 return retrieved;
276 }
277 size_t SshCommandChannel::write(char const* buffer, gate_size_t length, enumint_t streamType)
278 {
279 gate_size_t processed = 0;
280 result_t result = gate_sshclient_channel_write(&this->impl, streamType, buffer, length, &processed);
281 GATEXX_CHECK_EXCEPTION(result);
282 return processed;
283 }
284 bool SshCommandChannel::eof()
285 {
286 return gate_sshclient_channel_eof(&this->impl);
287 }
288 void SshCommandChannel::sendEof()
289 {
290 result_t result = gate_sshclient_channel_send_eof(&this->impl);
291 GATEXX_CHECK_EXCEPTION(result);
292 }
293 void SshCommandChannel::waitEof()
294 {
295 result_t result = gate_sshclient_channel_wait_eof(&this->impl);
296 GATEXX_CHECK_EXCEPTION(result);
297 }
298 void SshCommandChannel::setEnv(String const& name, String const& value)
299 {
300 result_t result = gate_sshclient_channel_setenv(&this->impl, name.c_impl(), value.c_impl());
301 GATEXX_CHECK_EXCEPTION(result);
302 }
303 void SshCommandChannel::getExitSignal(String* signal, String* errmsg, String* langtag)
304 {
305 gate_string_t strsig = GATE_STRING_INIT_EMPTY;
306 gate_string_t strerr = GATE_STRING_INIT_EMPTY;
307 gate_string_t strlang = GATE_STRING_INIT_EMPTY;
308 result_t result = gate_sshclient_channel_get_exit_signal(&this->impl, &strsig, &strerr, &strlang);
309 GATEXX_CHECK_EXCEPTION(result);
310 if (signal) *signal = String::createFrom(strsig);
311 if (errmsg) *errmsg = String::createFrom(strerr);
312 if (langtag) *langtag = String::createFrom(strlang);
313 gate_string_release(&strlang);
314 gate_string_release(&strerr);
315 gate_string_release(&strsig);
316 }
317 int SshCommandChannel::getExitStatus()
318 {
319 int status = 0;
320 result_t result = gate_sshclient_channel_get_exit_status(&this->impl, &status);
321 GATEXX_CHECK_EXCEPTION(result);
322 return status;
323 }
324
325 } // end of namespace net
326 } // end of namespace gate
327