24
24
#include < cstdlib>
25
25
#include < cstring>
26
26
27
+ #include < tuple>
28
+
27
29
#include < dirent.h>
28
30
#include < curl/curl.h>
29
31
#include < sys/stat.h>
@@ -82,18 +84,49 @@ namespace {
82
84
return written;
83
85
}
84
86
85
- sua::TechCode download (const std::string & caPath, const std::string & caFile, const char * url)
87
+ class CurlGlobalGuard {
88
+ public:
89
+ CURLcode init () {
90
+ return curl_global_init (CURL_GLOBAL_ALL);
91
+ }
92
+
93
+ ~CurlGlobalGuard () {
94
+ curl_global_cleanup ();
95
+ }
96
+ };
97
+
98
+ class CurlEasyHandleGuard {
99
+ public:
100
+ CURL * init () {
101
+ _handle = curl_easy_init ();
102
+ return _handle;
103
+ }
104
+
105
+ ~CurlEasyHandleGuard () {
106
+ if (_handle) {
107
+ curl_easy_cleanup (_handle);
108
+ }
109
+ }
110
+
111
+ private:
112
+ CURL * _handle = nullptr ;
113
+ };
114
+
115
+ sua::DownloadResult download (const std::string & caPath, const std::string & caFile, const char * url)
86
116
{
87
- CURLcode gres = curl_global_init (CURL_GLOBAL_ALL);
88
- if (gres != 0 ) {
89
- sua::Logger::critical (" curl_global_init failed with code = {}" , gres);
90
- return sua::TechCode::DownloadFailed;
117
+ CurlGlobalGuard global_guard;
118
+ auto init_status = global_guard.init ();
119
+ if (init_status != 0 ) {
120
+ sua::Logger::critical (" curl_global_init failed with code = {}" , init_status);
121
+ return std::make_tuple (sua::TechCode::DownloadFailed, " libcurl init failed" );
91
122
}
92
123
93
- CURL* easy_handle = curl_easy_init ();
94
- if (!easy_handle) {
124
+ CurlEasyHandleGuard easy_guard;
125
+ auto h = easy_guard.init ();
126
+
127
+ if (!h) {
95
128
sua::Logger::critical (" curl_easy_init failed" );
96
- return sua::TechCode::DownloadFailed;
129
+ return std::make_tuple ( sua::TechCode::DownloadFailed, " libcurl init failed " ) ;
97
130
}
98
131
99
132
DIR* dir = opendir (FILE_DIR);
@@ -103,49 +136,50 @@ namespace {
103
136
const int dir_err = mkdir (FILE_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
104
137
if (dir_err) {
105
138
sua::Logger::critical (" Issue with creating a dir {}, error: {}" , FILE_DIR, dir_err);
106
- return sua::TechCode::DownloadFailed;
139
+ return std::make_tuple ( sua::TechCode::DownloadFailed, " temporary file folder could not be created " ) ;
107
140
}
108
141
}
109
142
110
143
long response_code;
111
144
FILE* fp = fopen (FILE_PATH, " wb" );
112
145
if (!fp) {
113
146
sua::Logger::critical (" Failed to open '{}' for writing" , FILE_PATH);
114
- return sua::TechCode::DownloadFailed;
147
+ return std::make_tuple ( sua::TechCode::DownloadFailed, " temporary file could not be opened for writing " ) ;
115
148
}
116
149
117
- curl_easy_setopt (easy_handle , CURLOPT_URL, url);
118
- curl_easy_getinfo (easy_handle , CURLINFO_RESPONSE_CODE, &response_code);
150
+ curl_easy_setopt (h , CURLOPT_URL, url);
151
+ curl_easy_getinfo (h , CURLINFO_RESPONSE_CODE, &response_code);
119
152
if (!caFile.empty ()) {
120
- curl_easy_setopt (easy_handle , CURLOPT_CAINFO, caFile.c_str ());
153
+ curl_easy_setopt (h , CURLOPT_CAINFO, caFile.c_str ());
121
154
} else {
122
- curl_easy_setopt (easy_handle , CURLOPT_CAPATH, caPath.c_str ());
155
+ curl_easy_setopt (h , CURLOPT_CAPATH, caPath.c_str ());
123
156
}
124
- curl_easy_setopt (easy_handle, CURLOPT_SSL_VERIFYPEER, 1 );
125
- curl_easy_setopt (easy_handle, CURLOPT_WRITEFUNCTION, write_data);
126
- curl_easy_setopt (easy_handle, CURLOPT_WRITEDATA, fp);
127
- curl_easy_setopt (easy_handle, CURLOPT_FOLLOWLOCATION, 1L );
128
- curl_easy_setopt (easy_handle, CURLOPT_PROGRESSDATA, &data);
129
- curl_easy_setopt (easy_handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
130
- curl_easy_setopt (easy_handle, CURLOPT_NOPROGRESS, 0 );
131
- CURLcode res = curl_easy_perform (easy_handle);
157
+ curl_easy_setopt (h, CURLOPT_SSL_VERIFYPEER, 1L );
158
+ curl_easy_setopt (h, CURLOPT_SSL_VERIFYHOST, 2L );
159
+ curl_easy_setopt (h, CURLOPT_WRITEFUNCTION, write_data);
160
+ curl_easy_setopt (h, CURLOPT_WRITEDATA, fp);
161
+ curl_easy_setopt (h, CURLOPT_FOLLOWLOCATION, 1L );
162
+ curl_easy_setopt (h, CURLOPT_PROGRESSDATA, &data);
163
+ curl_easy_setopt (h, CURLOPT_PROGRESSFUNCTION, progress_callback);
164
+ curl_easy_setopt (h, CURLOPT_NOPROGRESS, 0 );
165
+ curl_easy_setopt (h, CURLOPT_PROTOCOLS_STR, " https" );
166
+ CURLcode res = curl_easy_perform (h);
132
167
133
168
sua::Logger::debug (" curl_easy_perform ended with code = '{}'" , res);
134
169
135
170
long http_code = 0 ;
136
- curl_easy_getinfo (easy_handle, CURLINFO_RESPONSE_CODE, &http_code);
137
- curl_easy_cleanup (easy_handle);
138
- curl_global_cleanup ();
171
+ curl_easy_getinfo (h, CURLINFO_RESPONSE_CODE, &http_code);
139
172
fclose (fp);
140
173
progressNotificationLimiter = 0 ;
141
174
142
175
sua::Logger::debug (" CURLINFO_RESPONSE_CODE = {}" , http_code);
143
176
if (http_code != 200 ) {
144
- sua::Logger::error (curl_easy_strerror (res));
145
- return sua::TechCode::DownloadFailed;
177
+ auto e = curl_easy_strerror (res);
178
+ sua::Logger::error (e);
179
+ return std::make_tuple (sua::TechCode::DownloadFailed, e);
146
180
}
147
181
148
- return sua::TechCode::OK;
182
+ return std::make_tuple ( sua::TechCode::OK, " " ) ;
149
183
}
150
184
151
185
} // namespace
@@ -162,7 +196,7 @@ namespace sua {
162
196
strncpy (FILE_PATH, filepath.c_str (), FILENAME_MAX - 1 );
163
197
}
164
198
165
- TechCode Downloader::start (const std::string & input)
199
+ DownloadResult Downloader::start (const std::string & input)
166
200
{
167
201
return download (_context.caDirectory , _context.caFilepath , input.c_str ());
168
202
}
0 commit comments