• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mavlink / MAVSDK / 16633580645

30 Jul 2025 08:56PM UTC coverage: 44.659% (-1.7%) from 46.31%
16633580645

Pull #2626

github

web-flow
Merge cfb0d163b into c0a7c02a0
Pull Request #2626: core: flush after each Log* line

240 of 353 new or added lines in 38 files covered. (67.99%)

440 existing lines in 21 files now uncovered.

15469 of 34638 relevant lines covered (44.66%)

313.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.17
/src/mavsdk/plugins/ftp/ftp_impl.cpp
1
#include <algorithm>
2
#include <functional>
3
#include <iostream>
4

5
#include "ftp_impl.h"
6
#include "system.h"
7

8
namespace mavsdk {
9

10
FtpImpl::FtpImpl(System& system) : PluginImplBase(system)
×
11
{
12
    _system_impl->register_plugin(this);
×
13
}
×
14

15
FtpImpl::FtpImpl(std::shared_ptr<System> system) : PluginImplBase(std::move(system))
24✔
16
{
17
    _system_impl->register_plugin(this);
24✔
18
}
24✔
19

20
FtpImpl::~FtpImpl()
48✔
21
{
22
    _system_impl->unregister_plugin(this);
24✔
23
}
48✔
24

25
void FtpImpl::init() {}
24✔
26

27
void FtpImpl::deinit()
24✔
28
{
29
    // Cancel all FTP operations to prevent use-after-free callbacks
30
    _system_impl->mavlink_ftp_client().cancel_all_operations();
24✔
31
}
24✔
32

33
void FtpImpl::enable() {}
24✔
34

35
void FtpImpl::disable() {}
24✔
36

37
void FtpImpl::download_async(
14✔
38
    const std::string& remote_path,
39
    const std::string& local_folder,
40
    bool use_burst,
41
    Ftp::DownloadCallback callback)
42
{
43
    _system_impl->mavlink_ftp_client().download_async(
14✔
44
        remote_path,
45
        local_folder,
46
        use_burst,
47
        [callback, this](
528✔
48
            MavlinkFtpClient::ClientResult result, MavlinkFtpClient::ProgressData progress_data) {
1,056✔
49
            if (callback) {
528✔
50
                _system_impl->call_user_callback(
1,056✔
51
                    [temp_callback = callback, result, progress_data, this]() {
52
                        temp_callback(
53
                            result_from_mavlink_ftp_result(result),
54
                            progress_data_from_mavlink_ftp_progress_data(progress_data));
55
                    });
56
            }
57
        });
528✔
58
}
14✔
59

60
void FtpImpl::upload_async(
7✔
61
    const std::string& local_file_path,
62
    const std::string& remote_folder,
63
    Ftp::UploadCallback callback)
64
{
65
    _system_impl->mavlink_ftp_client().upload_async(
7✔
66
        local_file_path,
67
        remote_folder,
68
        [callback, this](
104✔
69
            MavlinkFtpClient::ClientResult result, MavlinkFtpClient::ProgressData progress_data) {
208✔
70
            if (callback) {
104✔
71
                _system_impl->call_user_callback(
208✔
72
                    [temp_callback = callback, result, progress_data, this]() {
73
                        temp_callback(
74
                            result_from_mavlink_ftp_result(result),
75
                            progress_data_from_mavlink_ftp_progress_data(progress_data));
76
                    });
77
            }
78
        });
104✔
79
}
7✔
80

81
std::pair<Ftp::Result, Ftp::ListDirectoryData> FtpImpl::list_directory(const std::string& path)
2✔
82
{
83
    std::promise<std::pair<Ftp::Result, Ftp::ListDirectoryData>> prom;
2✔
84
    auto fut = prom.get_future();
2✔
85

86
    list_directory_async(path, [&prom](Ftp::Result result, Ftp::ListDirectoryData data) {
2✔
87
        prom.set_value(std::pair<Ftp::Result, Ftp::ListDirectoryData>(result, data));
2✔
88
    });
2✔
89
    return fut.get();
2✔
90
}
2✔
91

92
void FtpImpl::list_directory_async(const std::string& path, Ftp::ListDirectoryCallback callback)
2✔
93
{
94
    _system_impl->mavlink_ftp_client().list_directory_async(
2✔
95
        path,
96
        [callback, this](
2✔
97
            MavlinkFtpClient::ClientResult result,
98
            std::vector<std::string> dirs,
99
            std::vector<std::string> files) {
2✔
100
            if (callback) {
2✔
101
                _system_impl->call_user_callback([=]() {
4✔
102
                    callback(
103
                        result_from_mavlink_ftp_result(result),
104
                        Ftp::ListDirectoryData{dirs, files});
105
                });
106
            }
107
        });
2✔
108
}
2✔
109

110
Ftp::Result FtpImpl::create_directory(const std::string& path)
3✔
111
{
112
    std::promise<Ftp::Result> prom{};
3✔
113
    auto fut = prom.get_future();
3✔
114

115
    create_directory_async(path, [&prom](Ftp::Result result) { prom.set_value(result); });
6✔
116
    return fut.get();
3✔
117
}
3✔
118

119
void FtpImpl::create_directory_async(const std::string& path, Ftp::ResultCallback callback)
3✔
120
{
121
    _system_impl->mavlink_ftp_client().create_directory_async(
3✔
122
        path, [callback, this](MavlinkFtpClient::ClientResult result) {
9✔
123
            if (callback) {
3✔
124
                _system_impl->call_user_callback([temp_callback = callback, result, this]() {
6✔
125
                    temp_callback(result_from_mavlink_ftp_result(result));
126
                });
127
            }
128
        });
3✔
129
}
3✔
130

131
Ftp::Result FtpImpl::remove_directory(const std::string& path)
2✔
132
{
133
    std::promise<Ftp::Result> prom{};
2✔
134
    auto fut = prom.get_future();
2✔
135

136
    remove_directory_async(path, [&prom](Ftp::Result result) { prom.set_value(result); });
4✔
137

138
    return fut.get();
2✔
139
}
2✔
140

141
void FtpImpl::remove_directory_async(const std::string& path, Ftp::ResultCallback callback)
2✔
142
{
143
    _system_impl->mavlink_ftp_client().remove_directory_async(
2✔
144
        path, [callback, this](MavlinkFtpClient::ClientResult result) {
6✔
145
            if (callback) {
2✔
146
                _system_impl->call_user_callback([temp_callback = callback, result, this]() {
4✔
147
                    temp_callback(result_from_mavlink_ftp_result(result));
148
                });
149
            }
150
        });
2✔
151
}
2✔
152

153
Ftp::Result FtpImpl::remove_file(const std::string& path)
4✔
154
{
155
    // Add corruption detection
156
    const uint32_t STACK_GUARD = 0xDEADBEEF;
4✔
157
    uint32_t guard1 = STACK_GUARD;
4✔
158

159
    std::promise<Ftp::Result> prom;
4✔
160
    auto fut = prom.get_future();
4✔
161

162
    uint32_t guard2 = STACK_GUARD;
4✔
163

164
    // Store promise address for validation
165
    void* orig_prom_addr = &prom;
4✔
166
    void* orig_fut_addr = &fut;
4✔
167

168
    remove_file_async(path, [&, orig_prom_addr, orig_fut_addr](Ftp::Result result) {
4✔
169
        LogInfo() << "Setting promise value for remove_file";
4✔
170

171
        // Check for corruption before fulfillment
172
        if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
4✔
NEW
173
            LogErr() << "Stack corruption detected around promise! guard1=" << std::hex << guard1
×
NEW
174
                     << " guard2=" << guard2;
×
NEW
175
            std::abort();
×
176
        }
177

178
        if (&prom != orig_prom_addr || &fut != orig_fut_addr) {
4✔
NEW
179
            LogErr() << "Promise/future address changed! prom: " << &prom << " vs "
×
NEW
180
                     << orig_prom_addr << " fut: " << &fut << " vs " << orig_fut_addr;
×
NEW
181
            std::abort();
×
182
        }
183

184
        prom.set_value(result);
4✔
185
    });
4✔
186

187
    // Check corruption before get()
188
    if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
4✔
NEW
189
        LogErr() << "Stack corruption detected before fut.get()! guard1=" << std::hex << guard1
×
NEW
190
                 << " guard2=" << guard2;
×
NEW
191
        std::abort();
×
192
    }
