diff mbox

[18/24] petitboot: Add discover user event

Message ID 20090413011137.879863989@am.sony.com
State Accepted
Headers show

Commit Message

Geoff Levand April 13, 2009, 1:11 a.m. UTC
Add a gereric event interface to pb-discover.

Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
 discover/device-handler.c |   58 +++++++++++++++
 discover/event-parser.c   |   55 ++++++++++++++
 discover/parser.h         |    1 
 discover/pb-discover.c    |    7 +
 discover/user-event.c     |  175 ++++++++++++++++++++++++++++++++++++++++++++++
 discover/user-event.h     |   33 ++++++++
 rules.mk                  |    7 +
 7 files changed, 333 insertions(+), 3 deletions(-)
diff mbox

Patch

--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -335,6 +335,52 @@  static int handle_remove_udev_event(stru
 	return 0;
 }
 
+static int handle_add_user_event(struct device_handler *handler,
+		struct event *event)
+{
+	struct device *device;
+
+	assert(event->device);
+
+	device = talloc_zero(handler, struct device);
+
+	if (!device)
+		goto fail;
+
+	device->id = talloc_strdup(device, event->device);
+	list_init(&device->boot_options);
+
+	parse_user_event(device, event);
+
+	discover_server_notify_add(handler->server, device);
+
+	/* add device to handler device array */
+	device_handler_add(handler, device);
+
+	return 0;
+
+fail:
+	talloc_free(device);
+	return 0;
+}
+
+static int handle_remove_user_event(struct device_handler *handler,
+		struct event *event)
+{
+	struct device *device = device_handler_find(handler, event->device);
+
+	if (!device)
+		return 0;
+
+	discover_server_notify_remove(handler->server, device);
+
+	/* remove device from handler device array */
+	device_handler_remove(handler, device);
+
+	talloc_free(device);
+	return 0;
+}
+
 int device_handler_event(struct device_handler *handler,
 		struct event *event)
 {
@@ -356,6 +402,18 @@  int device_handler_event(struct device_h
 		}
 		break;
 	case EVENT_TYPE_USER:
+		switch (event->action) {
+		case EVENT_ACTION_ADD:
+			rc = handle_add_user_event(handler, event);
+			break;
+		case EVENT_ACTION_REMOVE:
+			rc = handle_remove_user_event(handler, event);
+			break;
+		default:
+			pb_log("%s unknown action: %d\n", __func__,
+				event->action);
+			break;
+		}
 		break;
 	default:
 		pb_log("%s unknown type: %d\n", __func__, event->type);
--- /dev/null
+++ b/discover/event-parser.c
@@ -0,0 +1,55 @@ 
+#define _GNU_SOURCE
+
+#include <assert.h>
+
+#include "log/log.h"
+#include "talloc/talloc.h"
+#include "event.h"
+#include "parser-utils.h"
+
+int parse_user_event(struct device *device, struct event *event)
+{
+	struct boot_option *opt;
+	const char *p;
+
+	opt = talloc_zero(device, struct boot_option);
+
+	if (!opt)
+		goto fail;
+
+	p = event_get_param(event, "name");
+
+	if (!p) {
+		pb_log("%s: no name found\n", __func__);
+		goto fail;
+	}
+
+	opt->id = talloc_asprintf(opt, "%s#%s", device->id, p);
+	opt->name = talloc_strdup(opt, p);
+
+	p = event_get_param(event, "image");
+	assert(p);
+
+	if (!p) {
+		pb_log("%s: no image found\n", __func__);
+		goto fail;
+	}
+
+	opt->boot_image_file = talloc_strdup(opt, p);
+
+	p = event_get_param(event, "args");
+	assert(p);
+
+	opt->boot_args = talloc_strdup(opt, p);
+
+	opt->description = talloc_asprintf(opt, "%s %s", opt->boot_image_file,
+		opt->boot_args);
+
+	device_add_boot_option(device, opt);
+
+	return 0;
+
+fail:
+	talloc_free(opt);
+	return -1;
+}
--- a/discover/parser.h
+++ b/discover/parser.h
@@ -23,5 +23,6 @@  enum generic_icon_type {
 void parser_init(void);
 
 void iterate_parsers(struct discover_context *ctx);
+int parse_user_event(struct device *device, struct event *event);
 
 #endif /* _PARSER_H */
--- a/discover/pb-discover.c
+++ b/discover/pb-discover.c
@@ -7,6 +7,7 @@ 
 #include <log/log.h>
 
 #include "udev.h"
+#include "user-event.h"
 #include "discover-server.h"
 #include "device-handler.h"
 
@@ -22,6 +23,7 @@  int main(void)
 	struct device_handler *handler;
 	struct discover_server *server;
 	struct udev *udev;
+	struct user_event *uev;
 	FILE *log;
 
 	log = fopen("pb-discover.log", "a");
@@ -52,7 +54,12 @@  int main(void)
 	if (!udev)
 		return EXIT_FAILURE;
 
+	uev = user_event_init(handler);
+	if (!uev)
+		return EXIT_FAILURE;
+
 	udev_trigger(udev);
+	user_event_trigger(uev);
 
 	for (running = 1; running;) {
 		if (waiter_poll())
--- /dev/null
+++ b/discover/user-event.c
@@ -0,0 +1,175 @@ 
+/*
+ *  Copyright (C) 2009 Sony Computer Entertainment Inc.
+ *  Copyright 2009 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <log/log.h>
+#include <talloc/talloc.h>
+#include <waiter/waiter.h>
+
+#include "device-handler.h"
+#include "event.h"
+#include "user-event.h"
+
+
+struct user_event {
+	struct device_handler *handler;
+	int socket;
+};
+
+static void user_event_print_event(struct event __attribute__((unused)) *event)
+{
+	const char *action, *params[] = {
+		"name", "image", "args",
+		NULL,
+	};
+	int i;
+
+	action = event->action == EVENT_ACTION_ADD ? "add" : "remove";
+
+	pb_log("user_event %s event:\n", action);
+	pb_log("\tdevice: %s\n", event->device);
+
+	for (i = 0; params[i]; i++)
+		pb_log("\t%-12s => %s\n",
+				params[i], event_get_param(event, params[i]));
+}
+
+static void user_event_handle_message(struct user_event *uev, char *buf,
+	int len)
+{
+	int result;
+	struct event *event;
+
+	event = talloc(uev, struct event);
+	event->type = EVENT_TYPE_USER;
+
+	result = event_parse_ad_message(event, buf, len);
+
+	if (result)
+		return;
+
+	user_event_print_event(event);
+	device_handler_event(uev->handler, event);
+	talloc_free(event);
+
+	return;
+}
+
+static int user_event_process(void *arg)
+{
+	struct user_event *uev = arg;
+	char buf[PBOOT_USER_EVENT_SIZE];
+	int len;
+
+	len = recvfrom(uev->socket, buf, sizeof(buf), 0, NULL, NULL);
+
+	if (len < 0) {
+		pb_log("%s: socket read failed: %s", __func__, strerror(errno));
+		return 0;
+	}
+
+	if (len == 0) {
+		pb_log("%s: empty", __func__);
+		return 0;
+	}
+
+	pb_log("%s: %u bytes\n", __func__, len);
+
+	user_event_handle_message(uev, buf, len);
+
+	return 0;
+}
+
+static int user_event_destructor(void *arg)
+{
+	struct user_event *uev = arg;
+
+	pb_log("%s\n", __func__);
+
+	if (uev->socket >= 0)
+		close(uev->socket);
+
+	return 0;
+}
+
+struct user_event *user_event_init(struct device_handler *handler)
+{
+	struct sockaddr_un addr;
+	struct user_event *uev;
+
+	unlink(PBOOT_USER_EVENT_SOCKET);
+
+	uev = talloc(NULL, struct user_event);
+
+	uev->handler = handler;
+
+	uev->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (uev->socket < 0) {
+		pb_log("%s: Error creating event handler socket: %s\n",
+			__func__, strerror(errno));
+		goto out_err;
+	}
+
+	talloc_set_destructor(uev, user_event_destructor);
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strcpy(addr.sun_path, PBOOT_USER_EVENT_SOCKET);
+
+	if (bind(uev->socket, (struct sockaddr *)&addr, sizeof(addr))) {
+		pb_log("Error binding event handler socket: %s\n",
+			strerror(errno));
+	}
+
+	waiter_register(uev->socket, WAIT_IN, user_event_process, uev);
+
+	pb_log("%s: waiting on %s\n", __func__, PBOOT_USER_EVENT_SOCKET);
+
+	return uev;
+
+out_err:
+	talloc_free(uev);
+	return NULL;
+}
+
+/**
+ * user_event_trigger - Trigger known user events
+ *
+ * SIGUSR1 causes udhcpc to renew the current lease or obtain a new lease.
+ */
+
+void user_event_trigger(struct user_event __attribute__((unused)) *uev)
+{
+	/* FIXME: todo */
+}
+
+void user_event_destroy(struct user_event *uev)
+{
+	talloc_free(uev);
+}
--- /dev/null
+++ b/discover/user-event.h
@@ -0,0 +1,33 @@ 
+/*
+ *  Copyright (C) 2009 Sony Computer Entertainment Inc.
+ *  Copyright 2009 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_PB_DISCOVER_USER_EVENT_H)
+#define _PB_DISCOVER_USER_EVENT_H
+
+#include "device-handler.h"
+
+#define PBOOT_USER_EVENT_SOCKET "/tmp/petitboot.ev"
+#define PBOOT_USER_EVENT_SIZE (1 * 1024)
+
+struct user_event;
+
+struct user_event *user_event_init(struct device_handler *handler);
+void user_event_trigger(struct user_event *uev);
+void user_event_destroy(struct user_event *uev);
+
+#endif
--- a/rules.mk
+++ b/rules.mk
@@ -17,7 +17,7 @@  parser_test = test/parser-test
 
 # install targets and components
 daemons = $(pb_discover)
-parsers = kboot yaboot
+parsers = event kboot yaboot
 uis = $(pb_test)
 tests = $(parser_test)
 
@@ -40,8 +40,9 @@  waiter_objs = lib/waiter/waiter.o
 # daemon objs
 parser_objs = discover/parser.o discover/parser-conf.o discover/paths.o \
 	$(foreach p, $(parsers), discover/$(p)-parser.o)
-discover_objs = discover/event.o  discover/udev.o discover/discover-server.o \
-	discover/device-handler.o discover/paths.o discover/parser-utils.o
+discover_objs = discover/event.o discover/user-event.o discover/udev.o \
+	discover/discover-server.o discover/device-handler.o discover/paths.o \
+	discover/parser-utils.o
 
 # client objs
 ui_common_objs = ui/common/discover-client.o ui/common/loader.o \