Message ID | 20180305154006.18122-5-christian.storm@siemens.com |
---|---|
State | Accepted |
Headers | show |
Series | [1/8] channel_curl: add support for Basic Auth credentials | expand |
On 05/03/2018 16:40, Christian Storm wrote: > Instead of the downloader having an own cURL binding > implementation, make use of the generic channel_curl. > > Signed-off-by: Christian Storm <christian.storm@siemens.com> > --- > Kconfig | 2 +- > corelib/downloader.c | 347 +++++++-------------------------------------------- > 2 files changed, 49 insertions(+), 300 deletions(-) > > diff --git a/Kconfig b/Kconfig > index fe2f5ae..ed5559c 100644 > --- a/Kconfig > +++ b/Kconfig > @@ -286,7 +286,7 @@ config DOWNLOAD > bool "Enable image downloading" > default n > depends on HAVE_LIBCURL > - select CURL > + select CHANNEL_CURL > help > Enable update from image URL using libcurl. The stream is sent via IPC > to the installer as it is done for other interfaces. > diff --git a/corelib/downloader.c b/corelib/downloader.c > index 108a6f6..23471f1 100644 > --- a/corelib/downloader.c > +++ b/corelib/downloader.c > @@ -5,29 +5,17 @@ > * SPDX-License-Identifier: GPL-2.0-or-later > */ > > -#include <stdio.h> > #include <stdlib.h> > -#include <stdint.h> > -#include <unistd.h> > -#include <string.h> > #include <errno.h> > -#include <ctype.h> > #include <getopt.h> > -#include <sys/types.h> > -#include <fcntl.h> > -#include <sys/stat.h> > > -#include <curl/curl.h> > - > -#include "bsdqueue.h" > #include "util.h" > -#include "swupdate.h" > -#include "installer.h" > #include "network_ipc.h" > +#include "download_interface.h" > +#include "channel.h" > +#include "channel_curl.h" > #include "parselib.h" > -#include "swupdate_status.h" > #include "swupdate_settings.h" > -#include "download_interface.h" > > #define SETSTRING(p, v) do { \ > if (p) \ > @@ -37,30 +25,13 @@ > > /* > * Number of seconds while below low speed > - * limit before aborting > - * it can be overwritten by -t > + * limit before aborting. It can be overwritten > + * by -t command line flag. > */ > #define DL_LOWSPEED_TIME 300 > > #define DL_DEFAULT_RETRIES 3 > > -static int cnt = 0; > - > -struct dwl_options { > - char *url; > - unsigned int retries; > - unsigned int timeout; > - char *auth; > -}; > - > -/* notify download progress each second */ > -#define MINIMAL_PROGRESS_INTERVAL 1 > - > -struct dlprogress { > - double lastruntime; > - CURL *curl; > -}; > - > static struct option long_options[] = { > {"url", required_argument, NULL, 'u'}, > {"retries", required_argument, NULL, 'r'}, > @@ -68,242 +39,37 @@ static struct option long_options[] = { > {"authentification", required_argument, NULL, 'a'}, > {NULL, 0, NULL, 0}}; > > - > -/* > - * Callback from the libcurl API to progress meter function > - * This function gets called by libcurl instead of its internal equivalent. > - */ > -static int download_info(void *p, > - curl_off_t dltotal, curl_off_t dlnow, > - curl_off_t __attribute__ ((__unused__)) ultotal, > - curl_off_t __attribute__ ((__unused__)) ulnow) > -{ > - struct dlprogress *dlp = (struct dlprogress *)p; > - CURL *curl = dlp->curl; > - double curtime = 0; > - curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); > - > - if ((curtime - dlp->lastruntime) >= MINIMAL_PROGRESS_INTERVAL) { > - dlp->lastruntime = curtime; > - INFO("Received : %" CURL_FORMAT_CURL_OFF_T " / %" > - CURL_FORMAT_CURL_OFF_T, dlnow, dltotal); > - } > - > - return 0; > -} > - > -/* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */ > -static int legacy_download_info(void *p, > - double dltotal, double dlnow, > - double ultotal, double ulnow) > -{ > - return download_info(p, > - (curl_off_t)dltotal, > - (curl_off_t)dlnow, > - (curl_off_t)ultotal, > - (curl_off_t)ulnow); > -} > - > -/* > - * Callback from the libcurl API > - * It is called any time a chunk of data is received > - * to transfer it via IPC to the installer > - */ > -static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) > -{ > - int ret; > - int fd; > - > - if (!nmemb) > - return 0; > - if (!userp) { > - ERROR("Failure IPC stream file descriptor \n"); > - return -EFAULT; > - } > - > - fd = *(int *)userp; > - ret = ipc_send_data(fd, buffer, size * nmemb); > - if (ret < 0) { > - ERROR("Failure writing into IPC Stream\n"); > - return ret; > - } > - cnt += size * nmemb; > - > - return nmemb; > -} > - > -/* Minimum bytes/sec, else connection is broken */ > -#define DL_LOWSPEED_BYTES 8 > - > -/* > - * libcurl options (see easy interface in libcurl documentation) > - * are grouped together into this function > - */ > -static void set_option_common(CURL *curl_handle, > - unsigned long lowspeed_time, > - struct dlprogress *prog) > -{ > - int ret; > - > - prog->lastruntime = 0; > - prog->curl = curl_handle; > - > - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "swupdate"); > - > - curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, legacy_download_info); > - curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, prog); > -#if LIBCURL_VERSION_NUM >= 0x072000 > - /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will > - compile as they won't have the symbols around. > - > - If built with a newer libcurl, but running with an older libcurl: > - curl_easy_setopt() will fail in run-time trying to set the new > - callback, making the older callback get used. > - > - New libcurls will prefer the new callback and instead use that one > - even if both callbacks are set. */ > - curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, download_info); > - curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, prog); > -#endif > - curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L); > - > - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, DL_LOWSPEED_BYTES); > - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, lowspeed_time); > - > - /* enable TCP keep-alive for this transfer */ > - ret = curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 1L); > - if (ret == CURLE_UNKNOWN_OPTION) { > - TRACE("No keep alive (unsupported in curl)"); > - return; > - } > - > - /* keep-alive idle time to 240 seconds */ > - curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPIDLE, 240L); > - > - /* interval time between keep-alive probes: 120 seconds */ > - curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPINTVL, 120L); > -} > - > /* > - * This provide a pull from an external server > - * It si not thought to work with local (file://) > - * for that, the -i option is used. > + * This provides a pull from an external server > + * It is not thought to work with local (file://) > + * files. For that, the -i option is used. > */ > -static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries, > - unsigned long lowspeed_time, char *auth) > +static RECOVERY_STATUS download_from_url(channel_data_t* channel_data) > { > - CURL *curl_handle; > - CURLcode res = CURLE_GOT_NOTHING; > - int fd; > - int attempt = 10; > - int result; > - double dummy; > - unsigned long long dwlbytes = 0; > - unsigned int i; > - struct dlprogress progress; > - > - > - /* > - * Maybe daemon is not yet started, > - * try several times > - */ > - while (--attempt) { > - fd = ipc_inst_start(); > - if (fd > 0) > - break; > - sleep(1); > - } > - > - if (fd < 0) { > - ERROR("Error getting IPC: %s\n", strerror(errno)); > + channel_t *channel = channel_new(); > + if (channel->open(channel, channel_data) != CHANNEL_OK) { > + free(channel); > return FAILURE; > } > - errno = 0; > > - TRACE("download from url started : %s", image_url); > - if (!image_url || !strlen(image_url)) { > - ERROR("Image URL not provided... aborting download and update\n"); > - return FAILURE; > - } > - > - /* We are starting a download */ > + TRACE("Image download started : %s", channel_data->url); > notify(DOWNLOAD, 0, INFOLEVEL, NULL); > > - curl_global_init(CURL_GLOBAL_ALL); > - curl_handle = curl_easy_init(); > - if (!curl_handle) { > - /* something very bad, it should never happen */ > - ERROR("FAULT: no handle from libcurl"); > - return FAILURE; > - } > - > - /* Set URL */ > - if (curl_easy_setopt(curl_handle, CURLOPT_URL, image_url) != CURLE_OK) { > - TRACE("Runs out of memory: serious internal error"); > - return FAILURE; > - } > - > - /* Set Authentification */ > - if (auth && curl_easy_setopt(curl_handle, CURLOPT_USERPWD, auth) != CURLE_OK) { > - TRACE("Runs out of memory: serious internal error"); > - return FAILURE; > - } > - > - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); > - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd); > - set_option_common(curl_handle, lowspeed_time, &progress); > - > - TRACE("Image download started : %s", image_url); > - > - for (i = 0; (res != CURLE_OK); i++) { > - /* if resume, set the offset */ > - if (i) { > - TRACE("Connection with server interrupted, try RESUME after %llu", > - dwlbytes); > - if (curl_easy_setopt(curl_handle,CURLOPT_RESUME_FROM_LARGE, > - dwlbytes) != CURLE_OK) { > - TRACE("CURLOPT_RESUME_FROM_LARGE not implemented"); > - break; > - } > - > - /* motivation: router restart, DNS reconfiguration */ > - sleep(20); > - } > - res = curl_easy_perform(curl_handle); > - > - /* if size cannot be determined, exit because no resume is possible */ > - if (curl_easy_getinfo(curl_handle, > - CURLINFO_SIZE_DOWNLOAD, > - &dummy) != CURLE_OK) > - break; > - > - dwlbytes += dummy; > - > - /* Check if max attempts is reached */ > - if (retries && (i >= retries)) > - break; > - > - } > - > - curl_easy_cleanup(curl_handle); > - curl_global_cleanup(); > - > - if (res == CURLE_OK) { > - result = ipc_wait_for_complete(NULL); > - } else { > - INFO("Error : %s", curl_easy_strerror(res)); > + RECOVERY_STATUS result = SUCCESS; > + channel_op_res_t chanresult = channel->get_file(channel, channel_data, FD_USE_IPC); > + if (chanresult != CHANNEL_OK) { > result = FAILURE; > } > - > - ipc_end(fd); > - > + ipc_wait_for_complete(NULL); > + channel->close(channel); > + free(channel); > return result; > } > > static int download_settings(void *elem, void __attribute__ ((__unused__)) *data) > { > - struct dwl_options *opt = (struct dwl_options *)data; > - char tmp[128]; > + channel_data_t *opt = (channel_data_t *)data; > + char tmp[SWUPDATE_GENERAL_STRING_SIZE]; > > GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "url", tmp); > if (strlen(tmp)) { > @@ -320,7 +86,7 @@ static int download_settings(void *elem, void __attribute__ ((__unused__)) *dat > get_field(LIBCFG_PARSER, elem, "retries", > &opt->retries); > get_field(LIBCFG_PARSER, elem, "timeout", > - &opt->timeout); > + &opt->low_speed_timeout); > > return 0; > } > @@ -338,40 +104,36 @@ void download_print_help(void) > DL_DEFAULT_RETRIES, DL_LOWSPEED_TIME); > } > > +static channel_data_t channel_options = { > + .source = SOURCE_DOWNLOADER, > + .debug = false, > + .retries = DL_DEFAULT_RETRIES, > + .low_speed_timeout = DL_LOWSPEED_TIME > +}; > + > int start_download(const char *fname, int argc, char *argv[]) > { > - struct dwl_options options; > - unsigned int attempt; > - int choice = 0; > - RECOVERY_STATUS result; > - > - memset(&options, 0, sizeof(options)); > - > - options.retries = DL_DEFAULT_RETRIES; > - options.timeout = DL_LOWSPEED_TIME; > - options.auth = NULL; > - > if (fname) { > - read_module_settings(fname, "download", download_settings, > - &options); > + read_module_settings(fname, "download", download_settings, &channel_options); > } > > /* reset to optind=1 to parse download's argument vector */ > optind = 1; > + int choice = 0; > while ((choice = getopt_long(argc, argv, "t:u:r:a:", > long_options, NULL)) != -1) { > switch (choice) { > case 't': > - options.timeout = strtoul(optarg, NULL, 10); > + channel_options.low_speed_timeout = strtoul(optarg, NULL, 10); > break; > case 'u': > - SETSTRING(options.url, optarg); > + SETSTRING(channel_options.url, optarg); > break; > case 'a': > - SETSTRING(options.auth, optarg); > + SETSTRING(channel_options.auth, optarg); > break; > case 'r': > - options.retries = strtoul(optarg, NULL, 10); > + channel_options.retries = strtoul(optarg, NULL, 10); > break; > case '?': > default: > @@ -379,34 +141,21 @@ int start_download(const char *fname, int argc, char *argv[]) > } > } > > - result = FAILURE; > - > - /* > - * Maybe we need a different option as retries > - * to check if an updated must be retried > - */ > - for (attempt = 0;; attempt++) { > - result = download_from_url(options.url, options.retries, > - options.timeout, options.auth); > - if (result != FAILURE) { > - ipc_message msg; > - if (ipc_postupdate(&msg) != 0) { > - result = FAILURE; > - } else { > - result = msg.type == ACK ? result : FAILURE; > - } > - break; > + RECOVERY_STATUS result = download_from_url(&channel_options); > + if (result != FAILURE) { > + ipc_message msg; > + if (ipc_postupdate(&msg) != 0) { > + result = FAILURE; > + } else { > + result = msg.type == ACK ? result : FAILURE; > } > + } > > - if (options.retries > 0 && attempt >= options.retries) > - break; > - > - /* > - * motivation: slow connection, download_from_url fetched half the > - * image, then aborted due to lowspeed_timeout, if we retry immediately > - * we would just waste our bandwidth. Useful for A/B images. > - */ > - sleep(60); > + if (channel_options.url != NULL) { > + free(channel_options.url); > + } > + if (channel_options.auth != NULL) { > + free(channel_options.auth); > } > > exit(result == SUCCESS ? EXIT_SUCCESS : result); > Code is becoming much more cleaner and readable and silly duplication are removed - thanks ! Reviewed-by: Stefano Babic <sbabic@denx.de> Best regards, Stefano Babic
diff --git a/Kconfig b/Kconfig index fe2f5ae..ed5559c 100644 --- a/Kconfig +++ b/Kconfig @@ -286,7 +286,7 @@ config DOWNLOAD bool "Enable image downloading" default n depends on HAVE_LIBCURL - select CURL + select CHANNEL_CURL help Enable update from image URL using libcurl. The stream is sent via IPC to the installer as it is done for other interfaces. diff --git a/corelib/downloader.c b/corelib/downloader.c index 108a6f6..23471f1 100644 --- a/corelib/downloader.c +++ b/corelib/downloader.c @@ -5,29 +5,17 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -#include <stdio.h> #include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <string.h> #include <errno.h> -#include <ctype.h> #include <getopt.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <curl/curl.h> - -#include "bsdqueue.h" #include "util.h" -#include "swupdate.h" -#include "installer.h" #include "network_ipc.h" +#include "download_interface.h" +#include "channel.h" +#include "channel_curl.h" #include "parselib.h" -#include "swupdate_status.h" #include "swupdate_settings.h" -#include "download_interface.h" #define SETSTRING(p, v) do { \ if (p) \ @@ -37,30 +25,13 @@ /* * Number of seconds while below low speed - * limit before aborting - * it can be overwritten by -t + * limit before aborting. It can be overwritten + * by -t command line flag. */ #define DL_LOWSPEED_TIME 300 #define DL_DEFAULT_RETRIES 3 -static int cnt = 0; - -struct dwl_options { - char *url; - unsigned int retries; - unsigned int timeout; - char *auth; -}; - -/* notify download progress each second */ -#define MINIMAL_PROGRESS_INTERVAL 1 - -struct dlprogress { - double lastruntime; - CURL *curl; -}; - static struct option long_options[] = { {"url", required_argument, NULL, 'u'}, {"retries", required_argument, NULL, 'r'}, @@ -68,242 +39,37 @@ static struct option long_options[] = { {"authentification", required_argument, NULL, 'a'}, {NULL, 0, NULL, 0}}; - -/* - * Callback from the libcurl API to progress meter function - * This function gets called by libcurl instead of its internal equivalent. - */ -static int download_info(void *p, - curl_off_t dltotal, curl_off_t dlnow, - curl_off_t __attribute__ ((__unused__)) ultotal, - curl_off_t __attribute__ ((__unused__)) ulnow) -{ - struct dlprogress *dlp = (struct dlprogress *)p; - CURL *curl = dlp->curl; - double curtime = 0; - curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); - - if ((curtime - dlp->lastruntime) >= MINIMAL_PROGRESS_INTERVAL) { - dlp->lastruntime = curtime; - INFO("Received : %" CURL_FORMAT_CURL_OFF_T " / %" - CURL_FORMAT_CURL_OFF_T, dlnow, dltotal); - } - - return 0; -} - -/* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */ -static int legacy_download_info(void *p, - double dltotal, double dlnow, - double ultotal, double ulnow) -{ - return download_info(p, - (curl_off_t)dltotal, - (curl_off_t)dlnow, - (curl_off_t)ultotal, - (curl_off_t)ulnow); -} - -/* - * Callback from the libcurl API - * It is called any time a chunk of data is received - * to transfer it via IPC to the installer - */ -static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) -{ - int ret; - int fd; - - if (!nmemb) - return 0; - if (!userp) { - ERROR("Failure IPC stream file descriptor \n"); - return -EFAULT; - } - - fd = *(int *)userp; - ret = ipc_send_data(fd, buffer, size * nmemb); - if (ret < 0) { - ERROR("Failure writing into IPC Stream\n"); - return ret; - } - cnt += size * nmemb; - - return nmemb; -} - -/* Minimum bytes/sec, else connection is broken */ -#define DL_LOWSPEED_BYTES 8 - -/* - * libcurl options (see easy interface in libcurl documentation) - * are grouped together into this function - */ -static void set_option_common(CURL *curl_handle, - unsigned long lowspeed_time, - struct dlprogress *prog) -{ - int ret; - - prog->lastruntime = 0; - prog->curl = curl_handle; - - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "swupdate"); - - curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, legacy_download_info); - curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, prog); -#if LIBCURL_VERSION_NUM >= 0x072000 - /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will - compile as they won't have the symbols around. - - If built with a newer libcurl, but running with an older libcurl: - curl_easy_setopt() will fail in run-time trying to set the new - callback, making the older callback get used. - - New libcurls will prefer the new callback and instead use that one - even if both callbacks are set. */ - curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, download_info); - curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, prog); -#endif - curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L); - - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_LIMIT, DL_LOWSPEED_BYTES); - curl_easy_setopt(curl_handle, CURLOPT_LOW_SPEED_TIME, lowspeed_time); - - /* enable TCP keep-alive for this transfer */ - ret = curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 1L); - if (ret == CURLE_UNKNOWN_OPTION) { - TRACE("No keep alive (unsupported in curl)"); - return; - } - - /* keep-alive idle time to 240 seconds */ - curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPIDLE, 240L); - - /* interval time between keep-alive probes: 120 seconds */ - curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPINTVL, 120L); -} - /* - * This provide a pull from an external server - * It si not thought to work with local (file://) - * for that, the -i option is used. + * This provides a pull from an external server + * It is not thought to work with local (file://) + * files. For that, the -i option is used. */ -static RECOVERY_STATUS download_from_url(char *image_url, unsigned int retries, - unsigned long lowspeed_time, char *auth) +static RECOVERY_STATUS download_from_url(channel_data_t* channel_data) { - CURL *curl_handle; - CURLcode res = CURLE_GOT_NOTHING; - int fd; - int attempt = 10; - int result; - double dummy; - unsigned long long dwlbytes = 0; - unsigned int i; - struct dlprogress progress; - - - /* - * Maybe daemon is not yet started, - * try several times - */ - while (--attempt) { - fd = ipc_inst_start(); - if (fd > 0) - break; - sleep(1); - } - - if (fd < 0) { - ERROR("Error getting IPC: %s\n", strerror(errno)); + channel_t *channel = channel_new(); + if (channel->open(channel, channel_data) != CHANNEL_OK) { + free(channel); return FAILURE; } - errno = 0; - TRACE("download from url started : %s", image_url); - if (!image_url || !strlen(image_url)) { - ERROR("Image URL not provided... aborting download and update\n"); - return FAILURE; - } - - /* We are starting a download */ + TRACE("Image download started : %s", channel_data->url); notify(DOWNLOAD, 0, INFOLEVEL, NULL); - curl_global_init(CURL_GLOBAL_ALL); - curl_handle = curl_easy_init(); - if (!curl_handle) { - /* something very bad, it should never happen */ - ERROR("FAULT: no handle from libcurl"); - return FAILURE; - } - - /* Set URL */ - if (curl_easy_setopt(curl_handle, CURLOPT_URL, image_url) != CURLE_OK) { - TRACE("Runs out of memory: serious internal error"); - return FAILURE; - } - - /* Set Authentification */ - if (auth && curl_easy_setopt(curl_handle, CURLOPT_USERPWD, auth) != CURLE_OK) { - TRACE("Runs out of memory: serious internal error"); - return FAILURE; - } - - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd); - set_option_common(curl_handle, lowspeed_time, &progress); - - TRACE("Image download started : %s", image_url); - - for (i = 0; (res != CURLE_OK); i++) { - /* if resume, set the offset */ - if (i) { - TRACE("Connection with server interrupted, try RESUME after %llu", - dwlbytes); - if (curl_easy_setopt(curl_handle,CURLOPT_RESUME_FROM_LARGE, - dwlbytes) != CURLE_OK) { - TRACE("CURLOPT_RESUME_FROM_LARGE not implemented"); - break; - } - - /* motivation: router restart, DNS reconfiguration */ - sleep(20); - } - res = curl_easy_perform(curl_handle); - - /* if size cannot be determined, exit because no resume is possible */ - if (curl_easy_getinfo(curl_handle, - CURLINFO_SIZE_DOWNLOAD, - &dummy) != CURLE_OK) - break; - - dwlbytes += dummy; - - /* Check if max attempts is reached */ - if (retries && (i >= retries)) - break; - - } - - curl_easy_cleanup(curl_handle); - curl_global_cleanup(); - - if (res == CURLE_OK) { - result = ipc_wait_for_complete(NULL); - } else { - INFO("Error : %s", curl_easy_strerror(res)); + RECOVERY_STATUS result = SUCCESS; + channel_op_res_t chanresult = channel->get_file(channel, channel_data, FD_USE_IPC); + if (chanresult != CHANNEL_OK) { result = FAILURE; } - - ipc_end(fd); - + ipc_wait_for_complete(NULL); + channel->close(channel); + free(channel); return result; } static int download_settings(void *elem, void __attribute__ ((__unused__)) *data) { - struct dwl_options *opt = (struct dwl_options *)data; - char tmp[128]; + channel_data_t *opt = (channel_data_t *)data; + char tmp[SWUPDATE_GENERAL_STRING_SIZE]; GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "url", tmp); if (strlen(tmp)) { @@ -320,7 +86,7 @@ static int download_settings(void *elem, void __attribute__ ((__unused__)) *dat get_field(LIBCFG_PARSER, elem, "retries", &opt->retries); get_field(LIBCFG_PARSER, elem, "timeout", - &opt->timeout); + &opt->low_speed_timeout); return 0; } @@ -338,40 +104,36 @@ void download_print_help(void) DL_DEFAULT_RETRIES, DL_LOWSPEED_TIME); } +static channel_data_t channel_options = { + .source = SOURCE_DOWNLOADER, + .debug = false, + .retries = DL_DEFAULT_RETRIES, + .low_speed_timeout = DL_LOWSPEED_TIME +}; + int start_download(const char *fname, int argc, char *argv[]) { - struct dwl_options options; - unsigned int attempt; - int choice = 0; - RECOVERY_STATUS result; - - memset(&options, 0, sizeof(options)); - - options.retries = DL_DEFAULT_RETRIES; - options.timeout = DL_LOWSPEED_TIME; - options.auth = NULL; - if (fname) { - read_module_settings(fname, "download", download_settings, - &options); + read_module_settings(fname, "download", download_settings, &channel_options); } /* reset to optind=1 to parse download's argument vector */ optind = 1; + int choice = 0; while ((choice = getopt_long(argc, argv, "t:u:r:a:", long_options, NULL)) != -1) { switch (choice) { case 't': - options.timeout = strtoul(optarg, NULL, 10); + channel_options.low_speed_timeout = strtoul(optarg, NULL, 10); break; case 'u': - SETSTRING(options.url, optarg); + SETSTRING(channel_options.url, optarg); break; case 'a': - SETSTRING(options.auth, optarg); + SETSTRING(channel_options.auth, optarg); break; case 'r': - options.retries = strtoul(optarg, NULL, 10); + channel_options.retries = strtoul(optarg, NULL, 10); break; case '?': default: @@ -379,34 +141,21 @@ int start_download(const char *fname, int argc, char *argv[]) } } - result = FAILURE; - - /* - * Maybe we need a different option as retries - * to check if an updated must be retried - */ - for (attempt = 0;; attempt++) { - result = download_from_url(options.url, options.retries, - options.timeout, options.auth); - if (result != FAILURE) { - ipc_message msg; - if (ipc_postupdate(&msg) != 0) { - result = FAILURE; - } else { - result = msg.type == ACK ? result : FAILURE; - } - break; + RECOVERY_STATUS result = download_from_url(&channel_options); + if (result != FAILURE) { + ipc_message msg; + if (ipc_postupdate(&msg) != 0) { + result = FAILURE; + } else { + result = msg.type == ACK ? result : FAILURE; } + } - if (options.retries > 0 && attempt >= options.retries) - break; - - /* - * motivation: slow connection, download_from_url fetched half the - * image, then aborted due to lowspeed_timeout, if we retry immediately - * we would just waste our bandwidth. Useful for A/B images. - */ - sleep(60); + if (channel_options.url != NULL) { + free(channel_options.url); + } + if (channel_options.auth != NULL) { + free(channel_options.auth); } exit(result == SUCCESS ? EXIT_SUCCESS : result);
Instead of the downloader having an own cURL binding implementation, make use of the generic channel_curl. Signed-off-by: Christian Storm <christian.storm@siemens.com> --- Kconfig | 2 +- corelib/downloader.c | 347 +++++++-------------------------------------------- 2 files changed, 49 insertions(+), 300 deletions(-)