GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/cxx_sshclients.cpp
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 67 182 36.8%
Functions: 15 38 39.5%
Branches: 30 168 17.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, 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 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 try
145 {
146 cb(&fileEntry, data->userparam, &continueListing);
147 }
148 catch (...) {}
149 return continueListing;
150 }
151
152 void SshFtp::listEntries(String const& dirpath, File::callback_t const& callback, void* userparam)
153 {
154 SshFtp_listEntries_data data;
155 data.callback = &callback;
156 data.userparam = userparam;
157
158 result_t result = gate_sshclient_sftp_listdir(&this->impl, dirpath.c_impl(), &SshFtp_listEntries_cb, &data);
159 GATEXX_CHECK_EXCEPTION(result);
160 }
161
162 1 File::pathmap_t SshFtp::listEntryPaths(String const& dirpath)
163 {
164 1 File::pathmap_t ret;
165 gate_sshclient_sftp_handle_t sftpHandle;
166
167
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);
168
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
169
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 while (GATE_SUCCEEDED(result))
170 {
171
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 File::Entry fileEntry;
172
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 result = gate_sshclient_sftp_readdir(&sftpHandle, &fileEntry);
173
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 GATE_BREAK_IF_FAILED(result);
174
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());
175 }
176
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 gate_sshclient_sftp_close(&sftpHandle);
177
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result != GATE_RESULT_NODATA)
179 {
180 GATEXX_CHECK_EXCEPTION(result);
181 }
182 2 return ret;
183 }
184
185 1 gate_sshclient_sftp_t* SshFtp::c_impl()
186 {
187 1 return &this->impl;
188 }
189
190 1 SshClientRef SshFtp::getClient() const
191 {
192 1 return this->client;
193 }
194
195
196
197 1 SshFtpFile::SshFtpFile(SshFtp& sftp, String const& path, enumint_t streamOpenFlags)
198 1 : client(sftp.getClient())
199 {
200
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);
201
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
202 1 }
203 1 SshFtpFile::~SshFtpFile() noexcept
204 {
205 1 gate_sshclient_sftp_close(&this->impl);
206 1 }
207
208 1 size_t SshFtpFile::read(char* buffer, gate_size_t capacity)
209 {
210 1 gate_size_t received = 0;
211
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_read(&this->impl, buffer, capacity, &received);
212
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
213 1 return received;
214 }
215 size_t SshFtpFile::write(char const* buffer, gate_size_t length)
216 {
217 gate_size_t written = 0;
218 result_t result = gate_sshclient_sftp_write(&this->impl, buffer, length, &written);
219 GATEXX_CHECK_EXCEPTION(result);
220 return written;
221 }
222 1 void SshFtpFile::seek(gate_uint64_t position)
223 {
224 1 result_t result = gate_sshclient_sftp_seek(&this->impl, position);
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATEXX_CHECK_EXCEPTION(result);
226 1 }
227 1 uint64_t SshFtpFile::tell()
228 {
229 1 gate_uint64_t pos = 0;
230
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 result_t result = gate_sshclient_sftp_tell(&this->impl, &pos);
231
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 GATEXX_CHECK_EXCEPTION(result);
232 1 return pos;
233 }
234
235 gate_sshclient_sftp_handle_t* SshFtpFile::c_impl()
236 {
237 return &this->impl;
238 }
239 SshClientRef SshFtpFile::getClient() const
240 {
241 return this->client;
242 }
243
244
245 enumint_t const SshCommandChannel::StreamType_Default = GATE_SSHCLIENT_STREAMTYPE_DEFAULT;
246 enumint_t const SshCommandChannel::StreamType_Error = GATE_SSHCLIENT_STREAMTYPE_ERROR;
247
248 SshCommandChannel::SshCommandChannel(SshClientRef const& connectedClient)
249 : client(connectedClient),
250 impl(NULL)
251 {
252 result_t result = gate_sshclient_channel_open(this->client->c_impl(), &this->impl);
253 GATEXX_CHECK_EXCEPTION(result);
254 }
255 SshCommandChannel::~SshCommandChannel() noexcept
256 {
257 gate_sshclient_channel_free(&this->impl);
258 }
259
260 void SshCommandChannel::execute(String const& command)
261 {
262 result_t result = gate_sshclient_channel_exec(&this->impl, command.c_impl());
263 GATEXX_CHECK_EXCEPTION(result);
264 }
265 bool_t SshCommandChannel::canRead(enumint_t streamType)
266 {
267 gate_bool_t value = false;
268 result_t result = gate_sshclient_channel_canread(&this->impl, streamType, &value);
269 GATEXX_CHECK_EXCEPTION(result);
270 return value;
271 }
272 size_t SshCommandChannel::read(char* buffer, gate_size_t capacity, enumint_t streamType)
273 {
274 gate_size_t retrieved = 0;
275 result_t result = gate_sshclient_channel_read(&this->impl, streamType, buffer, capacity, &retrieved);
276 GATEXX_CHECK_EXCEPTION(result);
277 return retrieved;
278 }
279 size_t SshCommandChannel::write(char const* buffer, gate_size_t length, enumint_t streamType)
280 {
281 gate_size_t processed = 0;
282 result_t result = gate_sshclient_channel_write(&this->impl, streamType, buffer, length, &processed);
283 GATEXX_CHECK_EXCEPTION(result);
284 return processed;
285 }
286 bool SshCommandChannel::eof()
287 {
288 return gate_sshclient_channel_eof(&this->impl);
289 }
290 void SshCommandChannel::sendEof()
291 {
292 result_t result = gate_sshclient_channel_send_eof(&this->impl);
293 GATEXX_CHECK_EXCEPTION(result);
294 }
295 void SshCommandChannel::waitEof()
296 {
297 result_t result = gate_sshclient_channel_wait_eof(&this->impl);
298 GATEXX_CHECK_EXCEPTION(result);
299 }
300 void SshCommandChannel::setEnv(String const& name, String const& value)
301 {
302 result_t result = gate_sshclient_channel_setenv(&this->impl, name.c_impl(), value.c_impl());
303 GATEXX_CHECK_EXCEPTION(result);
304 }
305 void SshCommandChannel::getExitSignal(String* signal, String* errmsg, String* langtag)
306 {
307 gate_string_t strsig = GATE_STRING_INIT_EMPTY;
308 gate_string_t strerr = GATE_STRING_INIT_EMPTY;
309 gate_string_t strlang = GATE_STRING_INIT_EMPTY;
310 result_t result = gate_sshclient_channel_get_exit_signal(&this->impl, &strsig, &strerr, &strlang);
311 GATEXX_CHECK_EXCEPTION(result);
312 try
313 {
314 if (signal) *signal = String::createFrom(strsig);
315 if (errmsg) *errmsg = String::createFrom(strerr);
316 if (langtag) *langtag = String::createFrom(strlang);
317 }
318 catch (...)
319 {
320 gate_string_release(&strlang);
321 gate_string_release(&strerr);
322 gate_string_release(&strsig);
323 throw;
324 }
325 gate_string_release(&strlang);
326 gate_string_release(&strerr);
327 gate_string_release(&strsig);
328 }
329 int SshCommandChannel::getExitStatus()
330 {
331 int status = 0;
332 result_t result = gate_sshclient_channel_get_exit_status(&this->impl, &status);
333 GATEXX_CHECK_EXCEPTION(result);
334 return status;
335 }
336
337 } // end of namespace net
338 } // end of namespace gate
339