193

194
    // Try to detect future corruption before calling get() - no exceptions available
195
    auto status = fut.wait_for(std::chrono::seconds(0));
4✔
196
    LogInfo() << "Future wait_for succeeded, status=" << (int)status;
4✔
197

198
    return fut.get();
4✔
199
}
4✔
200

201
void FtpImpl::remove_file_async(const std::string& path, Ftp::ResultCallback callback)
4✔
202
{
203
    _system_impl->mavlink_ftp_client().remove_file_async(
4✔
204
        path, [callback, this](MavlinkFtpClient::ClientResult result) {
12✔
205
            if (callback) {
4✔
206
                _system_impl->call_user_callback([temp_callback = callback, result, this]() {
8✔
207
                    temp_callback(result_from_mavlink_ftp_result(result));
208
                });
209
            }
210
        });
4✔
211
}
4✔
212

213
Ftp::Result FtpImpl::rename(const std::string& from_path, const std::string& to_path)
2✔
214
{
215
    // Add corruption detection
216
    const uint32_t STACK_GUARD = 0xDEADBEEF;
2✔
217
    uint32_t guard1 = STACK_GUARD;
2✔
218

219
    std::promise<Ftp::Result> prom{};
2✔
220
    auto fut = prom.get_future();
2✔
221

222
    uint32_t guard2 = STACK_GUARD;
2✔
223

224
    // Store promise address for validation
225
    void* orig_prom_addr = &prom;
2✔
226
    void* orig_fut_addr = &fut;
2✔
227

228
    rename_async(from_path, to_path, [&, orig_prom_addr, orig_fut_addr](Ftp::Result result) {
2✔
229
        LogInfo() << "Setting promise value for rename";
2✔
230

231
        // Check for corruption before fulfillment
232
        if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
2✔
NEW
233
            LogErr() << "Stack corruption detected around promise! guard1=" << std::hex << guard1
×
NEW
234
                     << " guard2=" << guard2;
×
NEW
235
            std::abort();
×
236
        }
237

238
        if (&prom != orig_prom_addr || &fut != orig_fut_addr) {
2✔
NEW
239
            LogErr() << "Promise/future address changed! prom: " << &prom << " vs "
×
NEW
240
                     << orig_prom_addr << " fut: " << &fut << " vs " << orig_fut_addr;
×
NEW
241
            std::abort();
×
242
        }
243

244
        prom.set_value(result);
2✔
245
    });
