Message ID | 20210924134922.2712134-1-sava.jakovljev@teufel.de |
---|---|
State | Accepted |
Headers | show |
Series | [v2] channel_curl: Add maximum download speed limit | expand |
On 24.09.21 15:49, Sava Jakovljev wrote: > * Extend Suricatta and general server with options to set download speed > limit. > * Add 'n' short and 'max-download-speed' long command line option for > setting download speed limit. > * Add 'maximum-download-speed' option in configuration file. > * Document new feature and provide configuration file example. > > Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de> > --- > corelib/channel_curl.c | 9 +++++++++ > corelib/downloader.c | 3 ++- > doc/source/swupdate.rst | 8 ++++++++ > examples/configuration/swupdate.cfg | 8 ++++++-- > include/channel_curl.h | 1 + > suricatta/common.c | 4 ++++ > suricatta/server_general.c | 12 ++++++++++-- > suricatta/server_hawkbit.c | 15 +++++++++++---- > 8 files changed, 51 insertions(+), 9 deletions(-) > > diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c > index 0761811..ff2053d 100644 > --- a/corelib/channel_curl.c > +++ b/corelib/channel_curl.c > @@ -1104,6 +1104,15 @@ channel_op_res_t channel_get_file(channel_t *this, void *data) > goto cleanup_header; > } > > + if (channel_data->max_download_speed && > + curl_easy_setopt(channel_curl->handle, > + CURLOPT_MAX_RECV_SPEED_LARGE, > + channel_data->max_download_speed) != CURLE_OK) { > + ERROR("Set channel download speed limit failed."); > + result = CHANNEL_EINIT; > + goto cleanup_header; > + } > + > download_callback_data_t download_data; > if (channel_enable_download_progress_tracking(channel_curl, > channel_data->url, > diff --git a/corelib/downloader.c b/corelib/downloader.c > index 3d0a0a5..8596694 100644 > --- a/corelib/downloader.c > +++ b/corelib/downloader.c > @@ -105,7 +105,8 @@ static channel_data_t channel_options = { > .debug = false, > .retries = DL_DEFAULT_RETRIES, > .low_speed_timeout = DL_LOWSPEED_TIME, > - .headers_to_send = NULL > + .headers_to_send = NULL, > + .max_download_speed = 0 // Unlimited download speed is default. > }; > > int start_download(const char *fname, int argc, char *argv[]) > diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst > index 5af52f1..a81b87a 100644 > --- a/doc/source/swupdate.rst > +++ b/doc/source/swupdate.rst > @@ -665,6 +665,14 @@ Mandatory arguments are marked with '\*': > | | | value to be sent with every HTTP request | > | | | made. | > +-------------------------+----------+--------------------------------------------+ > +| -n <value> | string | Maximum download speed to be used. | > +| | | Value be specified in kB/s, B/s, MB/s | > +| | | or GB/s. Examples: | > +| | | -n 100k : Set limit to 100 kB/s. | > +| | | -n 500 : Set limit to 500 B/s. | > +| | | -n 2M : Set limit to 1 M/s. | > +| | | -n 1G : Set limit to 1 G/s. | > ++-------------------------+----------+--------------------------------------------+ > > > systemd Integration > diff --git a/examples/configuration/swupdate.cfg b/examples/configuration/swupdate.cfg > index 39a4401..ba36a31 100644 > --- a/examples/configuration/swupdate.cfg > +++ b/examples/configuration/swupdate.cfg > @@ -18,7 +18,7 @@ > # enable sending logs to syslog daemon > # public-key-file : string > # file with public key for > -# image verification > +# image verification > # mtd-blacklist : list integers > # MTD devices where SWUpdate > # must not try to check for UBI filesystem. > @@ -123,7 +123,7 @@ identify : ( > { name = "swCompatibility"; value = "unknown";} > ); > > -# > +# > # suricatta section: setup for backend > # > # Currently, they refer to the Hawkbit agent. > @@ -176,6 +176,9 @@ identify : ( > # Specify server connection timeout. If no connection has been established in this > # period, libcurl will consider connection unsuccessful. > # Default value is determined by underlying libcurl implementation (300s). > +# max-download-speed : string > +# Specify maximum download speed to use. Value can be expressed as > +# B/s, kB/s, M/s, G/s. Example: 512k > > suricatta : > { > @@ -192,6 +195,7 @@ suricatta : > enable = true; > initial-report-resend-period = 30; > connection-timeout = 10; > + max-download-speed = "1M"; > /* > cafile = "/etc/ssl/cafile"; > sslkey = "/etc/ssl/sslkey"; > diff --git a/include/channel_curl.h b/include/channel_curl.h > index 6dabae6..8ecaf59 100644 > --- a/include/channel_curl.h > +++ b/include/channel_curl.h > @@ -74,4 +74,5 @@ typedef struct { > sourcetype source; > struct dict *headers_to_send; > struct dict *received_headers; > + unsigned int max_download_speed; > } channel_data_t; > diff --git a/suricatta/common.c b/suricatta/common.c > index e5a3db2..71aa2df 100644 > --- a/suricatta/common.c > +++ b/suricatta/common.c > @@ -23,6 +23,10 @@ void suricatta_channel_settings(void *elem, channel_data_t *chan) > get_field(LIBCFG_PARSER, elem, "retry", > &chan->retries); > > + GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "max-download-speed", tmp); > + if (strlen(tmp)) > + chan->max_download_speed = (unsigned int)ustrtoull(tmp, 10); > + > GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "retrywait", tmp); > if (strlen(tmp)) > chan->retry_sleep = > diff --git a/suricatta/server_general.c b/suricatta/server_general.c > index d9ad50d..e8c3186 100644 > --- a/suricatta/server_general.c > +++ b/suricatta/server_general.c > @@ -65,6 +65,7 @@ static struct option long_options[] = { > {"retry", required_argument, NULL, 'r'}, > {"retrywait", required_argument, NULL, 'w'}, > {"cache", required_argument, NULL, '2'}, > + {"max-download-speed", required_argument, NULL, 'n'}, > {NULL, 0, NULL, 0}}; > > static unsigned short mandatory_argument_count = 0; > @@ -525,7 +526,9 @@ void server_print_help(void) > "\t -y, --proxy Use proxy. Either give proxy URL, else " > "{http,all}_proxy env is tried.\n" > "\t -a, --custom-http-header <name> <value> Set custom HTTP header, " > - "appended to every HTTP request being sent.", > + "appended to every HTTP request being sent." > + "\t -n, --max-download-speed <limit> Set download speed limit." > + "Example: -n 100k; -n 1M; -n 100; -n 1G", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY); > } > @@ -630,7 +633,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > /* reset to optind=1 to parse suricatta's argument vector */ > optind = 1; > opterr = 0; > - while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", > + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:n", > long_options, NULL)) != -1) { > switch (choice) { > case 'u': > @@ -665,6 +668,11 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > return SERVER_EINIT; > > break; > + case 'n': > + channel_data_defaults.max_download_speed = > + (unsigned int)ustrtoull(optarg, 10); > + break; > + > case '?': > /* Ignore not recognized options, they can be already parsed by the caller */ > default: > diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c > index 9a338d8..f8f560e 100644 > --- a/suricatta/server_hawkbit.c > +++ b/suricatta/server_hawkbit.c > @@ -53,6 +53,7 @@ static struct option long_options[] = { > {"initial-report-resend-period", required_argument, NULL, 'm'}, > {"connection-timeout", required_argument, NULL, 's'}, > {"custom-http-header", required_argument, NULL, 'a'}, > + {"max-download-speed", required_argument, NULL, 'l'}, > {NULL, 0, NULL, 0}}; > > static unsigned short mandatory_argument_count = 0; > @@ -135,7 +136,8 @@ static channel_data_t channel_data_defaults = {.debug = false, > .strictssl = true, > .connection_timeout = 0, > .headers_to_send = NULL, > - .received_headers = NULL > + .received_headers = NULL, > + .max_download_speed = 0 // No download speed limit is default. > }; > > static struct timeval server_time; > @@ -1611,7 +1613,9 @@ void server_print_help(void) > "sending initial state with '-c' option (default: %ds).\n" > "\t -s, --connection-timeout Set the server connection timeout (default: 300s).\n" > "\t -a, --custom-http-header <name> <value> Set custom HTTP header, " > - "appended to every HTTP request being sent.", > + "appended to every HTTP request being sent.\n" > + "\t -n, --max-download-speed <limit> Set download speed limit.\n" > + "Example: -n 100k; -n 1M; -n 100; -n 1G\n", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY, > INITIAL_STATUS_REPORT_WAIT_DELAY); > @@ -1702,7 +1706,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > /* reset to optind=1 to parse suricatta's argument vector */ > optind = 1; > opterr = 0; > - while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", > + while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:n:", > long_options, NULL)) != -1) { > switch (choice) { > case 't': > @@ -1803,7 +1807,10 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > optarg, > argv[optind++]) < 0) > return SERVER_EINIT; > - > + break; > + case 'n': > + channel_data_defaults.max_download_speed = > + (unsigned int)ustrtoull(optarg, 10); > break; > /* Ignore not recognized options, they can be already parsed by the caller */ > case '?': > -- > 2.31.1 > Reviewed-by: Stefano Babic <sbabic@denx.de> Best regards, Stefano Babic
On 24.09.21 15:49, Sava Jakovljev wrote: > * Extend Suricatta and general server with options to set download speed > limit. > * Add 'n' short and 'max-download-speed' long command line option for > setting download speed limit. > * Add 'maximum-download-speed' option in configuration file. > * Document new feature and provide configuration file example. > > Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de> I supposed it was laready merged, it wasn't. Applied to -master, thanks ! Best regards, Stefano Babic
diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c index 0761811..ff2053d 100644 --- a/corelib/channel_curl.c +++ b/corelib/channel_curl.c @@ -1104,6 +1104,15 @@ channel_op_res_t channel_get_file(channel_t *this, void *data) goto cleanup_header; } + if (channel_data->max_download_speed && + curl_easy_setopt(channel_curl->handle, + CURLOPT_MAX_RECV_SPEED_LARGE, + channel_data->max_download_speed) != CURLE_OK) { + ERROR("Set channel download speed limit failed."); + result = CHANNEL_EINIT; + goto cleanup_header; + } + download_callback_data_t download_data; if (channel_enable_download_progress_tracking(channel_curl, channel_data->url, diff --git a/corelib/downloader.c b/corelib/downloader.c index 3d0a0a5..8596694 100644 --- a/corelib/downloader.c +++ b/corelib/downloader.c @@ -105,7 +105,8 @@ static channel_data_t channel_options = { .debug = false, .retries = DL_DEFAULT_RETRIES, .low_speed_timeout = DL_LOWSPEED_TIME, - .headers_to_send = NULL + .headers_to_send = NULL, + .max_download_speed = 0 // Unlimited download speed is default. }; int start_download(const char *fname, int argc, char *argv[]) diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst index 5af52f1..a81b87a 100644 --- a/doc/source/swupdate.rst +++ b/doc/source/swupdate.rst @@ -665,6 +665,14 @@ Mandatory arguments are marked with '\*': | | | value to be sent with every HTTP request | | | | made. | +-------------------------+----------+--------------------------------------------+ +| -n <value> | string | Maximum download speed to be used. | +| | | Value be specified in kB/s, B/s, MB/s | +| | | or GB/s. Examples: | +| | | -n 100k : Set limit to 100 kB/s. | +| | | -n 500 : Set limit to 500 B/s. | +| | | -n 2M : Set limit to 1 M/s. | +| | | -n 1G : Set limit to 1 G/s. | ++-------------------------+----------+--------------------------------------------+ systemd Integration diff --git a/examples/configuration/swupdate.cfg b/examples/configuration/swupdate.cfg index 39a4401..ba36a31 100644 --- a/examples/configuration/swupdate.cfg +++ b/examples/configuration/swupdate.cfg @@ -18,7 +18,7 @@ # enable sending logs to syslog daemon # public-key-file : string # file with public key for -# image verification +# image verification # mtd-blacklist : list integers # MTD devices where SWUpdate # must not try to check for UBI filesystem. @@ -123,7 +123,7 @@ identify : ( { name = "swCompatibility"; value = "unknown";} ); -# +# # suricatta section: setup for backend # # Currently, they refer to the Hawkbit agent. @@ -176,6 +176,9 @@ identify : ( # Specify server connection timeout. If no connection has been established in this # period, libcurl will consider connection unsuccessful. # Default value is determined by underlying libcurl implementation (300s). +# max-download-speed : string +# Specify maximum download speed to use. Value can be expressed as +# B/s, kB/s, M/s, G/s. Example: 512k suricatta : { @@ -192,6 +195,7 @@ suricatta : enable = true; initial-report-resend-period = 30; connection-timeout = 10; + max-download-speed = "1M"; /* cafile = "/etc/ssl/cafile"; sslkey = "/etc/ssl/sslkey"; diff --git a/include/channel_curl.h b/include/channel_curl.h index 6dabae6..8ecaf59 100644 --- a/include/channel_curl.h +++ b/include/channel_curl.h @@ -74,4 +74,5 @@ typedef struct { sourcetype source; struct dict *headers_to_send; struct dict *received_headers; + unsigned int max_download_speed; } channel_data_t; diff --git a/suricatta/common.c b/suricatta/common.c index e5a3db2..71aa2df 100644 --- a/suricatta/common.c +++ b/suricatta/common.c @@ -23,6 +23,10 @@ void suricatta_channel_settings(void *elem, channel_data_t *chan) get_field(LIBCFG_PARSER, elem, "retry", &chan->retries); + GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "max-download-speed", tmp); + if (strlen(tmp)) + chan->max_download_speed = (unsigned int)ustrtoull(tmp, 10); + GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "retrywait", tmp); if (strlen(tmp)) chan->retry_sleep = diff --git a/suricatta/server_general.c b/suricatta/server_general.c index d9ad50d..e8c3186 100644 --- a/suricatta/server_general.c +++ b/suricatta/server_general.c @@ -65,6 +65,7 @@ static struct option long_options[] = { {"retry", required_argument, NULL, 'r'}, {"retrywait", required_argument, NULL, 'w'}, {"cache", required_argument, NULL, '2'}, + {"max-download-speed", required_argument, NULL, 'n'}, {NULL, 0, NULL, 0}}; static unsigned short mandatory_argument_count = 0; @@ -525,7 +526,9 @@ void server_print_help(void) "\t -y, --proxy Use proxy. Either give proxy URL, else " "{http,all}_proxy env is tried.\n" "\t -a, --custom-http-header <name> <value> Set custom HTTP header, " - "appended to every HTTP request being sent.", + "appended to every HTTP request being sent." + "\t -n, --max-download-speed <limit> Set download speed limit." + "Example: -n 100k; -n 1M; -n 100; -n 1G", CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, CHANNEL_DEFAULT_RESUME_DELAY); } @@ -630,7 +633,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) /* reset to optind=1 to parse suricatta's argument vector */ optind = 1; opterr = 0; - while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:n", long_options, NULL)) != -1) { switch (choice) { case 'u': @@ -665,6 +668,11 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) return SERVER_EINIT; break; + case 'n': + channel_data_defaults.max_download_speed = + (unsigned int)ustrtoull(optarg, 10); + break; + case '?': /* Ignore not recognized options, they can be already parsed by the caller */ default: diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c index 9a338d8..f8f560e 100644 --- a/suricatta/server_hawkbit.c +++ b/suricatta/server_hawkbit.c @@ -53,6 +53,7 @@ static struct option long_options[] = { {"initial-report-resend-period", required_argument, NULL, 'm'}, {"connection-timeout", required_argument, NULL, 's'}, {"custom-http-header", required_argument, NULL, 'a'}, + {"max-download-speed", required_argument, NULL, 'l'}, {NULL, 0, NULL, 0}}; static unsigned short mandatory_argument_count = 0; @@ -135,7 +136,8 @@ static channel_data_t channel_data_defaults = {.debug = false, .strictssl = true, .connection_timeout = 0, .headers_to_send = NULL, - .received_headers = NULL + .received_headers = NULL, + .max_download_speed = 0 // No download speed limit is default. }; static struct timeval server_time; @@ -1611,7 +1613,9 @@ void server_print_help(void) "sending initial state with '-c' option (default: %ds).\n" "\t -s, --connection-timeout Set the server connection timeout (default: 300s).\n" "\t -a, --custom-http-header <name> <value> Set custom HTTP header, " - "appended to every HTTP request being sent.", + "appended to every HTTP request being sent.\n" + "\t -n, --max-download-speed <limit> Set download speed limit.\n" + "Example: -n 100k; -n 1M; -n 100; -n 1G\n", CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, CHANNEL_DEFAULT_RESUME_DELAY, INITIAL_STATUS_REPORT_WAIT_DELAY); @@ -1702,7 +1706,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) /* reset to optind=1 to parse suricatta's argument vector */ optind = 1; opterr = 0; - while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", + while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:n:", long_options, NULL)) != -1) { switch (choice) { case 't': @@ -1803,7 +1807,10 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) optarg, argv[optind++]) < 0) return SERVER_EINIT; - + break; + case 'n': + channel_data_defaults.max_download_speed = + (unsigned int)ustrtoull(optarg, 10); break; /* Ignore not recognized options, they can be already parsed by the caller */ case '?':
* Extend Suricatta and general server with options to set download speed limit. * Add 'n' short and 'max-download-speed' long command line option for setting download speed limit. * Add 'maximum-download-speed' option in configuration file. * Document new feature and provide configuration file example. Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de> --- corelib/channel_curl.c | 9 +++++++++ corelib/downloader.c | 3 ++- doc/source/swupdate.rst | 8 ++++++++ examples/configuration/swupdate.cfg | 8 ++++++-- include/channel_curl.h | 1 + suricatta/common.c | 4 ++++ suricatta/server_general.c | 12 ++++++++++-- suricatta/server_hawkbit.c | 15 +++++++++++---- 8 files changed, 51 insertions(+), 9 deletions(-) -- 2.31.1