From dfd67ab68a438f1a692e91832c3698b023c74167 Mon Sep 17 00:00:00 2001
From: José Bollo <jose.bollo@iot.bzh>
Date: Sat, 13 Feb 2016 17:20:08 +0100
Subject: afm-launch: begins integration of modes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Change-Id: I51b3659ca86c04f7276b4beb0e0863fa0e1d700d
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
---
 conf/afm-launch.conf  |   8 ++
 src/afm-launch.c      | 280 +++++++++++++++++++++++++++++++++-----------------
 src/afm-user-daemon.c |   2 +-
 3 files changed, 192 insertions(+), 98 deletions(-)

diff --git a/conf/afm-launch.conf b/conf/afm-launch.conf
index a572c88..92ede4d 100644
--- a/conf/afm-launch.conf
+++ b/conf/afm-launch.conf
@@ -14,6 +14,8 @@
 # %H height
 # %% %
 
+mode local
+
 text/html
 	/usr/bin/afb-daemon --alias=/icons:%I --port=%P --rootdir=%r --token=%S --sessiondir=%D/.afb-daemon
 	/usr/bin/web-runtime http://localhost:%P/%c?token=%S
@@ -24,3 +26,9 @@ application/x-executable
 text/vnd.qt.qml
 	/usr/bin/qt5/qmlscene -fullscreen -I %r -I %r/imports %r/%c
 
+mode remote
+
+text/html
+	/usr/bin/afb-daemon --alias=/icons:%I --port=%P --rootdir=%r --token=%S --sessiondir=%D/.afb-daemon
+	http://%%h:%P/%c?token=%S
+
diff --git a/src/afm-launch.c b/src/afm-launch.c
index 216e6df..87e8e3a 100644
--- a/src/afm-launch.c
+++ b/src/afm-launch.c
@@ -38,20 +38,18 @@ extern char **environ;
 
 #define DEFAULT_TYPE "text/html"
 
