Mercurial > irccd
changeset 1162:8278d14e7aaa
irccd: add irc_bot_pollable_add, closes #2529
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 12 Feb 2022 19:55:57 +0100 |
parents | b6a0d9515c82 |
children | ad7673c59ec5 |
files | CHANGES.md lib/irccd/irccd.c lib/irccd/irccd.h man/libirccd-irccd.3 |
diffstat | 4 files changed, 142 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.md Mon Feb 07 08:42:25 2022 +0100 +++ b/CHANGES.md Sat Feb 12 19:55:57 2022 +0100 @@ -1,6 +1,12 @@ IRC Client Daemon CHANGES ========================= +irccd 4.1.0 ????-??-?? +====================== + +- Add `irc_bot_pollable_add` to insert a custom interface into the main irccd + loop. + irccd 4.0.1 2022-02-07 ======================
--- a/lib/irccd/irccd.c Mon Feb 07 08:42:25 2022 +0100 +++ b/lib/irccd/irccd.c Sat Feb 12 19:55:57 2022 +0100 @@ -45,6 +45,11 @@ struct defer *next; }; +struct pollable { + struct irc_pollable *iface; + struct pollable *next; +}; + struct irc irc = {0}; static struct sigaction sa; @@ -52,6 +57,8 @@ static int pipes[2]; static pthread_t self; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +static struct pollable *pollables; +static size_t pollablesz; static int is_command(const struct irc_plugin *p, const struct irc_event *ev) @@ -254,6 +261,18 @@ irc_util_die("read: %s\n", strerror(errno)); } +static inline void +delpollable(struct pollable *pb) +{ + if (pb->iface->finish) + pb->iface->finish(pb->iface->data); + + LL_DELETE(pollables, pb); + free(pb); + + pollablesz--; +} + void irc_bot_init(void) { @@ -582,7 +601,7 @@ size_t irc_bot_poll_size(void) { - size_t i = 1; + size_t i = 1 + pollablesz; struct irc_server *s; LL_FOREACH(irc.servers, s) @@ -597,6 +616,8 @@ assert(fds); struct irc_server *s; + struct pollable *pb; + int frecv = 0, fsend = 0; fds->fd = pipes[0]; fds->events = POLLIN; @@ -604,6 +625,11 @@ LL_FOREACH(irc.servers, s) irc_server_prepare(s, fds++); + LL_FOREACH(pollables, pb) { + pb->iface->want(&frecv, &fsend, pb->iface->data); + fds->fd = pb->iface->fd(pb->iface->data); + fds++->events |= (frecv ? POLLIN : 0) | (fsend ? POLLOUT : 0); + } } void @@ -613,6 +639,9 @@ struct irc_server *s; struct defer *d, *dtmp; + struct pollable *pb, *pbnext; + size_t pbsz = pollablesz; + int frecv, fsend; pipe_flush(fds++); @@ -625,6 +654,19 @@ LL_FOREACH(irc.servers, s) irc_server_flush(s, fds++); + + /* + * We must iterate using the number of pollables because their sync + * function may modify the list. + */ + for (pb = pollables; pbsz--; pb = pbnext) { + pbnext = pb->next; + frecv = fds->revents & POLLIN; + fsend = fds++->revents & POLLOUT; + + if (pb->iface->sync(frecv, fsend, pb->iface->data) < 0) + delpollable(pb); + } } int @@ -667,10 +709,26 @@ } void +irc_bot_pollable_add(struct irc_pollable *iface) +{ + assert(iface); + assert(iface->fd && iface->want && iface->sync); + + struct pollable *pb; + + pb = irc_util_calloc(1, sizeof (*pb)); + pb->iface = iface; + + LL_APPEND(pollables, pb); + pollablesz++; +} + +void irc_bot_finish(void) { struct irc_plugin_loader *ld, *ldtmp; struct defer *d, *dtmp; + struct pollable *pb, *pbtmp; close(pipes[0]); close(pipes[1]); @@ -685,8 +743,17 @@ /* Remove all deferred calls. */ LL_FOREACH_SAFE(queue, d, dtmp) free(d); + LL_FOREACH_SAFE(pollables, pb, pbtmp) { + if (pb->iface->finish) + pb->iface->finish(pb->iface->data); + + free(pb); + } queue = NULL; + pollables = NULL; + pollablesz = 0; + irc_bot_server_clear(); irc_bot_plugin_clear(); irc_bot_rule_clear();
--- a/lib/irccd/irccd.h Mon Feb 07 08:42:25 2022 +0100 +++ b/lib/irccd/irccd.h Sat Feb 12 19:55:57 2022 +0100 @@ -30,6 +30,14 @@ extern "C" { #endif +struct irc_pollable { + void *data; + int (*fd)(void *); + void (*want)(int *, int *, void *); + int (*sync)(int, int, void *); + void (*finish)(void *); +}; + extern struct irc { struct irc_server *servers; struct irc_plugin *plugins; @@ -117,6 +125,9 @@ irc_bot_post(void (*)(void *), void *); void +irc_bot_pollable_add(struct irc_pollable *); + +void irc_bot_finish(void); #if defined(__cplusplus)
--- a/man/libirccd-irccd.3 Mon Feb 07 08:42:25 2022 +0100 +++ b/man/libirccd-irccd.3 Sat Feb 12 19:55:57 2022 +0100 @@ -31,6 +31,14 @@ struct irc_rule *rules; struct irc_hook *hooks; } irc; + +struct irc_pollable { + void *data; + int (*fd)(void *data); + void (*want)(int *frecv, int *fsend, void *data); + int (*sync)(int frecv, int fsend, void *data); + void (*finish)(void *data); +}; .Ed .Pp .Ft void @@ -86,6 +94,8 @@ .Ft void .Fn irc_bot_post "void (*fn)(void *), void *data" .Ft void +.Fn irc_bot_pollable_add "struct irc_pollable *pb" +.Ft void .Fn irc_bot_finish "void" .\" DESCRIPTION .Sh DESCRIPTION @@ -114,6 +124,44 @@ .El .Pp The +.Vt irc_pollable +interface is an opaque structure that can be used to insert custom descriptors +into the irccd main loop. +.Pp +All these functions takes as last argument the user data specified in the field +.Va data . +.Pp +Available fields: +.Bl -tag +.It Va data +Opaque user data, can be NULL. +.It Va fd +This function must return the user file descriptor to monitor. +.It Va want +This function must assign to the +.Fa frecv +and +.Fa fsend +arguments if the descriptor has to be selected for read or write condition +respectively. They are set to 0 prior to the invocation. +.It Va sync +This function is called after polling for the file descriptors. The arguments +.Fa frecv +and +.Fa fsend +will be set to 1 if the condition were met similarly to the +.Va want +function. +.Pp +The function must return 0 on success and any other value on error. +.It Va finish +This optional function is called when the pollable is about to be finalized, +this happens when the function +.Va sync +returned -1 or the bot is quitting. +.El +.Pp +The .Fn irc_bot_init function initializes the irccd globals and some of its APIs. This function does not need to be called from plugins. @@ -277,6 +325,15 @@ as first argument. .Pp The +.Fn irc_bot_pollable_add +function inserts the new +.Fa pb +to the list of custom descriptor to monitor in the irccd main's loop. Ownership +is kept to the user and the address of +.Fa pb +must remain valid until it is no longer necessary. +.Pp +The .Fn irc_bot_finish function cleanups any allocated resources. .Pp