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

mendersoftware / mender / 998809055

10 Sep 2023 01:55PM UTC coverage: 78.737% (-0.5%) from 79.223%
998809055

push

gitlab-ci

lluiscampos
chore: Move `PrivateKey::Generate` with default exponent to `.hpp`

We consider this method cross-platform as we should provide a key with
the same exponent regardless of the platform.

Signed-off-by: Lluis Campos <lluis.campos@northern.tech>

2 of 2 new or added lines in 1 file covered. (100.0%)

5836 of 7412 relevant lines covered (78.74%)

249.58 hits per line

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

85.48
/mender-update/update_module/v3/update_module_download.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <mender-update/update_module/v3/update_module.hpp>
16

17
#include <common/events.hpp>
18
#include <common/events_io.hpp>
19
#include <common/log.hpp>
20
#include <common/path.hpp>
21

22
namespace mender {
23
namespace update {
24
namespace update_module {
25
namespace v3 {
26

27
namespace log = mender::common::log;
28
namespace path = mender::common::path;
29

30
void UpdateModule::StartDownloadProcess() {
74✔
31
        log::Debug(
74✔
32
                "Calling Update Module with command `" + update_module_path_ + " Download "
148✔
33
                + update_module_workdir_ + "`.");
222✔
34
        download_->proc_ = make_shared<procs::Process>(
148✔
35
                vector<string> {update_module_path_, "Download", update_module_workdir_});
444✔
36

37
        download_->proc_->SetWorkDir(update_module_workdir_);
74✔
38

39
        auto err = PrepareStreamNextPipe();
74✔
40
        if (err != error::NoError) {
74✔
41
                DownloadErrorHandler(err);
×
42
                return;
×
43
        }
44

45
        err = download_->proc_->Start();
74✔
46
        if (err != error::NoError) {
74✔
47
                DownloadErrorHandler(GetProcessError(err));
×
48
                return;
×
49
        }
50

51
        err = download_->proc_->AsyncWait(
148✔
52
                download_->event_loop_,
74✔
53
                [this](error::Error err) {
144✔
54
                        if (err.code == make_error_condition(errc::timed_out)) {
72✔
55
                                DownloadTimeoutHandler();
2✔
56
                        } else {
57
                                ProcessEndedHandler(err);
70✔
58
                        }
59
                },
72✔
60
                chrono::seconds(ctx_.GetConfig().module_timeout_seconds));
222✔
61
        if (err != error::NoError) {
74✔
62
                DownloadErrorHandler(err);
×
63
                return;
×
64
        }
65

66
        DownloadErrorHandler(OpenStreamNextPipe(
74✔
67
                [this](io::ExpectedAsyncWriterPtr writer) { StreamNextOpenHandler(writer); }));
156✔
68
}
69

70
void UpdateModule::StreamNextOpenHandler(io::ExpectedAsyncWriterPtr writer) {
11✔
71
        if (!writer) {
11✔
72
                DownloadErrorHandler(writer.error());
×
73
                return;
2✔
74
        }
75
        download_->stream_next_writer_ = writer.value();
11✔
76

77
        download_->module_has_started_download_ = true;
11✔
78

79
        auto reader = download_->payload_.Next();
11✔
80
        if (!reader) {
11✔
81
                if (reader.error().code
4✔
82
                        == artifact::parser_error::MakeError(
2✔
83
                                   artifact::parser_error::NoMorePayloadFilesError, "")
4✔
84
                                   .code) {
85
                        download_->module_has_finished_download_ = true;
2✔
86
                        log::Debug("Update Module finished all downloads");
2✔
87
                        EndStreamNext();
2✔
88
                } else {
89
                        DownloadErrorHandler(reader.error());
×
90
                }
91
                return;
2✔
92
        }
93
        auto payload_reader = make_shared<artifact::Reader>(std::move(reader.value()));
9✔
94
        download_->current_payload_reader_ =
9✔
95
                make_shared<events::io::AsyncReaderFromReader>(download_->event_loop_, payload_reader);
18✔
96
        download_->current_payload_name_ = payload_reader->Name();
9✔
97

98
        auto stream_path =
99
                path::Join(update_module_workdir_, string("streams"), download_->current_payload_name_);
18✔
100
        DownloadErrorHandler(PrepareAndOpenStreamPipe(
9✔
101
                stream_path, [this](io::ExpectedAsyncWriterPtr writer) { StreamOpenHandler(writer); }));
23✔
102

103
        string stream_next_string = path::Join("streams", download_->current_payload_name_);
18✔
104
        size_t entry_size = stream_next_string.size() + 1;
9✔
105
        if (entry_size > download_->buffer_.size()) {
9✔
106
                DownloadErrorHandler(error::Error(
×
107
                        make_error_condition(errc::no_buffer_space), "Payload name is too large for buffer"));
×
108
                return;
×
109
        }
110
        copy(stream_next_string.begin(), stream_next_string.end(), download_->buffer_.begin());
9✔
111
        download_->buffer_[entry_size - 1] = '\n';
9✔
112
        DownloadErrorHandler(download_->stream_next_writer_->AsyncWrite(
18✔
113
                download_->buffer_.begin(),
9✔
114
                download_->buffer_.begin() + entry_size,
9✔
115
                [this, entry_size](io::ExpectedSize result) {
18✔
116
                        StreamNextWriteHandler(entry_size, result);
9✔
117
                }));
45✔
118
}
119

120
void UpdateModule::StreamOpenHandler(io::ExpectedAsyncWriterPtr writer) {
5✔
121
        if (!writer) {
5✔
122
                DownloadErrorHandler(writer.error());
×
123
                return;
×
124
        }
125
        download_->current_stream_writer_ = writer.value();
5✔
126

127
        DownloadErrorHandler(download_->current_payload_reader_->AsyncRead(
10✔
128
                download_->buffer_.begin(), download_->buffer_.end(), [this](io::ExpectedSize result) {
10✔
129
                        PayloadReadHandler(result);
5✔
130
                }));
25✔
131
}
132

133
void UpdateModule::StreamNextWriteHandler(size_t expected_n, io::ExpectedSize result) {
9✔
134
        // Close stream-next writer.
135
        download_->stream_next_writer_.reset();
9✔
136
        if (!result) {
9✔
137
                DownloadErrorHandler(result.error());
1✔
138
        } else if (expected_n != result.value()) {
8✔
139
                DownloadErrorHandler(error::Error(
×
140
                        make_error_condition(errc::io_error),
×
141
                        "Unexpected number of written bytes to stream-next"));
×
142
        }
143
}
9✔
144

145
void UpdateModule::PayloadReadHandler(io::ExpectedSize result) {
531✔
146
        if (!result) {
531✔
147
                // Close streams.
148
                download_->current_stream_writer_.reset();
×
149
                download_->current_payload_reader_.reset();
×
150
                DownloadErrorHandler(result.error());
×
151
        } else if (result.value() > 0) {
531✔
152
                DownloadErrorHandler(download_->current_stream_writer_->AsyncWrite(
974✔
153
                        download_->buffer_.begin(),
487✔
154
                        download_->buffer_.begin() + result.value(),
487✔
155
                        [this, result](io::ExpectedSize write_result) {
487✔
156
                                StreamWriteHandler(result.value(), write_result);
487✔
157
                        }));
2,435✔
158
        } else {
159
                // Close streams.
160
                download_->current_stream_writer_.reset();
44✔
161
                download_->current_payload_reader_.reset();
44✔
162

163
                if (download_->downloading_to_files_) {
44✔
164
                        StartDownloadToFile();
40✔
165
                } else {
166
                        DownloadErrorHandler(OpenStreamNextPipe(
4✔
167
                                [this](io::ExpectedAsyncWriterPtr writer) { StreamNextOpenHandler(writer); }));
11✔
168
                }
169
        }
170
}
531✔
171

172
void UpdateModule::StreamWriteHandler(size_t expected_n, io::ExpectedSize result) {
487✔
173
        if (!result) {
487✔
174
                DownloadErrorHandler(result.error());
1✔
175
        } else if (expected_n != result.value()) {
486✔
176
                DownloadErrorHandler(error::Error(
×
177
                        make_error_condition(errc::io_error),
×
178
                        "Unexpected number of written bytes to download stream"));
×
179
        } else {
180
                download_->written_ += result.value();
486✔
181
                log::Trace("Wrote " + to_string(download_->written_) + " bytes to Update Module");
486✔
182
                DownloadErrorHandler(download_->current_payload_reader_->AsyncRead(
972✔
183
                        download_->buffer_.begin(), download_->buffer_.end(), [this](io::ExpectedSize result) {
972✔
184
                                PayloadReadHandler(result);
486✔
185
                        }));
2,430✔
186
        }
187
}
487✔
188

189
void UpdateModule::EndStreamNext() {
2✔
190
        // Empty write.
191
        DownloadErrorHandler(download_->stream_next_writer_->AsyncWrite(
4✔
192
                download_->buffer_.begin(), download_->buffer_.begin(), [this](io::ExpectedSize result) {
4✔
193
                        if (!result) {
2✔
194
                                DownloadErrorHandler(result.error());
×
195
                        } else {
196
                                DownloadErrorHandler(error::NoError);
2✔
197
                        }
198
                        // Close writer.
199
                        download_->stream_next_writer_.reset();
2✔
200
                        // No further action necessary. Now we just need to wait for the process to finish.
201
                }));
8✔
202
}
2✔
203

204
void UpdateModule::DownloadErrorHandler(const error::Error &err) {
1,127✔
205
        if (err != error::NoError) {
1,127✔
206
                EndDownloadLoop(err);
9✔
207
        }
208
}
1,127✔
209

210
void UpdateModule::EndDownloadLoop(const error::Error &err) {
74✔
211
        download_->download_finished_handler_(err);
74✔
212
}
74✔
213

214
void UpdateModule::DownloadTimeoutHandler() {
2✔
215
        download_->proc_->EnsureTerminated();
2✔
216
        EndDownloadLoop(error::Error(
2✔
217
                make_error_condition(errc::timed_out), "Update Module Download process timed out"));
4✔
218
}
2✔
219

220
void UpdateModule::ProcessEndedHandler(error::Error err) {
70✔
221
        if (err != error::NoError) {
70✔
222
                err = GetProcessError(err);
4✔
223
                DownloadErrorHandler(error::Error(
4✔
224
                        err.code, "Download: Update Module returned non-zero status: " + err.message));
8✔
225
        } else if (download_->module_has_finished_download_) {
66✔
226
                EndDownloadLoop(error::NoError);
2✔
227
        } else if (download_->module_has_started_download_) {
64✔
228
                DownloadErrorHandler(error::Error(
2✔
229
                        make_error_condition(errc::broken_pipe),
2✔
230
                        "Update Module started downloading, but did not finish"));
6✔
231
        } else {
232
                download_->downloading_to_files_ = true;
62✔
233
                download_->stream_next_opener_.reset();
62✔
234
                download_->current_stream_opener_.reset();
62✔
235
                err = DeleteStreamsFiles();
62✔
236
                if (err != error::NoError) {
62✔
237
                        DownloadErrorHandler(err);
×
238
                } else {
239
                        StartDownloadToFile();
62✔
240
                }
241
        }
242
}
70✔
243

244
void UpdateModule::StartDownloadToFile() {
102✔
245
        auto reader = download_->payload_.Next();
102✔
246
        if (!reader) {
102✔
247
                if (reader.error().code
122✔
248
                        == artifact::parser_error::MakeError(
61✔
249
                                   artifact::parser_error::NoMorePayloadFilesError, "")
122✔
250
                                   .code) {
251
                        log::Debug("Downloaded all files to `files` directory.");
61✔
252
                        EndDownloadLoop(error::NoError);
61✔
253
                } else {
254
                        DownloadErrorHandler(reader.error());
×
255
                }
256
                return;
61✔
257
        }
258
        auto payload_reader = make_shared<artifact::Reader>(std::move(reader.value()));
41✔
259
        download_->current_payload_reader_ =
41✔
260
                make_shared<events::io::AsyncReaderFromReader>(download_->event_loop_, payload_reader);
82✔
261
        download_->current_payload_name_ = payload_reader->Name();
41✔
262

263
        auto stream_path = path::Join(update_module_workdir_, string("files"));
82✔
264
        auto err = PrepareDownloadDirectory(stream_path);
41✔
265
        if (err != error::NoError) {
41✔
266
                DownloadErrorHandler(err);
×
267
                return;
×
268
        }
269

270
        stream_path = path::Join(stream_path, download_->current_payload_name_);
41✔
271

272
        auto current_stream_writer =
273
                make_shared<events::io::AsyncFileDescriptorWriter>(download_->event_loop_);
41✔
274
        err = current_stream_writer->Open(stream_path);
41✔
275
        if (err != error::NoError) {
41✔
276
                DownloadErrorHandler(err);
1✔
277
                return;
1✔
278
        }
279
        download_->current_stream_writer_ = current_stream_writer;
40✔
280

281
        DownloadErrorHandler(download_->current_payload_reader_->AsyncRead(
80✔
282
                download_->buffer_.begin(), download_->buffer_.end(), [this](io::ExpectedSize result) {
80✔
283
                        PayloadReadHandler(result);
40✔
284
                }));
200✔
285
}
286

287
} // namespace v3
288
} // namespace update_module
289
} // namespace update
290
} // namespace mender
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

© 2025 Coveralls, Inc