diff options
Diffstat (limited to 'smtpd/scheduler_proc.c')
-rw-r--r-- | smtpd/scheduler_proc.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/smtpd/scheduler_proc.c b/smtpd/scheduler_proc.c new file mode 100644 index 00000000..5f4e8b70 --- /dev/null +++ b/smtpd/scheduler_proc.c @@ -0,0 +1,446 @@ +/* $OpenBSD: scheduler_proc.c,v 1.8 2015/12/05 13:14:21 claudio Exp $ */ + +/* + * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/tree.h> +#include <sys/socket.h> + +#include <ctype.h> +#include <errno.h> +#include <event.h> +#include <fcntl.h> +#include <imsg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include "smtpd.h" +#include "log.h" + +static struct imsgbuf ibuf; +static struct imsg imsg; +static size_t rlen; +static char *rdata; + +static void +scheduler_proc_call(void) +{ + ssize_t n; + + if (imsg_flush(&ibuf) == -1) { + log_warn("warn: scheduler-proc: imsg_flush"); + fatalx("scheduler-proc: exiting"); + } + + while (1) { + if ((n = imsg_get(&ibuf, &imsg)) == -1) { + log_warn("warn: scheduler-proc: imsg_get"); + break; + } + if (n) { + rlen = imsg.hdr.len - IMSG_HEADER_SIZE; + rdata = imsg.data; + + if (imsg.hdr.type != PROC_SCHEDULER_OK) { + log_warnx("warn: scheduler-proc: bad response"); + break; + } + return; + } + + if ((n = imsg_read(&ibuf)) == -1 && errno != EAGAIN) { + log_warn("warn: scheduler-proc: imsg_read"); + break; + } + + if (n == 0) { + log_warnx("warn: scheduler-proc: pipe closed"); + break; + } + } + + fatalx("scheduler-proc: exiting"); +} + +static void +scheduler_proc_read(void *dst, size_t len) +{ + if (len > rlen) { + log_warnx("warn: scheduler-proc: bad msg len"); + fatalx("scheduler-proc: exiting"); + } + + memmove(dst, rdata, len); + rlen -= len; + rdata += len; +} + +static void +scheduler_proc_end(void) +{ + if (rlen) { + log_warnx("warn: scheduler-proc: bogus data"); + fatalx("scheduler-proc: exiting"); + } + imsg_free(&imsg); +} + +/* + * API + */ + +static int +scheduler_proc_init(const char *conf) +{ + int fd, r; + uint32_t version; + + fd = fork_proc_backend("scheduler", conf, "scheduler-proc"); + if (fd == -1) + fatalx("scheduler-proc: exiting"); + + imsg_init(&ibuf, fd); + + version = PROC_SCHEDULER_API_VERSION; + imsg_compose(&ibuf, PROC_SCHEDULER_INIT, 0, 0, -1, + &version, sizeof(version)); + scheduler_proc_call(); + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (1); +} + +static int +scheduler_proc_insert(struct scheduler_info *si) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_INSERT"); + + imsg_compose(&ibuf, PROC_SCHEDULER_INSERT, 0, 0, -1, si, sizeof(*si)); + + scheduler_proc_call(); + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static size_t +scheduler_proc_commit(uint32_t msgid) +{ + size_t s; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_COMMIT"); + + imsg_compose(&ibuf, PROC_SCHEDULER_COMMIT, 0, 0, -1, + &msgid, sizeof(msgid)); + + scheduler_proc_call(); + scheduler_proc_read(&s, sizeof(s)); + scheduler_proc_end(); + + return (s); +} + +static size_t +scheduler_proc_rollback(uint32_t msgid) +{ + size_t s; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_ROLLBACK"); + + imsg_compose(&ibuf, PROC_SCHEDULER_ROLLBACK, 0, 0, -1, + &msgid, sizeof(msgid)); + + scheduler_proc_call(); + scheduler_proc_read(&s, sizeof(s)); + scheduler_proc_end(); + + return (s); +} + +static int +scheduler_proc_update(struct scheduler_info *si) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_UPDATE"); + + imsg_compose(&ibuf, PROC_SCHEDULER_UPDATE, 0, 0, -1, si, sizeof(*si)); + + scheduler_proc_call(); + scheduler_proc_read(&r, sizeof(r)); + if (r == 1) + scheduler_proc_read(si, sizeof(*si)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_delete(uint64_t evpid) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_DELETE"); + + imsg_compose(&ibuf, PROC_SCHEDULER_DELETE, 0, 0, -1, + &evpid, sizeof(evpid)); + + scheduler_proc_call(); + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_hold(uint64_t evpid, uint64_t holdq) +{ + struct ibuf *buf; + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_HOLD"); + + buf = imsg_create(&ibuf, PROC_SCHEDULER_HOLD, 0, 0, + sizeof(evpid) + sizeof(holdq)); + if (buf == NULL) + return (-1); + if (imsg_add(buf, &evpid, sizeof(evpid)) == -1) + return (-1); + if (imsg_add(buf, &holdq, sizeof(holdq)) == -1) + return (-1); + imsg_close(&ibuf, buf); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_release(int type, uint64_t holdq, int n) +{ + struct ibuf *buf; + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_RELEASE"); + + buf = imsg_create(&ibuf, PROC_SCHEDULER_RELEASE, 0, 0, + sizeof(holdq) + sizeof(n)); + if (buf == NULL) + return (-1); + if (imsg_add(buf, &type, sizeof(type)) == -1) + return (-1); + if (imsg_add(buf, &holdq, sizeof(holdq)) == -1) + return (-1); + if (imsg_add(buf, &n, sizeof(n)) == -1) + return (-1); + imsg_close(&ibuf, buf); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_batch(int typemask, int *delay, size_t *count, uint64_t *evpids, int *types) +{ + struct ibuf *buf; + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_BATCH"); + + buf = imsg_create(&ibuf, PROC_SCHEDULER_BATCH, 0, 0, + sizeof(typemask) + sizeof(*count)); + if (buf == NULL) + return (-1); + if (imsg_add(buf, &typemask, sizeof(typemask)) == -1) + return (-1); + if (imsg_add(buf, count, sizeof(*count)) == -1) + return (-1); + imsg_close(&ibuf, buf); + + scheduler_proc_call(); + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_read(delay, sizeof(*delay)); + scheduler_proc_read(count, sizeof(*count)); + if (r > 0) { + scheduler_proc_read(evpids, sizeof(*evpids) * (*count)); + scheduler_proc_read(types, sizeof(*types) * (*count)); + } + scheduler_proc_end(); + + return (r); +} + +static size_t +scheduler_proc_messages(uint32_t from, uint32_t *dst, size_t size) +{ + struct ibuf *buf; + size_t s; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_MESSAGES"); + + buf = imsg_create(&ibuf, PROC_SCHEDULER_MESSAGES, 0, 0, + sizeof(from) + sizeof(size)); + if (buf == NULL) + return (-1); + if (imsg_add(buf, &from, sizeof(from)) == -1) + return (-1); + if (imsg_add(buf, &size, sizeof(size)) == -1) + return (-1); + imsg_close(&ibuf, buf); + + scheduler_proc_call(); + + s = rlen / sizeof(*dst); + scheduler_proc_read(dst, s * sizeof(*dst)); + scheduler_proc_end(); + + return (s); +} + +static size_t +scheduler_proc_envelopes(uint64_t from, struct evpstate *dst, size_t size) +{ + struct ibuf *buf; + size_t s; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_ENVELOPES"); + + buf = imsg_create(&ibuf, PROC_SCHEDULER_ENVELOPES, 0, 0, + sizeof(from) + sizeof(size)); + if (buf == NULL) + return (-1); + if (imsg_add(buf, &from, sizeof(from)) == -1) + return (-1); + if (imsg_add(buf, &size, sizeof(size)) == -1) + return (-1); + imsg_close(&ibuf, buf); + + scheduler_proc_call(); + + s = rlen / sizeof(*dst); + scheduler_proc_read(dst, s * sizeof(*dst)); + scheduler_proc_end(); + + return (s); +} + +static int +scheduler_proc_schedule(uint64_t evpid) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_SCHEDULE"); + + imsg_compose(&ibuf, PROC_SCHEDULER_SCHEDULE, 0, 0, -1, + &evpid, sizeof(evpid)); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_remove(uint64_t evpid) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_REMOVE"); + + imsg_compose(&ibuf, PROC_SCHEDULER_REMOVE, 0, 0, -1, + &evpid, sizeof(evpid)); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_suspend(uint64_t evpid) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_SUSPEND"); + + imsg_compose(&ibuf, PROC_SCHEDULER_SUSPEND, 0, 0, -1, + &evpid, sizeof(evpid)); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +static int +scheduler_proc_resume(uint64_t evpid) +{ + int r; + + log_debug("debug: scheduler-proc: PROC_SCHEDULER_RESUME"); + + imsg_compose(&ibuf, PROC_SCHEDULER_RESUME, 0, 0, -1, + &evpid, sizeof(evpid)); + + scheduler_proc_call(); + + scheduler_proc_read(&r, sizeof(r)); + scheduler_proc_end(); + + return (r); +} + +struct scheduler_backend scheduler_backend_proc = { + scheduler_proc_init, + scheduler_proc_insert, + scheduler_proc_commit, + scheduler_proc_rollback, + scheduler_proc_update, + scheduler_proc_delete, + scheduler_proc_hold, + scheduler_proc_release, + scheduler_proc_batch, + scheduler_proc_messages, + scheduler_proc_envelopes, + scheduler_proc_schedule, + scheduler_proc_remove, + scheduler_proc_suspend, + scheduler_proc_resume, +}; |