int queue_envelope_load(uint64_t evpid, struct envelope *ep) { const char *e; char evpbuf[sizeof(struct envelope)]; size_t evplen; struct envelope *cached; if ((env->sc_queue_flags & QUEUE_EVPCACHE) && (cached = tree_get(&evpcache_tree, evpid))) { *ep = *cached; stat_increment("queue.evpcache.load.hit", 1); return (1); } ep->id = evpid; profile_enter("queue_envelope_load"); evplen = handler_envelope_load(ep->id, evpbuf, sizeof evpbuf); profile_leave(); log_trace(TRACE_QUEUE, "queue-backend: queue_envelope_load(%016"PRIx64") -> %zu", evpid, evplen); if (evplen == 0) return (0); if (queue_envelope_load_buffer(ep, evpbuf, evplen)) { if ((e = envelope_validate(ep)) == NULL) { ep->id = evpid; if (env->sc_queue_flags & QUEUE_EVPCACHE) { queue_envelope_cache_add(ep); stat_increment("queue.evpcache.load.missed", 1); } return (1); } log_debug("debug: invalid envelope %016" PRIx64 ": %s", ep->id, e); } (void)queue_message_corrupt(evpid_to_msgid(evpid)); return (0); }
static void queue_msg_dispatch(void) { uint64_t evpid; uint32_t msgid, version; size_t n; char buffer[8192], path[SMTPD_MAXPATHLEN]; int r, fd; FILE *ifile, *ofile; switch (imsg.hdr.type) { case PROC_QUEUE_INIT: queue_msg_get(&version, sizeof(version)); queue_msg_end(); if (version != PROC_QUEUE_API_VERSION) { log_warnx("warn: queue-api: bad API version"); fatalx("queue-api: exiting"); } imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, NULL, 0); break; case PROC_QUEUE_MESSAGE_CREATE: queue_msg_end(); r = handler_message_create(&msgid); queue_msg_add(&r, sizeof(r)); if (r == 1) queue_msg_add(&msgid, sizeof(msgid)); queue_msg_close(); break; case PROC_QUEUE_MESSAGE_DELETE: queue_msg_get(&msgid, sizeof(msgid)); queue_msg_end(); r = handler_message_delete(msgid); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, &r, sizeof(r)); break; case PROC_QUEUE_MESSAGE_COMMIT: queue_msg_get(&msgid, sizeof(msgid)); queue_msg_end(); /* XXX needs more love */ r = -1; fd = mkstemp(path); if (fd == -1) { log_warn("warn: queue-api: mkstemp"); } else { ifile = fdopen(imsg.fd, "r"); ofile = fdopen(fd, "w"); if (ifile && ofile) { while (!feof(ifile)) { n = fread(buffer, 1, sizeof(buffer), ifile); fwrite(buffer, 1, n, ofile); } r = handler_message_commit(msgid, path); } if (ifile) fclose(ifile); if (ofile) fclose(ofile); } imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, &r, sizeof(r)); break; case PROC_QUEUE_MESSAGE_FD_R: queue_msg_get(&msgid, sizeof(msgid)); queue_msg_end(); fd = handler_message_fd_r(msgid); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, fd, NULL, 0); break; case PROC_QUEUE_MESSAGE_CORRUPT: queue_msg_get(&msgid, sizeof(msgid)); queue_msg_end(); r = handler_message_corrupt(msgid); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, &r, sizeof(r)); break; case PROC_QUEUE_ENVELOPE_CREATE: queue_msg_get(&msgid, sizeof(msgid)); r = handler_envelope_create(msgid, rdata, rlen, &evpid); queue_msg_get(NULL, rlen); queue_msg_end(); queue_msg_add(&r, sizeof(r)); if (r == 1) queue_msg_add(&evpid, sizeof(evpid)); queue_msg_close(); break; case PROC_QUEUE_ENVELOPE_DELETE: queue_msg_get(&evpid, sizeof(evpid)); queue_msg_end(); r = handler_envelope_delete(evpid); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, &r, sizeof(r)); break; case PROC_QUEUE_ENVELOPE_LOAD: queue_msg_get(&evpid, sizeof(evpid)); queue_msg_end(); r = handler_envelope_load(evpid, buffer, sizeof(buffer)); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, buffer, r); break; case PROC_QUEUE_ENVELOPE_UPDATE: queue_msg_get(&evpid, sizeof(evpid)); r = handler_envelope_update(evpid, rdata, rlen); queue_msg_get(NULL, rlen); queue_msg_end(); imsg_compose(&ibuf, PROC_QUEUE_OK, 0, 0, -1, &r, sizeof(r)); break; case PROC_QUEUE_ENVELOPE_WALK: queue_msg_end(); r = handler_envelope_walk(&evpid, buffer, sizeof(buffer)); queue_msg_add(&r, sizeof(r)); if (r > 0) { queue_msg_add(&evpid, sizeof(evpid)); queue_msg_add(buffer, r); } queue_msg_close(); default: log_warnx("warn: queue-api: bad message %i", imsg.hdr.type); fatalx("queue-api: exiting"); } }