-const char separators[] = " \t\n";
-
-struct execdesc {
-	char *type;
-	char **execs[2];
+struct type_list {
+	struct type_list *next;
+	char type[1];
 };
 
-struct launchers {
-	int count;
-	struct execdesc *descs;
+struct desc_list {
+	struct desc_list *next;
+	enum afm_launch_mode mode;
+	struct type_list *types;
+	char **execs[2];
 };
 
-static struct launchers launchers = { 0, NULL };
-
 struct launchparam {
 	int port;
 	const char *secret;
@@ -60,8 +58,6 @@ struct launchparam {
 	const char **slave;
 };
 
-static gid_t groupid = 0;
-
 struct confread {
 	const char *filepath;
 	FILE *file;
@@ -71,17 +67,29 @@ struct confread {
 	char buffer[4096];
 };
 
-static void dump_launchers(struct launchers *launchs)
+struct desc_list *launchers = NULL;
+
+static gid_t groupid = 0;
+
+const char separators[] = " \t\n";
+
+static void dump_launchers()
 {
-	int i, j, k;
-	for (i = 0 ; i < launchs->count ; i++) {
-		printf("%s\n", launchs->descs[i].type);
+	int j, k;
+	struct desc_list *desc;
+	struct type_list *type;
+
+	for (desc = launchers ; desc != NULL ; desc = desc->next) {
+		printf("mode %s\n", name_of_launch_mode(desc->mode));
+		for (type = desc->types ; type != NULL ; type = type->next)
+			printf("%s\n", type->type);
 		for ( j = 0 ; j < 2 ; j++)
-			if (launchs->descs[i].execs[j] != NULL) {
-				for (k = 0 ; launchs->descs[i].execs[j][k] != NULL ; k++)
-					printf("  %s", launchs->descs[i].execs[j][k]);
+			if (desc->execs[j] != NULL) {
+				for (k = 0 ; desc->execs[j][k] != NULL ; k++)
+					printf("  %s", desc->execs[j][k]);
 				printf("\n");
 			}
+		printf("\n");
 	}
 }
 
@@ -110,13 +118,7 @@ static int read_line(struct confread *cread)
 	return 0;
 }
 
-static char *dup_token(struct confread *cread)
-{
-	assert(cread->length);
-	return strndup(&cread->buffer[cread->index], cread->length);
-}
-
-static char **dup_tokens_vector(struct confread *cread)
+static char **read_vector(struct confread *cread)
 {
 	int index0, length0;
 	char **vector, *args;
@@ -158,99 +160,171 @@ static char **dup_tokens_vector(struct confread *cread)
 	return vector;
 }
 
-static int read_type(struct confread *cread)
+static struct type_list *read_type(struct confread *cread)
 {
-	int count;
-	struct execdesc *descs;
-	char *type;
+	int index, length;
+	struct type_list *result;
 
-	/* get the type */
-	type = dup_token(cread);
-	if (type == NULL) {
-		ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
-		errno = ENOMEM;
-		return -1;
-	}
+	/* record index and length */
+	index = cread->index;
+	length = cread->length;
 
-	/* check the type */
+	/* check no extra characters */
 	if (next_token(cread)) {
-		ERROR("%s:%d: extra characters found after type %s", cread->filepath, cread->lineno, type);
-		free(type);
+		ERROR("%s:%d: extra characters found after type %.*s", cread->filepath, cread->lineno, length, &cread->buffer[index]);
 		errno = EINVAL;
-		return -1;
+		return NULL;
 	}
 
-	/* allocates data */
-	count = launchers.count + 1;
-	descs = realloc(launchers.descs, count * sizeof(struct execdesc));
-	if (descs == NULL) {
-		free(type);
+	/* allocate structure */
+	result = malloc(sizeof(struct type_list) + length);
+	if (result == NULL) {
+		ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
 		errno = ENOMEM;
-		return -1;
+		return NULL;
 	}
 
-	/* fill data */
-	launchers.descs = descs;
-	descs += count - 1;
-	descs->type = type;
-	descs->execs[0] = NULL;
-	descs->execs[1] = NULL;
-	launchers.count = count;
-	return 0;
+	/* fill the structure */
+	memcpy(result->type, &cread->buffer[index], length);
+	result->type[length] = 0;
+	return result;
 }
 
-static int read_args(struct confread *cread, int bottom, int offset)
+static enum afm_launch_mode read_mode(struct confread *cread)
 {
-	char **vector;
+	int index, length;
+	enum afm_launch_mode result;
 
-	while (bottom < launchers.count) {
-		vector = dup_tokens_vector(cread);
-		if (vector == NULL) {
-			ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
-			return -1;
-		}
-		launchers.descs[bottom++].execs[offset] = vector;
+	assert(cread->index == 0);
+	assert(!strncmp(&cread->buffer[cread->index], "mode", 4));
+
+	/* get the next token: the mode string */
+	if (!next_token(cread)) {
+		ERROR("%s:%d: no mode value set", cread->filepath, cread->lineno);
+		errno = EINVAL;
+		return invalid_launch_mode;
+	}
+
+	/* record index and length */
+	index = cread->index;
+	length = cread->length;
+
+	/* check no extra characters */
+	if (next_token(cread)) {
+		ERROR("%s:%d: extra characters found after mode %.*s", cread->filepath, cread->lineno, length, &cread->buffer[index]);
+		errno = EINVAL;
+		return invalid_launch_mode;
+	}
+
+	/* get the mode */
+	cread->buffer[index + length] = 0;
+	result = launch_mode_of_string(&cread->buffer[index]);
+	if (result == invalid_launch_mode) {
+		ERROR("%s:%d: invalid mode value %s", cread->filepath, cread->lineno, &cread->buffer[index]);
+		errno = EINVAL;
+	}
+	return result;
+}
+
+static void free_type_list(struct type_list *types)
+{
+	while (types != NULL) {
+		struct type_list *next = types->next;
+		free(types);
+		types = next;
 	}
-	return 0;
 }
 
 static int read_launchers(struct confread *cread)
 {
-	int rc, bottom, offset, typed;
+	int rc;
+	struct type_list *types, *lt;
+	struct desc_list *desc;
+	enum afm_launch_mode mode;
+	char **vector;
 
 	/* reads the file */
-	offset = 0;
-	typed = 0;
-	bottom = launchers.count;
+	lt = NULL;
+	types = NULL;
+	desc = NULL;
+	mode = invalid_launch_mode;
 	rc = read_line(cread);
 	while (rc > 0) {
 		if (cread->index == 0) {
-			if (!typed)
-				bottom = launchers.count;
-			rc = read_type(cread);
-			if (rc)
-				return rc;
-			if (!typed) {
-				typed = 1;
-				offset = 0;
+			if (cread->length == 4 && !memcmp(&cread->buffer[cread->index], "mode", 4)) {
+				/* check if allowed */
+				if (types != NULL) {
+					ERROR("%s:%d: mode found before launch vector", cread->filepath, cread->lineno);
+					errno = EINVAL;
+					free_type_list(types);
+					return -1;
+				}
+
+				/* read the mode */
+				mode = read_mode(cread);
+				if (mode == invalid_launch_mode)
+					return -1;
+			} else {
+				if (mode == invalid_launch_mode) {
+					ERROR("%s:%d: mode not found before type", cread->filepath, cread->lineno);
+					errno = EINVAL;
+					assert(types == NULL);
+					return -1;
+				}
+				/* read a type */
+				lt = read_type(cread);
+				if (lt == NULL) {
+					free_type_list(types);
+					return -1;
+				}
+				lt->next = types;
+				types = lt;
 			}
-		} else if (!typed && !offset) {
-			ERROR("%s:%d: untyped launcher found", cread->filepath, cread->lineno);
-			errno = EINVAL;
-			return -1;
-		} else if (offset >= 2) {
-			ERROR("%s:%d: extra launcher found", cread->filepath, cread->lineno);
+			desc = NULL;
+		} else if (types == NULL && desc == NULL) {
+			if (lt == NULL)
+				ERROR("%s:%d: untyped launch vector found", cread->filepath, cread->lineno);
+			else
+				ERROR("%s:%d: extra launch vector found (2 max)", cread->filepath, cread->lineno);
 			errno = EINVAL;
 			return -1;
 		} else {
-			rc = read_args(cread, bottom, offset);
-			if (rc)
-				return rc;
-			offset++;
-			typed = 0;
+			vector = read_vector(cread);
+			if (vector == NULL) {
+				ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+				free_type_list(types);
+				errno = ENOMEM;
+				return -1;
+			}
+			if (types) {
+				assert(desc == NULL);
+				desc = malloc(sizeof * desc);
+				if (desc == NULL) {
+					ERROR("%s:%d: out of memory", cread->filepath, cread->lineno);
+					free_type_list(types);
+					errno = ENOMEM;
+					return -1;
+				}
+				desc->next = launchers;
+				desc->mode = mode;
+				desc->types = types;
+				desc->execs[0] = vector;
+				desc->execs[1] = NULL;
+				types = NULL;
+				launchers = desc;
+			} else {
+				desc->execs[1] = vector;
+				desc = NULL;
+			}
 		}
 		rc = read_line(cread);
 	}
+	if (types != NULL) {
+		ERROR("%s:%d: end of file found before launch vector", cread->filepath, cread->lineno);
+		free_type_list(types);
+		errno = EINVAL;
+		return -1;
+	}
 	return rc;
 }
 
@@ -587,17 +661,31 @@ int afm_launch_initialize()
 		groupid = -1;
 
 	rc = read_configuration_file(FWK_LAUNCH_CONF);
-	dump_launchers(&launchers);
+	dump_launchers();
 	return rc;
 }
 
+static struct desc_list *search_launcher(const char *type, enum afm_launch_mode mode)
+{
+	struct desc_list *dl;
+	struct type_list *tl;
+
+	for (dl = launchers ; dl ; dl = dl->next)
+		if (dl->mode == mode)
+			for (tl = dl->types ; tl != NULL ; tl = tl->next)
+				if (!strcmp(tl->type, type))
+					return dl;
+	return NULL;
+}
+
 int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
 {
 	char datadir[PATH_MAX];
-	int ikl, rc;
+	int rc;
 	char secret[9];
 	struct launchparam params;
 	const char *type;
+	struct desc_list *dl;
 
 	/* should be init */
 	assert(groupid != 0);
@@ -609,11 +697,9 @@ int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
 
 	/* what launcher ? */
 	type = desc->type != NULL && *desc->type ? desc->type : DEFAULT_TYPE;
-	ikl = 0;
-	while (ikl < launchers.count && strcmp(type, launchers.descs[ikl].type))
-		ikl++;
-	if (ikl == launchers.count) {
-		ERROR("type %s not found!", type);
+	dl = search_launcher(type, desc->mode);
+	if (dl == NULL) {
+		ERROR("type %s not found for mode %s!", type, name_of_launch_mode(desc->mode));
 		errno = ENOENT;
 		return -1;
 	}
@@ -631,8 +717,8 @@ int afm_launch(struct afm_launch_desc *desc, pid_t children[2], char **uri)
 	params.port = mkport();
 	params.secret = secret;
 	params.datadir = datadir;
-	params.master = (const char **)launchers.descs[ikl].execs[0];
-	params.slave = (const char **)launchers.descs[ikl].execs[1];
+	params.master = (const char **)dl->execs[0];
+	params.slave = (const char **)dl->execs[1];
 
 	return params.slave ? launchexec2(desc, children, &params) : launchexec1(desc, children, &params);
 }
diff --git a/src/afm-user-daemon.c b/src/afm-user-daemon.c
index 09ec0b5..81115d7 100644
--- a/src/afm-user-daemon.c
+++ b/src/afm-user-daemon.c
@@ -140,7 +140,7 @@ static void on_start(struct jreq *jreq, struct json_object *obj)
 	}
 
 	/* get the application */
-	INFO("method start called for %s mode=%s", appid, mode);
+	INFO("method start called for %s mode=%s", appid, name_of_launch_mode(mode));
 	appli = afm_db_get_application(afdb, appid);
 	if (appli == NULL) {
 		jbus_reply_error_s(jreq, error_not_found);
-- 
cgit