From fbb2f7a20e5ac7b6d9f578fdb3538fad4310c472 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Sun, 12 Apr 2009 15:11:54 +0000 Subject: [PATCH] Add discover user event Add a gereric event interface to pb-discover. Signed-off-by: Geoff Levand Signed-off-by: Jeremy Kerr --- 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(-) create mode 100644 discover/event-parser.c create mode 100644 discover/user-event.c create mode 100644 discover/user-event.h diff --git a/discover/device-handler.c b/discover/device-handler.c index 908409c..c72390b 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -335,6 +335,52 @@ static int handle_remove_udev_event(struct device_handler *handler, 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_handler *handler, } 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); diff --git a/discover/event-parser.c b/discover/event-parser.c new file mode 100644 index 0000000..0cfda9a --- /dev/null +++ b/discover/event-parser.c @@ -0,0 +1,55 @@ +#define _GNU_SOURCE + +#include + +#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; +} diff --git a/discover/parser.h b/discover/parser.h index ff86578..1b88831 100644 --- 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 */ diff --git a/discover/pb-discover.c b/discover/pb-discover.c index 4d61814..d7ea0ca 100644 --- a/discover/pb-discover.c +++ b/discover/pb-discover.c @@ -7,6 +7,7 @@ #include #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()) diff --git a/discover/user-event.c b/discover/user-event.c new file mode 100644 index 0000000..afc4c43 --- /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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#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); +} diff --git a/discover/user-event.h b/discover/user-event.h new file mode 100644 index 0000000..e134d0c --- /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 diff --git a/rules.mk b/rules.mk index 1c91661..ff807e4 100644 --- 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 \ -- 2.39.2