2✔
246

247
    // Check corruption before get()
248
    if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
2✔
NEW
249
        LogErr() << "Stack corruption detected before fut.get()! guard1=" << std::hex << guard1
×
NEW
250
                 << " guard2=" << guard2;
×
NEW
251
        std::abort();
×
252
    }
253

254
    // Try to detect future corruption before calling get() - no exceptions available
255
    auto status = fut.wait_for(std::chrono::seconds(0));
2✔
256
    LogInfo() << "Future wait_for succeeded, status=" << (int)status;
2✔
257

258
    return fut.get();
2✔
259
}
2✔
260

261
void FtpImpl::rename_async(
2✔
262
    const std::string& from_path, const std::string& to_path, Ftp::ResultCallback callback)
263
{
264
    _system_impl->mavlink_ftp_client().rename_async(
2✔
265
        from_path, to_path, [callback, this](MavlinkFtpClient::ClientResult result) {
6✔
266
            if (callback) {
2✔
267
                _system_impl->call_user_callback([temp_callback = callback, result, this]() {
4✔
268
                    temp_callback(result_from_mavlink_ftp_result(result));
269
                });
270
            }
271
        });
2✔
272
}
2✔
273

274
std::pair<Ftp::Result, bool>
275
FtpImpl::are_files_identical(const std::string& local_path, const std::string& remote_path)
3✔
276
{
277
    // Add corruption detection
278
    const uint32_t STACK_GUARD = 0xDEADBEEF;
3✔
279
    uint32_t guard1 = STACK_GUARD;
3✔
280

281
    std::promise<std::pair<Ftp::Result, bool>> prom{};
3✔
282
    auto fut = prom.get_future();
3✔
283

284
    uint32_t guard2 = STACK_GUARD;
3✔
285

286
    // Store promise address for validation
287
    void* orig_prom_addr = &prom;
3✔
288
    void* orig_fut_addr = &fut;
3✔
289

290
    are_files_identical_async(
3✔
291
        local_path,
292
        remote_path,
293
        [&, orig_prom_addr, orig_fut_addr](Ftp::Result result, bool identical) {
9✔
294
            LogInfo() << "Setting promise value for are_files_identical";
3✔
295

296
            // Check for corruption before fulfillment
297
            if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
3✔
NEW
298
                LogErr() << "Stack corruption detected around promise! guard1=" << std::hex
×
NEW
299
                         << guard1 << " guard2=" << guard2;
×
NEW
300
                std::abort();
×
301
            }
302

303
            if (&prom != orig_prom_addr || &fut != orig_fut_addr) {
3✔
NEW
304
                LogErr() << "Promise/future address changed! prom: " << &prom << " vs "
×
NEW
305
                         << orig_prom_addr << " fut: " << &fut << " vs " << orig_fut_addr;
×
NEW
306
                std::abort();
×
307
            }
308

309
            prom.set_value(std::pair<Ftp::Result, bool>{result, identical});
3✔
310
        });
