summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/smtppass.c21
-rw-r--r--common/smtppass.h2
-rw-r--r--common/spio.c10
3 files changed, 32 insertions, 1 deletions
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);