From: chris mikkelson Date: Thu, 15 Apr 2010 21:02:33 +0000 (-0500) Subject: Added inter-module communication "channels" API. Modules can X-Git-Url: https://git.mikk.net/?a=commitdiff_plain;h=993804158efc5e88cbc79c5d78d43aed11b8fcf6;p=smtpsink Added inter-module communication "channels" API. Modules can register callbacks to named channels with ssm_subscribe() and publish to named channels with ssm_publish(). --- diff --git a/module_api.c b/module_api.c index e050374..a2dcd1d 100644 --- a/module_api.c +++ b/module_api.c @@ -73,3 +73,79 @@ ssm_setpriv(struct smtpsink_module *m, struct conn *c, void *data) assert(c->priv_data); c->priv_data[m->ssm_module_index] = data; } + +struct sub { + void (*cb)(struct conn *, void *); + SLIST_ENTRY(sub) sub_list; +}; + +struct channel { + const char *name; + unsigned np; + SLIST_ENTRY(channel) chan_list; + SLIST_HEAD(,sub) subscribers; +}; + +SLIST_HEAD(,channel) channels = SLIST_HEAD_INITIALIZER(channels); + +void +ssm_subscribe(const char *chan, void (*cb)(struct conn *, void *)) +{ + struct sub *s = malloc(sizeof(struct sub)); + struct channel *ch; + + s->cb = cb; + SLIST_FOREACH(ch, &channels, chan_list) { + if (!strcmp(ch->name, chan)) { + SLIST_INSERT_HEAD(&ch->subscribers, s, sub_list); + return; + } + } + ch = malloc(sizeof(struct channel)); + ch->name = chan; + SLIST_INIT(&ch->subscribers); + SLIST_INSERT_HEAD(&ch->subscribers, s, sub_list); + SLIST_INSERT_HEAD(&channels, ch, chan_list); +} + +int +ssm_nproviders(const char *chan) +{ + struct channel *ch; + SLIST_FOREACH(ch, &channels, chan_list) { + if (!strcmp(ch->name, chan)) + return ch->np; + } + return 0; +} + +void +ssm_provide(const char *chan) +{ + struct channel *ch; + SLIST_FOREACH(ch, &channels, chan_list) { + if (!strcmp(ch->name, chan)) { + ch->np++; + return; + } + } + ch = malloc(sizeof(struct channel)); + ch->name = chan; + ch->np = 1; + SLIST_INIT(&ch->subscribers); + SLIST_INSERT_HEAD(&channels, ch, chan_list); +} + +void +ssm_publish(const char *chan, struct conn *c, void *data) +{ + struct sub *s; + struct channel *ch; + SLIST_FOREACH(ch, &channels, chan_list) { + if (!strcmp(ch->name, chan)) { + SLIST_FOREACH(s, &ch->subscribers, sub_list) { + s->cb(c, data); + } + } + } +} diff --git a/smtpsink.h b/smtpsink.h index a0302f6..11bb671 100644 --- a/smtpsink.h +++ b/smtpsink.h @@ -88,3 +88,14 @@ struct smtpsink_module { void *ssm_getpriv(struct smtpsink_module *, struct conn *); void ssm_setpriv(struct smtpsink_module *, struct conn *, void *); + +/* inter-module communication */ +int ssm_nproviders(const char *); +void ssm_provide(const char *); +void ssm_publish(const char *, struct conn *, void *); +void ssm_subscribe(const char *, void (*)(struct conn *, void *)); + +struct message_body { + char *body; + size_t blen; +};