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);
+ }
+ }
+ }
+}
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;
+};