From 854196b9645097bac7dc806d1a3a08c1ef379a3b Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 1 Oct 2004 20:20:41 +0000 Subject: Send NOOPs to the server during slow connections to prevent timeouts. Bug #134 --- common/smtppass.c | 21 ++++++++++++++++++++- common/smtppass.h | 2 ++ common/spio.c | 10 ++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/smtppass.c b/common/smtppass.c index dc1cf77..8b71f4d 100644 --- a/common/smtppass.c +++ b/common/smtppass.c @@ -78,7 +78,7 @@ typedef struct spthread spthread_t; /* ----------------------------------------------------------------------- - * STRINGS + * DATA */ #define CRLF "\r\n" @@ -93,6 +93,7 @@ spthread_t; #define SMTP_REJPREFIX "550 Content Rejected; " #define SMTP_DATA "DATA" CRLF +#define SMTP_NOOP "NOOP" CRLF #define SMTP_BANNER "220 smtp.passthru" CRLF #define SMTP_HELO_RSP "250 smtp.passthru" CRLF #define SMTP_EHLO_RSP "250-smtp.passthru" CRLF @@ -126,6 +127,9 @@ spthread_t; #define LINE_TOO_LONG(l) ((l) >= (SP_LINE_LENGTH - 2)) +/* The amount interval at which to send NOOPS to server */ +#define INTERACTION_DELTA 10 + /* ----------------------------------------------------------------------- * CONFIGURATION OPTIONS * @@ -179,6 +183,7 @@ static int read_server_response(spctx_t* ctx); static int parse_config_file(const char* configfile); static char* parse_address(char* line); static const char* get_successful_rsp(const char* line, int* cont); +static void do_server_noop(spctx_t* ctx); /* Used externally in some cases */ int sp_parse_option(const char* name, const char* option); @@ -1123,6 +1128,14 @@ int sp_read_data(spctx_t* ctx, const char** data) return -1; }; + /* + * During this time we're just reading from the client. If we haven't + * had any interaction with the server recently then send something + * to let it know we're still around. + */ + if((ctx->server.last_action + INTERACTION_DELTA) < time(NULL)) + do_server_noop(ctx); + if(ctx->_crlf && strcmp(ctx->client.line, DATA_END_SIG) == 0) return 0; @@ -1373,6 +1386,12 @@ static int read_server_response(spctx_t* ctx) return 0; } +static void do_server_noop(spctx_t* ctx) +{ + if(spio_write_data(ctx, &(ctx->server), SMTP_NOOP) != -1) + spio_read_line(ctx, &(ctx->server), SPIO_DISCARD); +} + void sp_setup_forked(spctx_t* ctx, int file) { /* Signals we've messed with */ diff --git a/common/smtppass.h b/common/smtppass.h index aebace1..e7fc780 100644 --- a/common/smtppass.h +++ b/common/smtppass.h @@ -66,6 +66,7 @@ typedef struct spio { int fd; /* The file descriptor wrapped */ const char* name; /* The name for logging */ + time_t last_action; /* Time of last action on descriptor */ /* Internal use only */ char line[SP_LINE_LENGTH]; @@ -124,6 +125,7 @@ typedef struct spctx int _crlf; /* Private data */ char _l1[SP_LINE_LENGTH]; char _l2[SP_LINE_LENGTH]; + time_t _tm; } spctx_t; diff --git a/common/spio.c b/common/spio.c index 67d32b1..4075e9a 100644 --- a/common/spio.c +++ b/common/spio.c @@ -245,6 +245,9 @@ unsigned int spio_select(spctx_t* ctx, ...) if(i > (sizeof(int) * 8) - 2) break; + /* We have data on the descriptor, which is an action */ + io->last_action = time(NULL); + /* Check if the buffer has something in it */ if(FD_ISSET(io->fd, &mask)) ret |= (1 << i); @@ -363,6 +366,9 @@ int read_raw(spctx_t* ctx, spio_t* io, int opts) return count; } + /* Read data which is a descriptor action */ + io->last_action = time(NULL); + /* Check for a new line */ p = (char*)memchr(at, '\n', x); if(p != NULL) @@ -489,6 +495,8 @@ int spio_write_data_raw(spctx_t* ctx, spio_t* io, unsigned char* buf, int len) if(io->fd == -1) return 0; + io->last_action = time(NULL); + while(len > 0) { r = write(io->fd, buf, len); @@ -556,6 +564,8 @@ void spio_read_junk(spctx_t* ctx, spio_t* io) if(l <= 0) break; + io->last_action = time(NULL); + buf[l] = 0; t = trim_start(buf); -- cgit v1.2.3