diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-11-06 09:27:39 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-11-06 09:27:39 +0100 |
commit | 235ba3535b4417c4bdb967374934af6202f58c01 (patch) | |
tree | fc8cc8b96169b7ae87d152487efda61e512a4482 /src | |
parent | 5b385427fa67e9c5d4f0f130ad5501cc027b37f7 (diff) |
owfd: p2pd: add event-fn callbacks to interface
Allow external programs to register event-functions. We call these for all
wpa events we get. This way, we can later add external dbus APIs or
similar to allow clients to visualize our p2p events and add user
interfaces.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/p2pd.h | 12 | ||||
-rw-r--r-- | src/p2pd_interface.c | 63 |
2 files changed, 75 insertions, 0 deletions
@@ -30,6 +30,7 @@ #include <stdlib.h> #include <sys/epoll.h> #include <sys/signalfd.h> +#include "wpa.h" #ifdef __cplusplus extern "C" { @@ -74,6 +75,10 @@ void owfd_p2pd_ep_remove(int efd, int fd); struct owfd_p2pd_interface; +typedef void (*owfd_p2pd_interface_event_fn) (struct owfd_p2pd_interface *ifc, + struct owfd_wpa_event *ev, + void *data); + int owfd_p2pd_interface_new(struct owfd_p2pd_interface **out, struct owfd_p2pd_config *conf, int efd); void owfd_p2pd_interface_free(struct owfd_p2pd_interface *iface); @@ -82,6 +87,13 @@ int owfd_p2pd_interface_dispatch(struct owfd_p2pd_interface *iface, int owfd_p2pd_interface_dispatch_chld(struct owfd_p2pd_interface *iface, struct signalfd_siginfo *info); +int owfd_p2pd_interface_register_event_fn(struct owfd_p2pd_interface *iface, + owfd_p2pd_interface_event_fn event_fn, + void *data); +void owfd_p2pd_interface_unregister_event_fn(struct owfd_p2pd_interface *iface, + owfd_p2pd_interface_event_fn event_fn, + void *data); + #ifdef __cplusplus } #endif diff --git a/src/p2pd_interface.c b/src/p2pd_interface.c index 2bdaa65..c1f1db1 100644 --- a/src/p2pd_interface.c +++ b/src/p2pd_interface.c @@ -38,14 +38,23 @@ #include <unistd.h> #include "p2pd.h" #include "shared.h" +#include "shl_dlist.h" #include "shl_log.h" #include "wpa.h" +struct event_user { + struct shl_dlist list; + owfd_p2pd_interface_event_fn event_fn; + void *data; +}; + struct owfd_p2pd_interface { struct owfd_wpa_ctrl *wpa; struct owfd_p2pd_config *config; int wpa_fd; pid_t pid; + + struct shl_dlist event_users; }; static int wpa_setup(struct owfd_p2pd_interface *iface); @@ -360,6 +369,7 @@ int owfd_p2pd_interface_new(struct owfd_p2pd_interface **out, if (!iface) return log_ENOMEM(); iface->config = conf; + shl_dlist_init(&iface->event_users); r = owfd_wpa_ctrl_new(&iface->wpa); if (r < 0) { @@ -367,6 +377,7 @@ int owfd_p2pd_interface_new(struct owfd_p2pd_interface **out, log_vERRNO(); goto err_iface; } + owfd_wpa_ctrl_set_data(iface->wpa, iface); r = fork_wpa(iface); if (r < 0) @@ -391,9 +402,18 @@ err_iface: void owfd_p2pd_interface_free(struct owfd_p2pd_interface *iface) { + struct event_user *e; + if (!iface) return; + while (!shl_dlist_empty(&iface->event_users)) { + e = shl_dlist_entry(shl_dlist_first(&iface->event_users), + struct event_user, list); + shl_dlist_unlink(&e->list); + free(e); + } + kill_wpa(iface); owfd_wpa_ctrl_close(iface->wpa); owfd_wpa_ctrl_unref(iface->wpa); @@ -429,6 +449,40 @@ int owfd_p2pd_interface_dispatch_chld(struct owfd_p2pd_interface *iface, return OWFD_P2PD_EP_QUIT; } +int owfd_p2pd_interface_register_event_fn(struct owfd_p2pd_interface *iface, + owfd_p2pd_interface_event_fn event_fn, + void *data) +{ + struct event_user *e; + + e = calloc(1, sizeof(*e)); + if (!e) + return -ENOMEM; + + e->event_fn = event_fn; + e->data = data; + + shl_dlist_link(&iface->event_users, &e->list); + return 0; +} + +void owfd_p2pd_interface_unregister_event_fn(struct owfd_p2pd_interface *iface, + owfd_p2pd_interface_event_fn event_fn, + void *data) +{ + struct shl_dlist *i; + struct event_user *e; + + shl_dlist_for_each(i, &iface->event_users) { + e = shl_dlist_entry(i, struct event_user, list); + if (e->event_fn == event_fn && e->data == data) { + shl_dlist_unlink(&e->list); + free(e); + return; + } + } +} + static int wpa_request_ok(struct owfd_p2pd_interface *iface, const char *req) { return owfd_wpa_ctrl_request_ok(iface->wpa, req, strlen(req), -1); @@ -478,6 +532,9 @@ err_notsupp: static void wpa_event(struct owfd_wpa_ctrl *wpa, void *buf, size_t len, void *data) { + struct owfd_p2pd_interface *iface = data; + struct shl_dlist *i, *t; + struct event_user *e; struct owfd_wpa_event ev; int r; @@ -492,6 +549,12 @@ static void wpa_event(struct owfd_wpa_ctrl *wpa, void *buf, } else { log_debug("wpa-event (%d:%s): %s", ev.type, owfd_wpa_event_name(ev.type), ev.raw); + + shl_dlist_for_each_safe(i, t, &iface->event_users) { + e = shl_dlist_entry(i, struct event_user, list); + if (e->event_fn) + e->event_fn(iface, &ev, e->data); + } } owfd_wpa_event_reset(&ev); |