Message ID | 20210909133428.338445-1-sava.jakovljev@teufel.de |
---|---|
State | Changes Requested |
Headers | show |
Series | [v4] channel_curl: Add ability to define a set of custom HTTP headers | expand |
Hi Stefano, v4 fixed indentation in documentation sources. Everything else is same as in v3, where the leak is fixed. Best regards, Sava On Thursday, September 9, 2021 at 3:35:00 PM UTC+2 Sava Jakovljev wrote: > * Expand Suricatta/Hawkbit client with ability to define a custom set of > HTTP requests, defined through command line or configuration file, > using 'a' short option or "custom-http-header" long option. > > Signed-off-by: Sava Jakovljev <sava.ja...@teufel.de> > --- > corelib/channel_curl.c | 8 +++++--- > corelib/downloader.c | 3 ++- > doc/source/swupdate.rst | 8 ++++++-- > include/channel_curl.h | 3 ++- > suricatta/server_general.c | 33 +++++++++++++++++++++++++++------ > suricatta/server_general.h | 3 ++- > suricatta/server_hawkbit.c | 27 ++++++++++++++++++++++++--- > suricatta/server_hawkbit.h | 1 + > 8 files changed, 69 insertions(+), 17 deletions(-) > > diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c > index e910f76..bc387d0 100644 > --- a/corelib/channel_curl.c > +++ b/corelib/channel_curl.c > @@ -585,7 +585,7 @@ channel_op_res_t channel_set_options(channel_t *this, > channel_data_t *channel_da > goto cleanup; > } > > - if (channel_data->headers) { > + if (channel_data->received_headers) { > /* > * Setup supply request and receive reply HTTP headers. > * A LIST_INIT()'d dictionary is expected at channel_data->headers. > @@ -596,14 +596,16 @@ channel_op_res_t channel_set_options(channel_t > *this, channel_data_t *channel_da > CURLOPT_HEADERFUNCTION, > channel_callback_headers) != CURLE_OK) || > (curl_easy_setopt(channel_curl->handle, CURLOPT_HEADERDATA, > - channel_data->headers) != CURLE_OK)) { > + channel_data->received_headers) != CURLE_OK)) { > result = CHANNEL_EINIT; > goto cleanup; > } > + } > > + if (channel_data->headers_to_send) { > struct dict_entry *entry; > char *header; > - LIST_FOREACH(entry, channel_data->headers, next) > + LIST_FOREACH(entry, channel_data->headers_to_send, next) > { > if (ENOMEM_ASPRINTF == > asprintf(&header, "%s: %s", > diff --git a/corelib/downloader.c b/corelib/downloader.c > index 437b36d..3d0a0a5 100644 > --- a/corelib/downloader.c > +++ b/corelib/downloader.c > @@ -104,7 +104,8 @@ static channel_data_t channel_options = { > .source = SOURCE_DOWNLOADER, > .debug = false, > .retries = DL_DEFAULT_RETRIES, > - .low_speed_timeout = DL_LOWSPEED_TIME > + .low_speed_timeout = DL_LOWSPEED_TIME, > + .headers_to_send = NULL > }; > > int start_download(const char *fname, int argc, char *argv[]) > diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst > index 317c54d..5b0c150 100644 > --- a/doc/source/swupdate.rst > +++ b/doc/source/swupdate.rst > @@ -184,7 +184,7 @@ Images fully streamed > --------------------- > > In case of remote update, SWUpdate extracts relevant images from the stream > -and copies them into the directory pointed to by the environment variable > +and copies them into the directory pointed to by the environment variable > ``TMPDIR`` (if unset, to ``/tmp``) before calling the handlers. > This guarantee that an update is initiated only if all parts are present > and > correct. However, on some systems with less resources, the amount of RAM > @@ -652,6 +652,10 @@ Mandatory arguments are marked with '\*': > | | | during this period - adapt this value to | > | | | your use case! | > > +-------------------------+----------+--------------------------------------------+ > +| -a <name> <value> | strings | Custom HTTP header with given name and | > +| | | value to be sent with every HTTP request | > +| | | made. | > > ++-------------------------+----------+--------------------------------------------+ > > > systemd Integration > @@ -706,7 +710,7 @@ files are also handed over on a "regular" start of > SWUpdate via > ``systemctl start swupdate.service``. > > Note that the socket paths in the two ``ListenStream=`` directives > -have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > +have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > ``CONFIG_SOCKET_PROGRESS_PATH`` in SWUpdate's configuration. > Here, the default socket path configuration is depicted. > > diff --git a/include/channel_curl.h b/include/channel_curl.h > index 4de098e..6dabae6 100644 > --- a/include/channel_curl.h > +++ b/include/channel_curl.h > @@ -72,5 +72,6 @@ typedef struct { > struct swupdate_digest *dgst; > char sha1hash[SWUPDATE_SHA_DIGEST_LENGTH * 2 + 1]; > sourcetype source; > - struct dict *headers; > + struct dict *headers_to_send; > + struct dict *received_headers; > } channel_data_t; > diff --git a/suricatta/server_general.c b/suricatta/server_general.c > index 1d11ada..146f02c 100644 > --- a/suricatta/server_general.c > +++ b/suricatta/server_general.c > @@ -453,8 +453,9 @@ static server_op_res_t > server_get_deployment_info(channel_t *channel, channel_da > */ > channel_data->url= server_prepare_query(server_general.url, > &server_general.configdata); > > - LIST_INIT(&server_general.httpheaders); > - channel_data->headers = &server_general.httpheaders; > + LIST_INIT(&server_general.received_httpheaders); > + LIST_INIT(&server_general.httpheaders_to_send); > + channel_data->received_headers = &server_general.received_httpheaders; > > result = map_http_retcode(channel->get(channel, (void *)channel_data)); > > @@ -462,12 +463,12 @@ static server_op_res_t > server_get_deployment_info(channel_t *channel, channel_da > free(channel_data->url); > } > > - pollstring = dict_get_value(&server_general.httpheaders, "Retry-After"); > + pollstring = dict_get_value(&server_general.received_httpheaders, > "Retry-After"); > if (pollstring) { > server_set_polling_interval(pollstring); > } > > - dict_drop_db(&server_general.httpheaders); > + dict_drop_db(&server_general.received_httpheaders); > > return result; > } > @@ -522,7 +523,9 @@ void server_print_help(void) > "\t -w, --retrywait Time to wait prior to retry and " > "resume a download (default: %ds).\n" > "\t -y, --proxy Use proxy. Either give proxy URL, else " > - "{http,all}_proxy env is tried.\n", > + "{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.", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY); > } > @@ -608,6 +611,7 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > int choice = 0; > > LIST_INIT(&server_general.configdata); > + LIST_INIT(&server_general.httpheaders_to_send); > > if (fname) { > swupdate_cfg_handle handle; > @@ -626,7 +630,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:", > + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", > long_options, NULL)) != -1) { > switch (choice) { > case 'u': > @@ -652,6 +656,21 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > SETSTRING(server_general.cached_file, optarg); > break; > /* Ignore not recognized options, they can be already parsed by the caller > */ > + case 'a': > + if (optind >= argc) > + return SERVER_EINIT; > + > + char *name = NULL; > + SETSTRING(name, optarg); > + char *value = NULL; > + SETSTRING(value, argv[optind++]); > + > + if (dict_insert_value(&server_general.httpheaders_to_send, > + name, > + value) < 0) > + return SERVER_EINIT; > + > + break; > case '?': > default: > break; > @@ -664,6 +683,8 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > return SERVER_EINIT; > } > > + channel_data_defaults.headers_to_send = > &server_general.httpheaders_to_send; > + > if (channel_curl_init() != CHANNEL_OK) > return SERVER_EINIT; > > diff --git a/suricatta/server_general.h b/suricatta/server_general.h > index 69345a1..d5d8d48 100644 > --- a/suricatta/server_general.h > +++ b/suricatta/server_general.h > @@ -23,7 +23,8 @@ typedef struct { > bool debug; > char *cached_file; > struct dict configdata; > - struct dict httpheaders; > + struct dict received_httpheaders; > + struct dict httpheaders_to_send; > update_state_t update_state; > channel_t *channel; > } server_general_t; > diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c > index 33d2eec..daa00f0 100644 > --- a/suricatta/server_hawkbit.c > +++ b/suricatta/server_hawkbit.c > @@ -52,6 +52,7 @@ static struct option long_options[] = { > {"cache", required_argument, NULL, '2'}, > {"initial-report-resend-period", required_argument, NULL, 'm'}, > {"connection-timeout", required_argument, NULL, 's'}, > + {"custom-http-header", required_argument, NULL, 'a'}, > {NULL, 0, NULL, 0}}; > > static unsigned short mandatory_argument_count = 0; > @@ -132,7 +133,9 @@ static channel_data_t channel_data_defaults = {.debug > = false, > .nocheckanswer = false, > .nofollow = false, > .strictssl = true, > - .connection_timeout = 0 > + .connection_timeout = 0, > + .headers_to_send = NULL, > + .received_headers = NULL > }; > > static struct timeval server_time; > @@ -1602,7 +1605,9 @@ void server_print_help(void) > "\t --cache <file> Use cache file as starting SWU\n" > "\t -m, --initial-report-resend-period <seconds> Time to wait prior to > retry " > "sending initial state with '-c' option (default: %ds).\n" > - "\t -s, --connection-timeout Set the server connection timeout (default: > 300s).\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.", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY, > INITIAL_STATUS_REPORT_WAIT_DELAY); > @@ -1661,6 +1666,7 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > mandatory_argument_count = 0; > > LIST_INIT(&server_hawkbit.configdata); > + LIST_INIT(&server_hawkbit.httpheaders); > > server_hawkbit.initial_report_resend_period = > INITIAL_STATUS_REPORT_WAIT_DELAY; > if (fname) { > @@ -1677,6 +1683,9 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > */ > read_module_settings(&handle, "hawkbit", server_hawkbit_settings, NULL); > read_module_settings(&handle, "identify", settings_into_dict, > &server_hawkbit.configdata); > + > + read_module_settings(&handle, "custom-http-headers", > + settings_into_dict, &server_hawkbit.httpheaders); > } > swupdate_cfg_destroy(&handle); > } > @@ -1689,7 +1698,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:", > + while ((choice = getopt_long(argc, argv, > "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", > long_options, NULL)) != -1) { > switch (choice) { > case 't': > @@ -1782,6 +1791,16 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > channel_data_defaults.connection_timeout = > (unsigned int)strtoul(optarg, NULL, 10); > break; > + case 'a': > + if (optind >= argc) > + return SERVER_EINIT; > + > + if (dict_insert_value(&server_hawkbit.httpheaders, > + optarg, > + argv[optind++]) < 0) > + return SERVER_EINIT; > + > + break; > /* Ignore not recognized options, they can be already parsed by the caller > */ > case '?': > break; > @@ -1799,6 +1818,8 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > return SERVER_EINIT; > } > > + channel_data_defaults.headers_to_send = &server_hawkbit.httpheaders; > + > if (channel_curl_init() != CHANNEL_OK) > return SERVER_EINIT; > > diff --git a/suricatta/server_hawkbit.h b/suricatta/server_hawkbit.h > index aea4bb0..67f1c31 100644 > --- a/suricatta/server_hawkbit.h > +++ b/suricatta/server_hawkbit.h > @@ -29,6 +29,7 @@ typedef struct { > bool polling_interval_from_server; > bool debug; > struct dict configdata; > + struct dict httpheaders; > bool has_to_send_configData; > char *configData_url; > char *cancel_url; >
Hi Sava, On 09.09.21 15:34, Sava Jakovljev wrote: > * Expand Suricatta/Hawkbit client with ability to define a custom set of > HTTP requests, defined through command line or configuration file, > using 'a' short option or "custom-http-header" long option. > ...but I do not see that the leak is fixed, in fact: > Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de> > --- > corelib/channel_curl.c | 8 +++++--- > corelib/downloader.c | 3 ++- > doc/source/swupdate.rst | 8 ++++++-- > include/channel_curl.h | 3 ++- > suricatta/server_general.c | 33 +++++++++++++++++++++++++++------ > suricatta/server_general.h | 3 ++- > suricatta/server_hawkbit.c | 27 ++++++++++++++++++++++++--- > suricatta/server_hawkbit.h | 1 + > 8 files changed, 69 insertions(+), 17 deletions(-) > > diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c > index e910f76..bc387d0 100644 > --- a/corelib/channel_curl.c > +++ b/corelib/channel_curl.c > @@ -585,7 +585,7 @@ channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da > goto cleanup; > } > > - if (channel_data->headers) { > + if (channel_data->received_headers) { > /* > * Setup supply request and receive reply HTTP headers. > * A LIST_INIT()'d dictionary is expected at channel_data->headers. > @@ -596,14 +596,16 @@ channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da > CURLOPT_HEADERFUNCTION, > channel_callback_headers) != CURLE_OK) || > (curl_easy_setopt(channel_curl->handle, CURLOPT_HEADERDATA, > - channel_data->headers) != CURLE_OK)) { > + channel_data->received_headers) != CURLE_OK)) { > result = CHANNEL_EINIT; > goto cleanup; > } > + } > > + if (channel_data->headers_to_send) { > struct dict_entry *entry; > char *header; > - LIST_FOREACH(entry, channel_data->headers, next) > + LIST_FOREACH(entry, channel_data->headers_to_send, next) > { > if (ENOMEM_ASPRINTF == > asprintf(&header, "%s: %s", > diff --git a/corelib/downloader.c b/corelib/downloader.c > index 437b36d..3d0a0a5 100644 > --- a/corelib/downloader.c > +++ b/corelib/downloader.c > @@ -104,7 +104,8 @@ static channel_data_t channel_options = { > .source = SOURCE_DOWNLOADER, > .debug = false, > .retries = DL_DEFAULT_RETRIES, > - .low_speed_timeout = DL_LOWSPEED_TIME > + .low_speed_timeout = DL_LOWSPEED_TIME, > + .headers_to_send = NULL > }; > > int start_download(const char *fname, int argc, char *argv[]) > diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst > index 317c54d..5b0c150 100644 > --- a/doc/source/swupdate.rst > +++ b/doc/source/swupdate.rst > @@ -184,7 +184,7 @@ Images fully streamed > --------------------- > > In case of remote update, SWUpdate extracts relevant images from the stream > -and copies them into the directory pointed to by the environment variable > +and copies them into the directory pointed to by the environment variable > ``TMPDIR`` (if unset, to ``/tmp``) before calling the handlers. > This guarantee that an update is initiated only if all parts are present and > correct. However, on some systems with less resources, the amount of RAM > @@ -652,6 +652,10 @@ Mandatory arguments are marked with '\*': > | | | during this period - adapt this value to | > | | | your use case! | > +-------------------------+----------+--------------------------------------------+ > +| -a <name> <value> | strings | Custom HTTP header with given name and | > +| | | value to be sent with every HTTP request | > +| | | made. | > ++-------------------------+----------+--------------------------------------------+ > > > systemd Integration > @@ -706,7 +710,7 @@ files are also handed over on a "regular" start of SWUpdate via > ``systemctl start swupdate.service``. > > Note that the socket paths in the two ``ListenStream=`` directives > -have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > +have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > ``CONFIG_SOCKET_PROGRESS_PATH`` in SWUpdate's configuration. > Here, the default socket path configuration is depicted. > > diff --git a/include/channel_curl.h b/include/channel_curl.h > index 4de098e..6dabae6 100644 > --- a/include/channel_curl.h > +++ b/include/channel_curl.h > @@ -72,5 +72,6 @@ typedef struct { > struct swupdate_digest *dgst; > char sha1hash[SWUPDATE_SHA_DIGEST_LENGTH * 2 + 1]; > sourcetype source; > - struct dict *headers; > + struct dict *headers_to_send; > + struct dict *received_headers; > } channel_data_t; > diff --git a/suricatta/server_general.c b/suricatta/server_general.c > index 1d11ada..146f02c 100644 > --- a/suricatta/server_general.c > +++ b/suricatta/server_general.c > @@ -453,8 +453,9 @@ static server_op_res_t server_get_deployment_info(channel_t *channel, channel_da > */ > channel_data->url= server_prepare_query(server_general.url, &server_general.configdata); > > - LIST_INIT(&server_general.httpheaders); > - channel_data->headers = &server_general.httpheaders; > + LIST_INIT(&server_general.received_httpheaders); > + LIST_INIT(&server_general.httpheaders_to_send); > + channel_data->received_headers = &server_general.received_httpheaders; > > result = map_http_retcode(channel->get(channel, (void *)channel_data)); > > @@ -462,12 +463,12 @@ static server_op_res_t server_get_deployment_info(channel_t *channel, channel_da > free(channel_data->url); > } > > - pollstring = dict_get_value(&server_general.httpheaders, "Retry-After"); > + pollstring = dict_get_value(&server_general.received_httpheaders, "Retry-After"); > if (pollstring) { > server_set_polling_interval(pollstring); > } > > - dict_drop_db(&server_general.httpheaders); > + dict_drop_db(&server_general.received_httpheaders); > > return result; > } > @@ -522,7 +523,9 @@ void server_print_help(void) > "\t -w, --retrywait Time to wait prior to retry and " > "resume a download (default: %ds).\n" > "\t -y, --proxy Use proxy. Either give proxy URL, else " > - "{http,all}_proxy env is tried.\n", > + "{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.", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY); > } > @@ -608,6 +611,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > int choice = 0; > > LIST_INIT(&server_general.configdata); > + LIST_INIT(&server_general.httpheaders_to_send); > > if (fname) { > swupdate_cfg_handle handle; > @@ -626,7 +630,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:", > + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", > long_options, NULL)) != -1) { > switch (choice) { > case 'u': > @@ -652,6 +656,21 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > SETSTRING(server_general.cached_file, optarg); > break; > /* Ignore not recognized options, they can be already parsed by the caller */ > + case 'a': > + if (optind >= argc) > + return SERVER_EINIT; > + > + char *name = NULL; the pointer is declared here and the scope is in this case: > + SETSTRING(name, optarg); SETSTRING allocates memory and set name > + char *value = NULL; > + SETSTRING(value, argv[optind++]); Same thing for value > + > + if (dict_insert_value(&server_general.httpheaders_to_send, > + name, > + value) < 0) both are added to the list, but the list reallocates key/value on its own. > + return SERVER_EINIT; > + > + break; End of scope, memory leak... > case '?': > default: > break; > @@ -664,6 +683,8 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > return SERVER_EINIT; > } > > + channel_data_defaults.headers_to_send = &server_general.httpheaders_to_send; > + > if (channel_curl_init() != CHANNEL_OK) > return SERVER_EINIT; > > diff --git a/suricatta/server_general.h b/suricatta/server_general.h > index 69345a1..d5d8d48 100644 > --- a/suricatta/server_general.h > +++ b/suricatta/server_general.h > @@ -23,7 +23,8 @@ typedef struct { > bool debug; > char *cached_file; > struct dict configdata; > - struct dict httpheaders; > + struct dict received_httpheaders; > + struct dict httpheaders_to_send; > update_state_t update_state; > channel_t *channel; > } server_general_t; > diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c > index 33d2eec..daa00f0 100644 > --- a/suricatta/server_hawkbit.c > +++ b/suricatta/server_hawkbit.c > @@ -52,6 +52,7 @@ static struct option long_options[] = { > {"cache", required_argument, NULL, '2'}, > {"initial-report-resend-period", required_argument, NULL, 'm'}, > {"connection-timeout", required_argument, NULL, 's'}, > + {"custom-http-header", required_argument, NULL, 'a'}, > {NULL, 0, NULL, 0}}; > > static unsigned short mandatory_argument_count = 0; > @@ -132,7 +133,9 @@ static channel_data_t channel_data_defaults = {.debug = false, > .nocheckanswer = false, > .nofollow = false, > .strictssl = true, > - .connection_timeout = 0 > + .connection_timeout = 0, > + .headers_to_send = NULL, > + .received_headers = NULL > }; > > static struct timeval server_time; > @@ -1602,7 +1605,9 @@ void server_print_help(void) > "\t --cache <file> Use cache file as starting SWU\n" > "\t -m, --initial-report-resend-period <seconds> Time to wait prior to retry " > "sending initial state with '-c' option (default: %ds).\n" > - "\t -s, --connection-timeout Set the server connection timeout (default: 300s).\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.", > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > CHANNEL_DEFAULT_RESUME_DELAY, > INITIAL_STATUS_REPORT_WAIT_DELAY); > @@ -1661,6 +1666,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > mandatory_argument_count = 0; > > LIST_INIT(&server_hawkbit.configdata); > + LIST_INIT(&server_hawkbit.httpheaders); > > server_hawkbit.initial_report_resend_period = INITIAL_STATUS_REPORT_WAIT_DELAY; > if (fname) { > @@ -1677,6 +1683,9 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > */ > read_module_settings(&handle, "hawkbit", server_hawkbit_settings, NULL); > read_module_settings(&handle, "identify", settings_into_dict, &server_hawkbit.configdata); > + > + read_module_settings(&handle, "custom-http-headers", > + settings_into_dict, &server_hawkbit.httpheaders); > } > swupdate_cfg_destroy(&handle); > } > @@ -1689,7 +1698,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:", > + while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", > long_options, NULL)) != -1) { > switch (choice) { > case 't': > @@ -1782,6 +1791,16 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > channel_data_defaults.connection_timeout = > (unsigned int)strtoul(optarg, NULL, 10); > break; > + case 'a': > + if (optind >= argc) > + return SERVER_EINIT; > + > + if (dict_insert_value(&server_hawkbit.httpheaders, > + optarg, > + argv[optind++]) < 0) > + return SERVER_EINIT; > + > + break; > /* Ignore not recognized options, they can be already parsed by the caller */ > case '?': > break; > @@ -1799,6 +1818,8 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) > return SERVER_EINIT; > } > > + channel_data_defaults.headers_to_send = &server_hawkbit.httpheaders; > + > if (channel_curl_init() != CHANNEL_OK) > return SERVER_EINIT; > > diff --git a/suricatta/server_hawkbit.h b/suricatta/server_hawkbit.h > index aea4bb0..67f1c31 100644 > --- a/suricatta/server_hawkbit.h > +++ b/suricatta/server_hawkbit.h > @@ -29,6 +29,7 @@ typedef struct { > bool polling_interval_from_server; > bool debug; > struct dict configdata; > + struct dict httpheaders; > bool has_to_send_configData; > char *configData_url; > char *cancel_url; > Best regards, Stefano Babic
Hm interesting. I managed to send a wrong patch file - I don't know how it came to the point where my changes were only partially applied. Sorry for this. v5 coming soon... Sava On Thursday, September 9, 2021 at 3:40:25 PM UTC+2 Stefano Babic wrote: > Hi Sava, > > On 09.09.21 15:34, Sava Jakovljev wrote: > > * Expand Suricatta/Hawkbit client with ability to define a custom set of > > HTTP requests, defined through command line or configuration file, > > using 'a' short option or "custom-http-header" long option. > > > > ...but I do not see that the leak is fixed, in fact: > > > Signed-off-by: Sava Jakovljev <sava.ja...@teufel.de> > > --- > > corelib/channel_curl.c | 8 +++++--- > > corelib/downloader.c | 3 ++- > > doc/source/swupdate.rst | 8 ++++++-- > > include/channel_curl.h | 3 ++- > > suricatta/server_general.c | 33 +++++++++++++++++++++++++++------ > > suricatta/server_general.h | 3 ++- > > suricatta/server_hawkbit.c | 27 ++++++++++++++++++++++++--- > > suricatta/server_hawkbit.h | 1 + > > 8 files changed, 69 insertions(+), 17 deletions(-) > > > > diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c > > index e910f76..bc387d0 100644 > > --- a/corelib/channel_curl.c > > +++ b/corelib/channel_curl.c > > @@ -585,7 +585,7 @@ channel_op_res_t channel_set_options(channel_t > *this, channel_data_t *channel_da > > goto cleanup; > > } > > > > - if (channel_data->headers) { > > + if (channel_data->received_headers) { > > /* > > * Setup supply request and receive reply HTTP headers. > > * A LIST_INIT()'d dictionary is expected at channel_data->headers. > > @@ -596,14 +596,16 @@ channel_op_res_t channel_set_options(channel_t > *this, channel_data_t *channel_da > > CURLOPT_HEADERFUNCTION, > > channel_callback_headers) != CURLE_OK) || > > (curl_easy_setopt(channel_curl->handle, CURLOPT_HEADERDATA, > > - channel_data->headers) != CURLE_OK)) { > > + channel_data->received_headers) != CURLE_OK)) { > > result = CHANNEL_EINIT; > > goto cleanup; > > } > > + } > > > > + if (channel_data->headers_to_send) { > > struct dict_entry *entry; > > char *header; > > - LIST_FOREACH(entry, channel_data->headers, next) > > + LIST_FOREACH(entry, channel_data->headers_to_send, next) > > { > > if (ENOMEM_ASPRINTF == > > asprintf(&header, "%s: %s", > > diff --git a/corelib/downloader.c b/corelib/downloader.c > > index 437b36d..3d0a0a5 100644 > > --- a/corelib/downloader.c > > +++ b/corelib/downloader.c > > @@ -104,7 +104,8 @@ static channel_data_t channel_options = { > > .source = SOURCE_DOWNLOADER, > > .debug = false, > > .retries = DL_DEFAULT_RETRIES, > > - .low_speed_timeout = DL_LOWSPEED_TIME > > + .low_speed_timeout = DL_LOWSPEED_TIME, > > + .headers_to_send = NULL > > }; > > > > int start_download(const char *fname, int argc, char *argv[]) > > diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst > > index 317c54d..5b0c150 100644 > > --- a/doc/source/swupdate.rst > > +++ b/doc/source/swupdate.rst > > @@ -184,7 +184,7 @@ Images fully streamed > > --------------------- > > > > In case of remote update, SWUpdate extracts relevant images from the > stream > > -and copies them into the directory pointed to by the environment > variable > > +and copies them into the directory pointed to by the environment > variable > > ``TMPDIR`` (if unset, to ``/tmp``) before calling the handlers. > > This guarantee that an update is initiated only if all parts are present > and > > correct. However, on some systems with less resources, the amount of RAM > > @@ -652,6 +652,10 @@ Mandatory arguments are marked with '\*': > > | | | during this period - adapt this value to | > > | | | your use case! | > > > +-------------------------+----------+--------------------------------------------+ > > +| -a <name> <value> | strings | Custom HTTP header with given name and | > > +| | | value to be sent with every HTTP request | > > +| | | made. | > > > ++-------------------------+----------+--------------------------------------------+ > > > > > > systemd Integration > > @@ -706,7 +710,7 @@ files are also handed over on a "regular" start of > SWUpdate via > > ``systemctl start swupdate.service``. > > > > Note that the socket paths in the two ``ListenStream=`` directives > > -have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > > +have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and > > ``CONFIG_SOCKET_PROGRESS_PATH`` in SWUpdate's configuration. > > Here, the default socket path configuration is depicted. > > > > diff --git a/include/channel_curl.h b/include/channel_curl.h > > index 4de098e..6dabae6 100644 > > --- a/include/channel_curl.h > > +++ b/include/channel_curl.h > > @@ -72,5 +72,6 @@ typedef struct { > > struct swupdate_digest *dgst; > > char sha1hash[SWUPDATE_SHA_DIGEST_LENGTH * 2 + 1]; > > sourcetype source; > > - struct dict *headers; > > + struct dict *headers_to_send; > > + struct dict *received_headers; > > } channel_data_t; > > diff --git a/suricatta/server_general.c b/suricatta/server_general.c > > index 1d11ada..146f02c 100644 > > --- a/suricatta/server_general.c > > +++ b/suricatta/server_general.c > > @@ -453,8 +453,9 @@ static server_op_res_t > server_get_deployment_info(channel_t *channel, channel_da > > */ > > channel_data->url= server_prepare_query(server_general.url, > &server_general.configdata); > > > > - LIST_INIT(&server_general.httpheaders); > > - channel_data->headers = &server_general.httpheaders; > > + LIST_INIT(&server_general.received_httpheaders); > > + LIST_INIT(&server_general.httpheaders_to_send); > > + channel_data->received_headers = &server_general.received_httpheaders; > > > > result = map_http_retcode(channel->get(channel, (void *)channel_data)); > > > > @@ -462,12 +463,12 @@ static server_op_res_t > server_get_deployment_info(channel_t *channel, channel_da > > free(channel_data->url); > > } > > > > - pollstring = dict_get_value(&server_general.httpheaders, > "Retry-After"); > > + pollstring = dict_get_value(&server_general.received_httpheaders, > "Retry-After"); > > if (pollstring) { > > server_set_polling_interval(pollstring); > > } > > > > - dict_drop_db(&server_general.httpheaders); > > + dict_drop_db(&server_general.received_httpheaders); > > > > return result; > > } > > @@ -522,7 +523,9 @@ void server_print_help(void) > > "\t -w, --retrywait Time to wait prior to retry and " > > "resume a download (default: %ds).\n" > > "\t -y, --proxy Use proxy. Either give proxy URL, else " > > - "{http,all}_proxy env is tried.\n", > > + "{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.", > > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > > CHANNEL_DEFAULT_RESUME_DELAY); > > } > > @@ -608,6 +611,7 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > > int choice = 0; > > > > LIST_INIT(&server_general.configdata); > > + LIST_INIT(&server_general.httpheaders_to_send); > > > > if (fname) { > > swupdate_cfg_handle handle; > > @@ -626,7 +630,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:", > > + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", > > long_options, NULL)) != -1) { > > switch (choice) { > > case 'u': > > @@ -652,6 +656,21 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > > SETSTRING(server_general.cached_file, optarg); > > break; > > /* Ignore not recognized options, they can be already parsed by the > caller */ > > + case 'a': > > + if (optind >= argc) > > + return SERVER_EINIT; > > + > > + char *name = NULL; > > the pointer is declared here and the scope is in this case: > > > + SETSTRING(name, optarg); > > SETSTRING allocates memory and set name > > > + char *value = NULL; > > + SETSTRING(value, argv[optind++]); > > Same thing for value > > > + > > + if (dict_insert_value(&server_general.httpheaders_to_send, > > + name, > > + value) < 0) > > both are added to the list, but the list reallocates key/value on its own. > > > > + return SERVER_EINIT; > > + > > + break; > > End of scope, memory leak... > > > case '?': > > default: > > break; > > @@ -664,6 +683,8 @@ server_op_res_t server_start(char *fname, int argc, > char *argv[]) > > return SERVER_EINIT; > > } > > > > + channel_data_defaults.headers_to_send = > &server_general.httpheaders_to_send; > > + > > if (channel_curl_init() != CHANNEL_OK) > > return SERVER_EINIT; > > > > diff --git a/suricatta/server_general.h b/suricatta/server_general.h > > index 69345a1..d5d8d48 100644 > > --- a/suricatta/server_general.h > > +++ b/suricatta/server_general.h > > @@ -23,7 +23,8 @@ typedef struct { > > bool debug; > > char *cached_file; > > struct dict configdata; > > - struct dict httpheaders; > > + struct dict received_httpheaders; > > + struct dict httpheaders_to_send; > > update_state_t update_state; > > channel_t *channel; > > } server_general_t; > > diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c > > index 33d2eec..daa00f0 100644 > > --- a/suricatta/server_hawkbit.c > > +++ b/suricatta/server_hawkbit.c > > @@ -52,6 +52,7 @@ static struct option long_options[] = { > > {"cache", required_argument, NULL, '2'}, > > {"initial-report-resend-period", required_argument, NULL, 'm'}, > > {"connection-timeout", required_argument, NULL, 's'}, > > + {"custom-http-header", required_argument, NULL, 'a'}, > > {NULL, 0, NULL, 0}}; > > > > static unsigned short mandatory_argument_count = 0; > > @@ -132,7 +133,9 @@ static channel_data_t channel_data_defaults = > {.debug = false, > > .nocheckanswer = false, > > .nofollow = false, > > .strictssl = true, > > - .connection_timeout = 0 > > + .connection_timeout = 0, > > + .headers_to_send = NULL, > > + .received_headers = NULL > > }; > > > > static struct timeval server_time; > > @@ -1602,7 +1605,9 @@ void server_print_help(void) > > "\t --cache <file> Use cache file as starting SWU\n" > > "\t -m, --initial-report-resend-period <seconds> Time to wait prior to > retry " > > "sending initial state with '-c' option (default: %ds).\n" > > - "\t -s, --connection-timeout Set the server connection timeout > (default: 300s).\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.", > > CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, > > CHANNEL_DEFAULT_RESUME_DELAY, > > INITIAL_STATUS_REPORT_WAIT_DELAY); > > @@ -1661,6 +1666,7 @@ server_op_res_t server_start(char *fname, int > argc, char *argv[]) > > mandatory_argument_count = 0; > > > > LIST_INIT(&server_hawkbit.configdata); > > + LIST_INIT(&server_hawkbit.httpheaders); > > > > server_hawkbit.initial_report_resend_period = > INITIAL_STATUS_REPORT_WAIT_DELAY; > > if (fname) { > > @@ -1677,6 +1683,9 @@ server_op_res_t server_start(char *fname, int > argc, char *argv[]) > > */ > > read_module_settings(&handle, "hawkbit", server_hawkbit_settings, NULL); > > read_module_settings(&handle, "identify", settings_into_dict, > &server_hawkbit.configdata); > > + > > + read_module_settings(&handle, "custom-http-headers", > > + settings_into_dict, &server_hawkbit.httpheaders); > > } > > swupdate_cfg_destroy(&handle); > > } > > @@ -1689,7 +1698,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:", > > + while ((choice = getopt_long(argc, argv, > "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", > > long_options, NULL)) != -1) { > > switch (choice) { > > case 't': > > @@ -1782,6 +1791,16 @@ server_op_res_t server_start(char *fname, int > argc, char *argv[]) > > channel_data_defaults.connection_timeout = > > (unsigned int)strtoul(optarg, NULL, 10); > > break; > > + case 'a': > > + if (optind >= argc) > > + return SERVER_EINIT; > > + > > + if (dict_insert_value(&server_hawkbit.httpheaders, > > + optarg, > > + argv[optind++]) < 0) > > + return SERVER_EINIT; > > + > > + break; > > /* Ignore not recognized options, they can be already parsed by the > caller */ > > case '?': > > break; > > @@ -1799,6 +1818,8 @@ server_op_res_t server_start(char *fname, int > argc, char *argv[]) > > return SERVER_EINIT; > > } > > > > + channel_data_defaults.headers_to_send = &server_hawkbit.httpheaders; > > + > > if (channel_curl_init() != CHANNEL_OK) > > return SERVER_EINIT; > > > > diff --git a/suricatta/server_hawkbit.h b/suricatta/server_hawkbit.h > > index aea4bb0..67f1c31 100644 > > --- a/suricatta/server_hawkbit.h > > +++ b/suricatta/server_hawkbit.h > > @@ -29,6 +29,7 @@ typedef struct { > > bool polling_interval_from_server; > > bool debug; > > struct dict configdata; > > + struct dict httpheaders; > > bool has_to_send_configData; > > char *configData_url; > > char *cancel_url; > > > > Best regards, > Stefano Babic > > -- > ===================================================================== > DENX Software Engineering GmbH, Managing Director: Wolfgang Denk > HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany > Phone: +49-8142-66989-53 <+49%208142%206698953> Fax: +49-8142-66989-80 > <+49%208142%206698980> Email: sba...@denx.de > ===================================================================== >
diff --git a/corelib/channel_curl.c b/corelib/channel_curl.c index e910f76..bc387d0 100644 --- a/corelib/channel_curl.c +++ b/corelib/channel_curl.c @@ -585,7 +585,7 @@ channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da goto cleanup; } - if (channel_data->headers) { + if (channel_data->received_headers) { /* * Setup supply request and receive reply HTTP headers. * A LIST_INIT()'d dictionary is expected at channel_data->headers. @@ -596,14 +596,16 @@ channel_op_res_t channel_set_options(channel_t *this, channel_data_t *channel_da CURLOPT_HEADERFUNCTION, channel_callback_headers) != CURLE_OK) || (curl_easy_setopt(channel_curl->handle, CURLOPT_HEADERDATA, - channel_data->headers) != CURLE_OK)) { + channel_data->received_headers) != CURLE_OK)) { result = CHANNEL_EINIT; goto cleanup; } + } + if (channel_data->headers_to_send) { struct dict_entry *entry; char *header; - LIST_FOREACH(entry, channel_data->headers, next) + LIST_FOREACH(entry, channel_data->headers_to_send, next) { if (ENOMEM_ASPRINTF == asprintf(&header, "%s: %s", diff --git a/corelib/downloader.c b/corelib/downloader.c index 437b36d..3d0a0a5 100644 --- a/corelib/downloader.c +++ b/corelib/downloader.c @@ -104,7 +104,8 @@ static channel_data_t channel_options = { .source = SOURCE_DOWNLOADER, .debug = false, .retries = DL_DEFAULT_RETRIES, - .low_speed_timeout = DL_LOWSPEED_TIME + .low_speed_timeout = DL_LOWSPEED_TIME, + .headers_to_send = NULL }; int start_download(const char *fname, int argc, char *argv[]) diff --git a/doc/source/swupdate.rst b/doc/source/swupdate.rst index 317c54d..5b0c150 100644 --- a/doc/source/swupdate.rst +++ b/doc/source/swupdate.rst @@ -184,7 +184,7 @@ Images fully streamed --------------------- In case of remote update, SWUpdate extracts relevant images from the stream -and copies them into the directory pointed to by the environment variable +and copies them into the directory pointed to by the environment variable ``TMPDIR`` (if unset, to ``/tmp``) before calling the handlers. This guarantee that an update is initiated only if all parts are present and correct. However, on some systems with less resources, the amount of RAM @@ -652,6 +652,10 @@ Mandatory arguments are marked with '\*': | | | during this period - adapt this value to | | | | your use case! | +-------------------------+----------+--------------------------------------------+ +| -a <name> <value> | strings | Custom HTTP header with given name and | +| | | value to be sent with every HTTP request | +| | | made. | ++-------------------------+----------+--------------------------------------------+ systemd Integration @@ -706,7 +710,7 @@ files are also handed over on a "regular" start of SWUpdate via ``systemctl start swupdate.service``. Note that the socket paths in the two ``ListenStream=`` directives -have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and +have to match the socket paths ``CONFIG_SOCKET_CTRL_PATH`` and ``CONFIG_SOCKET_PROGRESS_PATH`` in SWUpdate's configuration. Here, the default socket path configuration is depicted. diff --git a/include/channel_curl.h b/include/channel_curl.h index 4de098e..6dabae6 100644 --- a/include/channel_curl.h +++ b/include/channel_curl.h @@ -72,5 +72,6 @@ typedef struct { struct swupdate_digest *dgst; char sha1hash[SWUPDATE_SHA_DIGEST_LENGTH * 2 + 1]; sourcetype source; - struct dict *headers; + struct dict *headers_to_send; + struct dict *received_headers; } channel_data_t; diff --git a/suricatta/server_general.c b/suricatta/server_general.c index 1d11ada..146f02c 100644 --- a/suricatta/server_general.c +++ b/suricatta/server_general.c @@ -453,8 +453,9 @@ static server_op_res_t server_get_deployment_info(channel_t *channel, channel_da */ channel_data->url= server_prepare_query(server_general.url, &server_general.configdata); - LIST_INIT(&server_general.httpheaders); - channel_data->headers = &server_general.httpheaders; + LIST_INIT(&server_general.received_httpheaders); + LIST_INIT(&server_general.httpheaders_to_send); + channel_data->received_headers = &server_general.received_httpheaders; result = map_http_retcode(channel->get(channel, (void *)channel_data)); @@ -462,12 +463,12 @@ static server_op_res_t server_get_deployment_info(channel_t *channel, channel_da free(channel_data->url); } - pollstring = dict_get_value(&server_general.httpheaders, "Retry-After"); + pollstring = dict_get_value(&server_general.received_httpheaders, "Retry-After"); if (pollstring) { server_set_polling_interval(pollstring); } - dict_drop_db(&server_general.httpheaders); + dict_drop_db(&server_general.received_httpheaders); return result; } @@ -522,7 +523,9 @@ void server_print_help(void) "\t -w, --retrywait Time to wait prior to retry and " "resume a download (default: %ds).\n" "\t -y, --proxy Use proxy. Either give proxy URL, else " - "{http,all}_proxy env is tried.\n", + "{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.", CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, CHANNEL_DEFAULT_RESUME_DELAY); } @@ -608,6 +611,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) int choice = 0; LIST_INIT(&server_general.configdata); + LIST_INIT(&server_general.httpheaders_to_send); if (fname) { swupdate_cfg_handle handle; @@ -626,7 +630,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:", + while ((choice = getopt_long(argc, argv, "u:l:r:w:p:2:a:", long_options, NULL)) != -1) { switch (choice) { case 'u': @@ -652,6 +656,21 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) SETSTRING(server_general.cached_file, optarg); break; /* Ignore not recognized options, they can be already parsed by the caller */ + case 'a': + if (optind >= argc) + return SERVER_EINIT; + + char *name = NULL; + SETSTRING(name, optarg); + char *value = NULL; + SETSTRING(value, argv[optind++]); + + if (dict_insert_value(&server_general.httpheaders_to_send, + name, + value) < 0) + return SERVER_EINIT; + + break; case '?': default: break; @@ -664,6 +683,8 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) return SERVER_EINIT; } + channel_data_defaults.headers_to_send = &server_general.httpheaders_to_send; + if (channel_curl_init() != CHANNEL_OK) return SERVER_EINIT; diff --git a/suricatta/server_general.h b/suricatta/server_general.h index 69345a1..d5d8d48 100644 --- a/suricatta/server_general.h +++ b/suricatta/server_general.h @@ -23,7 +23,8 @@ typedef struct { bool debug; char *cached_file; struct dict configdata; - struct dict httpheaders; + struct dict received_httpheaders; + struct dict httpheaders_to_send; update_state_t update_state; channel_t *channel; } server_general_t; diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c index 33d2eec..daa00f0 100644 --- a/suricatta/server_hawkbit.c +++ b/suricatta/server_hawkbit.c @@ -52,6 +52,7 @@ static struct option long_options[] = { {"cache", required_argument, NULL, '2'}, {"initial-report-resend-period", required_argument, NULL, 'm'}, {"connection-timeout", required_argument, NULL, 's'}, + {"custom-http-header", required_argument, NULL, 'a'}, {NULL, 0, NULL, 0}}; static unsigned short mandatory_argument_count = 0; @@ -132,7 +133,9 @@ static channel_data_t channel_data_defaults = {.debug = false, .nocheckanswer = false, .nofollow = false, .strictssl = true, - .connection_timeout = 0 + .connection_timeout = 0, + .headers_to_send = NULL, + .received_headers = NULL }; static struct timeval server_time; @@ -1602,7 +1605,9 @@ void server_print_help(void) "\t --cache <file> Use cache file as starting SWU\n" "\t -m, --initial-report-resend-period <seconds> Time to wait prior to retry " "sending initial state with '-c' option (default: %ds).\n" - "\t -s, --connection-timeout Set the server connection timeout (default: 300s).\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.", CHANNEL_DEFAULT_POLLING_INTERVAL, CHANNEL_DEFAULT_RESUME_TRIES, CHANNEL_DEFAULT_RESUME_DELAY, INITIAL_STATUS_REPORT_WAIT_DELAY); @@ -1661,6 +1666,7 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) mandatory_argument_count = 0; LIST_INIT(&server_hawkbit.configdata); + LIST_INIT(&server_hawkbit.httpheaders); server_hawkbit.initial_report_resend_period = INITIAL_STATUS_REPORT_WAIT_DELAY; if (fname) { @@ -1677,6 +1683,9 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) */ read_module_settings(&handle, "hawkbit", server_hawkbit_settings, NULL); read_module_settings(&handle, "identify", settings_into_dict, &server_hawkbit.configdata); + + read_module_settings(&handle, "custom-http-headers", + settings_into_dict, &server_hawkbit.httpheaders); } swupdate_cfg_destroy(&handle); } @@ -1689,7 +1698,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:", + while ((choice = getopt_long(argc, argv, "t:i:c:u:p:xr:y::w:k:g:f:2:m:s:a:", long_options, NULL)) != -1) { switch (choice) { case 't': @@ -1782,6 +1791,16 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) channel_data_defaults.connection_timeout = (unsigned int)strtoul(optarg, NULL, 10); break; + case 'a': + if (optind >= argc) + return SERVER_EINIT; + + if (dict_insert_value(&server_hawkbit.httpheaders, + optarg, + argv[optind++]) < 0) + return SERVER_EINIT; + + break; /* Ignore not recognized options, they can be already parsed by the caller */ case '?': break; @@ -1799,6 +1818,8 @@ server_op_res_t server_start(char *fname, int argc, char *argv[]) return SERVER_EINIT; } + channel_data_defaults.headers_to_send = &server_hawkbit.httpheaders; + if (channel_curl_init() != CHANNEL_OK) return SERVER_EINIT; diff --git a/suricatta/server_hawkbit.h b/suricatta/server_hawkbit.h index aea4bb0..67f1c31 100644 --- a/suricatta/server_hawkbit.h +++ b/suricatta/server_hawkbit.h @@ -29,6 +29,7 @@ typedef struct { bool polling_interval_from_server; bool debug; struct dict configdata; + struct dict httpheaders; bool has_to_send_configData; char *configData_url; char *cancel_url;
* Expand Suricatta/Hawkbit client with ability to define a custom set of HTTP requests, defined through command line or configuration file, using 'a' short option or "custom-http-header" long option. Signed-off-by: Sava Jakovljev <sava.jakovljev@teufel.de> --- corelib/channel_curl.c | 8 +++++--- corelib/downloader.c | 3 ++- doc/source/swupdate.rst | 8 ++++++-- include/channel_curl.h | 3 ++- suricatta/server_general.c | 33 +++++++++++++++++++++++++++------ suricatta/server_general.h | 3 ++- suricatta/server_hawkbit.c | 27 ++++++++++++++++++++++++--- suricatta/server_hawkbit.h | 1 + 8 files changed, 69 insertions(+), 17 deletions(-)