@@ -8,14 +8,17 @@
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
+#include <json-c/json.h>
#include "util.h"
#include "network_ipc.h"
#include "download_interface.h"
+#include "server_utils.h"
#include "channel.h"
#include "channel_curl.h"
#include "parselib.h"
#include "swupdate_settings.h"
+#include "pctl.h"
/*
* Number of seconds while below low speed
@@ -34,6 +37,19 @@ static struct option long_options[] = {
{"authentication", required_argument, NULL, 'a'},
{NULL, 0, NULL, 0}};
+static channel_data_t channel_options = {
+ .source = SOURCE_DOWNLOADER,
+ .debug = false,
+ .retries = DL_DEFAULT_RETRIES,
+ .retry_sleep = CHANNEL_DEFAULT_RESUME_DELAY,
+ .low_speed_timeout = DL_LOWSPEED_TIME,
+ .headers_to_send = NULL,
+ .max_download_speed = 0, /* Unlimited download speed is default. */
+ .noipc = false,
+ .range = NULL,
+ .headers = NULL,
+};
+
/*
* This provides a pull from an external server
* It is not thought to work with local (file://)
@@ -99,6 +115,82 @@ static int download_settings(void *elem, void __attribute__ ((__unused__)) *dat
return 0;
}
+static server_op_res_t download_server_ipc(int fd)
+{
+ ipc_message msg;
+ server_op_res_t result = SERVER_OK;
+ int ret;
+ struct json_object *json_root;
+ json_object *json_data;
+
+
+ ret = read(fd, &msg, sizeof(msg));
+ if (ret != sizeof(msg))
+ return SERVER_EERR;
+ switch (msg.data.procmsg.cmd) {
+ case CMD_SET_DOWNLOAD_URL:
+ json_root = server_tokenize_msg(msg.data.procmsg.buf,
+ sizeof(msg.data.procmsg.buf));
+ if (!json_root) {
+ ERROR("Wrong JSON message, see documentation");
+ result = SERVER_EERR;
+ break;
+ }
+ json_data = json_get_path_key(json_root, (const char *[]){"url", NULL});
+ if (!json_data) {
+ ERROR("URL is mandatory, no URL found");
+ result = SERVER_EERR;
+ break;
+ }
+ channel_options.url = strdup(json_object_get_string(json_data));
+
+ /*
+ * check for authentication
+ */
+ json_data = json_get_path_key(json_root, (const char *[]){"userpassword", NULL});
+ if (json_data) {
+ /*
+ * Credentials are in the curl format, user:password, see CURLOPT_USERPWD
+ */
+ channel_options.auth = strdup(json_object_get_string(json_data));
+ }
+ break;
+ default:
+ result = SERVER_EERR;
+ break;
+ }
+
+ msg.data.procmsg.len = 0;
+ if (result == SERVER_EERR) {
+ msg.type = NACK;
+ } else
+ msg.type = ACK;
+
+ /*
+ * first send the answer, then blocks until update has finished
+ */
+ if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) {
+ TRACE("IPC ERROR: sending back msg");
+ }
+
+ if (result == SERVER_OK) {
+ RECOVERY_STATUS update_result = download_from_url(&channel_options);
+
+ if (channel_options.url != NULL) {
+ free(channel_options.url);
+ }
+ if (channel_options.auth != NULL) {
+ free(channel_options.auth);
+ }
+ channel_options.url = NULL;
+ channel_options.auth = NULL;
+
+ result = update_result == SUCCESS ? SERVER_OK : SERVER_EERR;
+ }
+ /* Send ipc back */
+ return result;
+}
+
void download_print_help(void)
{
fprintf(
@@ -113,19 +205,6 @@ void download_print_help(void)
DL_DEFAULT_RETRIES, DL_LOWSPEED_TIME, CHANNEL_DEFAULT_RESUME_DELAY);
}
-static channel_data_t channel_options = {
- .source = SOURCE_DOWNLOADER,
- .debug = false,
- .retries = DL_DEFAULT_RETRIES,
- .retry_sleep = CHANNEL_DEFAULT_RESUME_DELAY,
- .low_speed_timeout = DL_LOWSPEED_TIME,
- .headers_to_send = NULL,
- .max_download_speed = 0, /* Unlimited download speed is default. */
- .noipc = false,
- .range = NULL,
- .headers = NULL,
-};
-
int start_download_server(const char *fname, int argc, char *argv[])
{
if (fname) {
@@ -164,14 +243,34 @@ int start_download_server(const char *fname, int argc, char *argv[])
}
}
- RECOVERY_STATUS result = download_from_url(&channel_options);
+ /*
+ * if URL is passed, this is a one time step
+ * and update is started automatically. SWUpdate will
+ * exit after the update
+ */
+ if (channel_options.url) {
+ RECOVERY_STATUS result = download_from_url(&channel_options);
- if (channel_options.url != NULL) {
- free(channel_options.url);
- }
- if (channel_options.auth != NULL) {
- free(channel_options.auth);
+ if (channel_options.url != NULL) {
+ free(channel_options.url);
+ }
+ if (channel_options.auth != NULL) {
+ free(channel_options.auth);
+ }
+ exit(result == SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE);
}
- exit(result == SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE);
+ /*
+ * Loop waiting for IPC connection.
+ * Ther eis no other running thread in this process, so
+ * it is safe to call ipc_thread_fn() directly without spawning
+ * a new thread. Function dows not return
+ */
+ ipc_thread_fn(download_server_ipc);
+
+ /*
+ * function does not return
+ */
+
+ return SERVER_OK;
}
New fetaure: URL can be passed viy IPC if not transferred at startup via command line parameter. Signed-off-by: Stefano Babic <stefano.babic@swupdate.org> --- corelib/downloader.c | 139 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 20 deletions(-)