summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-04-20 17:07:02 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2009-04-20 17:07:02 +0000
commit40383a8787aa6e0fef512c71f88b737e7d32d665 (patch)
tree3db0b399b070730f47fa42b070a20dda7fdecd00
parentb7e1f9e4dd4578f5cf0c85d2827a5365321c406c (diff)
Rewrite smtp session timeouts; use evtimer_* from event(3) instead
of regularly walking session tree in search of idle clients. Gives the smtp process a chance to become idle. As a bonus, add smtp.sessions.timeout counter to "smtpctl show stats". ok gilles@
-rw-r--r--usr.sbin/smtpd/smtp.c10
-rw-r--r--usr.sbin/smtpd/smtp_session.c72
-rw-r--r--usr.sbin/smtpd/smtpctl.c3
-rw-r--r--usr.sbin/smtpd/smtpd.h5
4 files changed, 41 insertions, 49 deletions
diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c
index 90fee941759..fe8c9cb55f7 100644
--- a/usr.sbin/smtpd/smtp.c
+++ b/usr.sbin/smtpd/smtp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp.c,v 1.34 2009/04/16 15:35:06 jacekm Exp $ */
+/* $OpenBSD: smtp.c,v 1.35 2009/04/20 17:07:01 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -556,7 +556,6 @@ smtp_dispatch_control(int sig, short event, void *p)
s->s_id = queue_generate_id();
s->s_fd = fd[0];
- s->s_tm = time(NULL);
s->s_env = env;
s->s_l = &l;
s->s_msg.flags |= F_MESSAGE_ENQUEUED;
@@ -690,7 +689,6 @@ void
smtp_setup_events(struct smtpd *env)
{
struct listener *l;
- struct timeval tv;
TAILQ_FOREACH(l, &env->sc_listeners, entry) {
log_debug("smtp_setup_events: listen on %s port %d flags 0x%01x"
@@ -705,11 +703,6 @@ smtp_setup_events(struct smtpd *env)
event_add(&l->ev, NULL);
ssl_setup(env, l);
}
-
- evtimer_set(&env->sc_ev, session_timeout, env);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- evtimer_add(&env->sc_ev, &tv);
}
void
@@ -767,7 +760,6 @@ smtp_accept(int fd, short event, void *p)
s->s_id = queue_generate_id();
s->s_fd = s_fd;
- s->s_tm = time(NULL);
s->s_env = l->env;
s->s_l = l;
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index b896ef4a3ed..5ea42d2bae3 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtp_session.c,v 1.67 2009/04/19 12:48:27 jacekm Exp $ */
+/* $OpenBSD: smtp_session.c,v 1.68 2009/04/20 17:07:01 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -40,6 +40,8 @@
#include "smtpd.h"
+struct session_timeout;
+
int session_rfc5321_helo_handler(struct session *, char *);
int session_rfc5321_ehlo_handler(struct session *, char *);
int session_rfc5321_rset_handler(struct session *, char *);
@@ -70,7 +72,9 @@ void session_error(struct bufferevent *, short, void *);
void session_msg_submit(struct session *);
void session_command(struct session *, char *, char *);
int session_set_path(struct path *, char *);
-void session_timeout(int, short, void *);
+void session_set_timeout(struct session *, struct session_timeout *,
+ void (*)(int, short, void *));
+void smtp_timeout(int, short, void *);
void session_cleanup(struct session *);
void session_imsg(struct session *, enum smtp_proc_type,
enum imsg_type, u_int32_t, pid_t, int, void *, u_int16_t);
@@ -90,7 +94,8 @@ struct session_timeout rfc5321_timeouttab[] = {
{ S_RCPT, 300 },
{ S_DATA, 120 },
{ S_DATACONTENT, 180 },
- { S_DONE, 600 }
+ { S_DONE, 600 },
+ { 0, 0 }
};
struct session_cmd {
@@ -730,6 +735,8 @@ session_init(struct listener *l, struct session *s)
{
s->s_state = S_INIT;
+ session_set_timeout(s, rfc5321_timeouttab, smtp_timeout);
+
if ((s->s_bev = bufferevent_new(s->s_fd, session_read, session_write,
session_error, s)) == NULL)
fatalx("session_init: bufferevent_new failed");
@@ -755,7 +762,7 @@ session_read(struct bufferevent *bev, void *p)
size_t nr;
read:
- s->s_tm = time(NULL);
+ session_set_timeout(s, rfc5321_timeouttab, smtp_timeout);
nr = EVBUFFER_LENGTH(bev->input);
line = evbuffer_readline(bev->input);
if (line == NULL) {
@@ -896,6 +903,7 @@ session_destroy(struct session *s)
bufferevent_free(s->s_bev);
}
ssl_session_destroy(s);
+ evtimer_del(&s->s_timeout);
SPLAY_REMOVE(sessiontree, &s->s_env->sc_sessions, s);
bzero(s, sizeof(*s));
@@ -976,46 +984,36 @@ session_set_path(struct path *path, char *line)
}
void
-session_timeout(int fd, short event, void *p)
+session_set_timeout(struct session *s, struct session_timeout *tab,
+ void (*cb)(int, short, void *))
{
- struct smtpd *env = p;
- struct session *sessionp;
- struct session *rmsession;
- struct timeval tv;
- time_t tm;
- u_int8_t i;
-
- tm = time(NULL);
- rmsession = NULL;
- SPLAY_FOREACH(sessionp, sessiontree, &env->sc_sessions) {
-
- if (rmsession != NULL) {
- session_destroy(rmsession);
- rmsession = NULL;
- }
+ struct timeval tv;
- for (i = 0; i < sizeof (rfc5321_timeouttab) /
- sizeof(struct session_timeout); ++i)
- if (rfc5321_timeouttab[i].state == sessionp->s_state)
- break;
+ bzero(&tv, sizeof(tv));
- if (i == sizeof (rfc5321_timeouttab) / sizeof (struct session_timeout)) {
- if (tm - SMTPD_SESSION_TIMEOUT < sessionp->s_tm)
- continue;
- }
- else if (tm - rfc5321_timeouttab[i].timeout < sessionp->s_tm) {
- continue;
+ for (; tab->timeout; tab++)
+ if (s->s_state == tab->state) {
+ tv.tv_sec = tab->timeout;
+ break;
}
+ if (! tab->timeout)
+ tv.tv_sec = SMTPD_SESSION_TIMEOUT;
+ evtimer_set(&s->s_timeout, cb, s);
+ evtimer_add(&s->s_timeout, &tv);
+}
- rmsession = sessionp;
- }
+void
+smtp_timeout(int fd, short event, void *p)
+{
+ struct session *s = p;
- if (rmsession != NULL)
- session_destroy(rmsession);
+ log_debug("smtp_timeout: fd %d at state %d", s->s_fd, s->s_state);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- evtimer_add(&env->sc_ev, &tv);
+ s_smtp.timeout++;
+ if (s->s_flags & F_EVLOCKED)
+ s->s_flags |= F_QUIT;
+ else
+ session_destroy(s);
}
void
diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c
index 22f7dea195c..bcbf31df1ac 100644
--- a/usr.sbin/smtpd/smtpctl.c
+++ b/usr.sbin/smtpd/smtpctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpctl.c,v 1.21 2009/04/16 15:35:06 jacekm Exp $ */
+/* $OpenBSD: smtpctl.c,v 1.22 2009/04/20 17:07:01 jacekm Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -294,6 +294,7 @@ show_stats_output(struct imsg *imsg)
printf("smtp.sessions=%zd\n", s_smtp.sessions);
printf("smtp.sessions.aborted=%zd\n", s_smtp.aborted);
+ printf("smtp.sessions.timeout=%zd\n", s_smtp.timeout);
printf("smtp.sessions.active=%zd\n", s_smtp.sessions_active);
printf("smtp.sessions.smtps=%zd\n", s_smtp.smtps);
printf("smtp.sessions.smtps.active=%zd\n", s_smtp.smtps_active);
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 99c6bca3455..a556f079519 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: smtpd.h,v 1.99 2009/04/16 15:35:06 jacekm Exp $ */
+/* $OpenBSD: smtpd.h,v 1.100 2009/04/20 17:07:01 jacekm Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
@@ -587,12 +587,12 @@ struct session {
enum session_flags s_flags;
enum session_state s_state;
- time_t s_tm;
int s_fd;
struct sockaddr_storage s_ss;
char s_hostname[MAXHOSTNAMELEN];
struct event s_ev;
struct bufferevent *s_bev;
+ struct event s_timeout;
struct listener *s_l;
struct smtpd *s_env;
void *s_ssl;
@@ -668,6 +668,7 @@ struct s_session {
size_t starttls_active;
size_t aborted;
+ size_t timeout;
};
struct stats {