Пример #1
0
static void
filter_io_in(struct io *io, int evt)
{
	struct filter_session	*s = io->arg;
	char			*line;
	size_t			 len;

	log_trace(TRACE_FILTERS, "filter-api:%s filter_io_in(%p, %s)",
	    filter_name, s, io_strevent(evt));

	switch (evt) {
	case IO_DATAIN:
	    nextline:
		line = iobuf_getline(&s->pipe.ibuf, &len);
		if ((line == NULL && iobuf_len(&s->pipe.ibuf) >= LINE_MAX) ||
		    (line && len >= LINE_MAX)) {
			s->pipe.error = 1;
			break;
		}
		/* No complete line received */
		if (line == NULL) {
			iobuf_normalize(&s->pipe.ibuf);
			/* flow control */
			if (iobuf_queued(&s->pipe.obuf) >= FILTER_HIWAT)
				io_pause(&s->pipe.iev, IO_PAUSE_IN);
			return;
		}

		s->pipe.idatalen += len + 1;
		/* XXX warning: do not clear io from this call! */
		filter_dispatch_dataline(s->id, line);
		goto nextline;

	case IO_DISCONNECTED:
		if (iobuf_len(&s->pipe.ibuf)) {
			log_warn("warn: filter-api:%s %016"PRIx64" incomplete input",
			    filter_name, s->id);
		}
		log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" input done (%zu bytes)",
		    filter_name, s->id, s->pipe.idatalen);
		break;

	default:
		log_warn("warn: filter-api:%s %016"PRIx64": unexpected io event %d on data pipe",
		    filter_name, s->id, evt);
		s->pipe.error = 1;

	}
	if (s->pipe.error) {
		io_clear(&s->pipe.oev);
		iobuf_clear(&s->pipe.obuf);
	}
	io_clear(&s->pipe.iev);
	iobuf_clear(&s->pipe.ibuf);
	filter_trigger_eom(s);
}
Пример #2
0
static void
filter_dispatch(struct mproc *p, struct imsg *imsg)
{
	struct filter_connect	 q_connect;
	struct mailaddr		 maddr;
	struct msg		 m;
	const char		*line;
	uint32_t		 v;
	uint64_t		 id, qid;
	int			 status, event, hook;

	log_debug("debug: %s: imsg %i", filter_name, imsg->hdr.type);

	switch (imsg->hdr.type) {
	case IMSG_FILTER_REGISTER:
		m_msg(&m, imsg);
		m_get_u32(&m, &v);
		m_end(&m);
		if (v != FILTER_API_VERSION)
			errx(1, "API version mismatch");
		m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1);
		m_add_int(p, fi.hooks);
		m_add_int(p, fi.flags);
		m_close(p);
		break;

	case IMSG_FILTER_EVENT:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_int(&m, &event);
		m_end(&m);
		filter_dispatch_event(id, event);
		break;

	case IMSG_FILTER_QUERY:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_id(&m, &qid);
		m_get_int(&m, &hook);
		tree_xset(&queries, qid, NULL);
		switch(hook) {
		case HOOK_CONNECT:
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.local);
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.remote);
			m_get_string(&m, &q_connect.hostname);
			m_end(&m);
			filter_dispatch_connect(id, qid, &q_connect);
			break;
		case HOOK_HELO:
			m_get_string(&m, &line);
			m_end(&m);
			filter_dispatch_helo(id, qid, line);
			break;
		case HOOK_MAIL:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_dispatch_mail(id, qid, &maddr);
			break;
		case HOOK_RCPT:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_dispatch_rcpt(id, qid, &maddr);
			break;
		case HOOK_DATA:
			m_end(&m);
			filter_dispatch_data(id, qid);
			break;
		case HOOK_EOM:
			m_end(&m);
			filter_dispatch_eom(id, qid);
			break;
		default:
			errx(1, "bad query hook: %d", hook);
		}
		break;

	case IMSG_FILTER_NOTIFY:
		m_msg(&m, imsg);
		m_get_id(&m, &qid);
		m_get_int(&m, &status);
		m_end(&m);
		filter_dispatch_notify(qid, status);
		break;

	case IMSG_FILTER_DATA:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_string(&m, &line);
		m_end(&m);
		filter_dispatch_dataline(id, line);
		break;
	}
}