http-downloader.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2020 Intel Corporation. All Rights Reserved.
3 
4 
5 
6 #ifdef CHECK_FOR_UPDATES
7 #include <sstream>
8 #include <iostream>
9 #include <thread>
10 #include <atomic>
11 #include <mutex>
12 #include <curl/curl.h>
13 #include <curl/easy.h>
14 #include "types.h"
15 #endif // CHECK_FOR_UPDATES
16 
17 #include "http-downloader.h"
18 
19 
20 namespace rs2
21 {
22  namespace http
23  {
24 
25 #ifndef CHECK_FOR_UPDATES
26  // Dummy functions
29  bool http_downloader::download_to_stream(const std::string& url, std::stringstream &output, user_callback_func_type user_callback_func) { return false; }
30  bool http_downloader::download_to_file(const std::string& url, const std::string &file_name, user_callback_func_type user_callback_func) { return false; }
31  bool http_downloader::download_to_bytes_vector(const std::string& url, std::vector<uint8_t> &output, user_callback_func_type user_callback_func) { return false; }
32 
33 #else
34 
35  std::mutex initialize_mutex;
36  static const curl_off_t HALF_SEC = 500000; // User call back function delay
37  static const int CONNECT_TIMEOUT = 5L; // Libcurl connection timeout 5 [Sec]
38 
39  struct progress_data {
40  curl_off_t last_run_time;
41  user_callback_func_type user_callback_func;
42  CURL *curl;
43  };
44 
45 
46  size_t stream_write_callback(void *input_stream, size_t size, size_t nmemb, void *output_stream)
47  {
48  if (input_stream && output_stream)
49  {
50  std::string data((const char*)input_stream, (size_t)size * nmemb);
51  *((std::stringstream*)output_stream) << data;
52  return size * nmemb;
53  }
54  return 0; // Error
55  }
56 
57  size_t vector_write_callback(void *input_stream, size_t size, size_t nmemb, void *output_vec)
58  {
59  uint8_t* source_bytes(static_cast<uint8_t*>(input_stream));
60 
61  if (input_stream && output_vec)
62  {
63  int total_size((int)(size * nmemb));
64  while (total_size > 0)
65  {
66  static_cast<std::vector<uint8_t> *>(output_vec)->push_back(*source_bytes);
67  source_bytes++;
68  --total_size;
69  }
70 
71  return size * nmemb;
72  }
73  return 0; // Error
74  }
75 
76  size_t file_write_callback(void *input_stream, size_t size, size_t nmemb, void *output)
77  {
78 
79  if (input_stream && output)
80  {
81  std::ofstream &out_stream(*static_cast<std::ofstream*> (output));
82 
83  size_t num_of_bytem(nmemb*size);
84  out_stream.write((char *)input_stream, num_of_bytem);
85  return size * nmemb;
86 
87  }
88  return 0; // Error
89  }
90 
91  // This function will be called if CURLOPT_NOPROGRESS is set to 0
92  // Return value: 0 = continue download / 1 = stop download
93  int progress_callback(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
94  {
95  progress_data *myp = static_cast<progress_data *>(p);
96  CURL *curl(myp->curl);
97  curl_off_t curtime(0);
98  curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
99  if (dltotal != 0 && (curtime - myp->last_run_time > HALF_SEC))
100  {
101  myp->last_run_time = curtime;
102  return myp->user_callback_func(static_cast<uint64_t>(dlnow),
103  static_cast<uint64_t>(dltotal)) == callback_result::CONTINUE_DOWNLOAD ? 0 : 1;
104  }
105  else
106  {
107  return 0;
108  }
109  }
110 
112  {
113  // Protect curl_easy_init() it is not considers thread safe
114  std::lock_guard<std::mutex> lock(initialize_mutex);
115  _curl = curl_easy_init();
116  }
117 
119  {
120  std::lock_guard<std::mutex> lock(initialize_mutex);
121  curl_easy_cleanup(_curl);
122  }
123 
124  bool http_downloader::download_to_stream(const std::string& url, std::stringstream &output, user_callback_func_type user_callback_func)
125  {
126  if (!_curl) return false;
127 
128  set_common_options(url);
129  curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, stream_write_callback);
130  curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &output);
131  curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER ,0L);
132  curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYHOST ,0L);
133 
134  progress_data progress_record; // Should stay here - "curl_easy_perform" use it
135  if (user_callback_func)
136  {
137  register_progress_call_back(progress_record, user_callback_func);
138  }
139  auto res = curl_easy_perform(_curl);
140 
141  if (CURLE_OK != res)
142  {
143  LOG_ERROR("Download error from URL: " + url + ", error info: " + std::string(curl_easy_strerror(res)));
144  return false;
145  }
146  return true;
147  }
148 
149  bool http_downloader::download_to_bytes_vector(const std::string& url, std::vector<uint8_t> &output, user_callback_func_type user_callback_func)
150  {
151  if (!_curl) return false;
152 
153  set_common_options(url);
154  curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, vector_write_callback);
155  curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &output);
156 
157  progress_data progress_record; // Should stay here - "curl_easy_perform" use it
158  if (user_callback_func)
159  {
160  register_progress_call_back(progress_record, user_callback_func);
161  }
162  auto res = curl_easy_perform(_curl);
163 
164  if (CURLE_OK != res)
165  {
166  LOG_ERROR("Download error from URL: " + url + ", error info: " + std::string(curl_easy_strerror(res)));
167  return false;
168  }
169  return true;
170  }
171 
172 
174  {
175  if (!_curl) return false;
176 
177  /* open the file */
178  std::ofstream out_file(file_name, std::ios::out);
179 
180  if (out_file.good())
181  {
182  set_common_options(url);
183  curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, file_write_callback);
184  curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &out_file);
185 
186  progress_data progress_record; // Should stay here - "curl_easy_perform" use it
187  if (user_callback_func)
188  {
189  register_progress_call_back(progress_record, user_callback_func);
190  }
191  auto res = curl_easy_perform(_curl);
192  out_file.close();
193 
194  if (CURLE_OK != res)
195  {
196  LOG_ERROR("Download error from URL: " + url + ", error info: " + std::string(curl_easy_strerror(res)));
197  return false;
198  }
199  }
200  else
201  {
202  LOG_ERROR("Download error - Cannot open local file: " + file_name);
203  return false;
204  }
205 
206  return true;
207  }
208 
210  {
211  curl_easy_setopt(_curl, CURLOPT_URL, url.c_str()); // provide the URL to use in the request
212  curl_easy_setopt(_curl, CURLOPT_FOLLOWLOCATION, 1L); // follow HTTP 3xx redirects
213  curl_easy_setopt(_curl, CURLOPT_NOSIGNAL, 1); // skip all signal handling
214  curl_easy_setopt(_curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT); // timeout for the connect phase
215  curl_easy_setopt(_curl, CURLOPT_FAILONERROR, 1L); // request failure on HTTP response >= 400
216  curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, 1L); // switch off the progress meter
217  }
218  void http_downloader::register_progress_call_back(progress_data &progress_record, user_callback_func_type user_callback_func)
219  {
220  progress_record = { 0, user_callback_func, _curl };
221  curl_easy_setopt(_curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
222  curl_easy_setopt(_curl, CURLOPT_XFERINFODATA, &progress_record);
223  curl_easy_setopt(_curl, CURLOPT_NOPROGRESS, 0L);
224  }
225 #endif
226  }
227 }
static const textual_icon lock
Definition: model-views.h:218
GLfloat GLfloat p
Definition: glext.h:12687
bool download_to_bytes_vector(const std::string &url, std::vector< uint8_t > &output, user_callback_func_type user_callback_func=user_callback_func_type())
Definition: cah-model.h:10
GLsizei const GLchar *const * string
unsigned char uint8_t
Definition: stdint.h:78
GLsizeiptr size
#define LOG_ERROR(...)
Definition: src/types.h:242
std::function< callback_result(uint64_t dl_current_bytes, uint64_t dl_total_bytes)> user_callback_func_type
bool download_to_stream(const std::string &url, std::stringstream &output, user_callback_func_type user_callback_func=user_callback_func_type())
GLuint res
Definition: glext.h:8856
GLboolean * data
void register_progress_call_back(progress_data &progress_record, user_callback_func_type user_callback_func)
void set_common_options(const std::string &url)
bool download_to_file(const std::string &url, const std::string &file_name, user_callback_func_type user_callback_func=user_callback_func_type())


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:16