3✔
311

312
    // Check corruption before get()
313
    if (guard1 != STACK_GUARD || guard2 != STACK_GUARD) {
3✔
NEW
314
        LogErr() << "Stack corruption detected before fut.get()! guard1=" << std::hex << guard1
×
NEW
315
                 << " guard2=" << guard2;
×
NEW
316
        std::abort();
×
317
    }
318

319
    // Try to detect future corruption before calling get() - no exceptions available
320
    auto status = fut.wait_for(std::chrono::seconds(0));
3✔
321
    LogInfo() << "Future wait_for succeeded, status=" << (int)status;
3✔
322

323
    return fut.get();
3✔
324
}
3✔
325

326
void FtpImpl::are_files_identical_async(
3✔
327
    const std::string& local_path,
328
    const std::string& remote_path,
329
    Ftp::AreFilesIdenticalCallback callback)
330
{
331
    _system_impl->mavlink_ftp_client().are_files_identical_async(
3✔
332
        local_path,
333
        remote_path,
334
        [callback, this](MavlinkFtpClient::ClientResult result, bool identical) {
9✔
335
            if (callback) {
3✔
336
                _system_impl->call_user_callback(
6✔
337
                    [temp_callback = callback, result, identical, this]() {
338
                        temp_callback(result_from_mavlink_ftp_result(result), identical);
339
                    });
340
            }
341
        });
3✔
342
}
3✔
343

344
Ftp::Result FtpImpl::set_target_compid(uint8_t component_id)
×
345
{
346
    return result_from_mavlink_ftp_result(
×
347
        _system_impl->mavlink_ftp_client().set_target_compid(component_id));
×
348
}
349

350
Ftp::Result FtpImpl::result_from_mavlink_ftp_result(MavlinkFtpClient::ClientResult result)
648✔
351
{
352
    switch (result) {
648✔
353
        case MavlinkFtpClient::ClientResult::Unknown:
×
354
            return Ftp::Result::Unknown;
×
355
        case MavlinkFtpClient::ClientResult::Success:
19✔
356
            return Ftp::Result::Success;
19✔
357
        case MavlinkFtpClient::ClientResult::Next:
611✔
358
            return Ftp::Result::Next;
611✔
359
        case MavlinkFtpClient::ClientResult::Timeout:
3✔
360
            return Ftp::Result::Timeout;
3✔
361
        case MavlinkFtpClient::ClientResult::Busy:
×
362
            return Ftp::Result::Busy;
×
363
        case MavlinkFtpClient::ClientResult::FileIoError:
×
364
            return Ftp::Result::FileIoError;
×
365
        case MavlinkFtpClient::ClientResult::FileExists:
×
366
            return Ftp::Result::FileExists;
×
367
        case MavlinkFtpClient::ClientResult::FileDoesNotExist:
1✔
368
            return Ftp::Result::FileDoesNotExist;
1✔
369
        case MavlinkFtpClient::ClientResult::FileProtected:
×
370
            return Ftp::Result::FileProtected;
×
371
        case MavlinkFtpClient::ClientResult::InvalidParameter:
×
372
            return Ftp::Result::InvalidParameter;
×
373
        case MavlinkFtpClient::ClientResult::Unsupported:
×
374
            return Ftp::Result::Unsupported;
×
375
        case MavlinkFtpClient::ClientResult::ProtocolError:
14✔
376
            return Ftp::Result::ProtocolError;
14✔
377
        case MavlinkFtpClient::ClientResult::NoSystem:
×
378
            return Ftp::Result::NoSystem;
×
379
        default:
×
380
            return Ftp::Result::Unknown;
×
381
    }
382
}
383

384
Ftp::ProgressData
385
FtpImpl::progress_data_from_mavlink_ftp_progress_data(MavlinkFtpClient::ProgressData progress_data)
632✔
386
{
387
    return {progress_data.bytes_transferred, progress_data.total_bytes};
632✔
388
}
389

390
} // namespace mavsdk
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc