diff mbox series

[5/6] downloader: implement IPC to get URL

Message ID 20230817111712.235063-5-stefano.babic@swupdate.org
State Accepted
Delegated to: Stefano Babic
Headers show
Series None | expand

Commit Message

Stefano Babic Aug. 17, 2023, 11:17 a.m. UTC
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(-)
diff mbox series

Patch

diff --git a/corelib/downloader.c b/corelib/downloader.c
index be7090e7..ac138f85 100644
--- a/corelib/downloader.c
+++ b/corelib/downloader.c
@@ -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;
 }