@@ -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",
@@ -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[])
@@ -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,9 @@ Mandatory arguments are marked with '\*':
| | | during this period - adapt this value to |
| | | your use case! |
+-------------------------+----------+--------------------------------------------+
+| -a <name> <value> | strings | Custom HTTP header with given value to be |
+| | | sent on every HTTP request made. |
++-------------------------+----------+--------------------------------------------+
systemd Integration
@@ -706,7 +709,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.
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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 | 7 +++++-- 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, 68 insertions(+), 17 deletions(-)