lmtp-proxy.c revision 7bd72e4deca3cbf757dd1ea298486d9f3bc24226
/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "istream.h"
#include "istream-tee.h"
#include "ostream.h"
#include "lmtp-client.h"
#include "lmtp-proxy.h"
#define LMTP_MAX_LINE_LEN 1024
struct lmtp_proxy_recipient {
struct lmtp_proxy_connection *conn;
const char *address;
const char *reply;
unsigned int rcpt_to_failed:1;
unsigned int data_reply_received:1;
};
struct lmtp_proxy_connection {
struct lmtp_proxy *proxy;
struct lmtp_proxy_settings set;
struct lmtp_client *client;
struct istream *data_input;
unsigned int failed:1;
};
struct lmtp_proxy {
const char *mail_from, *my_hostname;
unsigned int next_data_reply_idx;
struct ostream *client_output;
struct tee_istream *tee_data_input;
unsigned int max_timeout_msecs;
void *finish_context;
unsigned int finished:1;
unsigned int input_timeout:1;
};
static void lmtp_conn_finish(void *context);
struct lmtp_proxy *
{
struct lmtp_proxy *proxy;
return proxy;
}
{
struct lmtp_proxy_connection *const *conns;
}
}
{
}
{
}
static struct lmtp_proxy_connection *
const struct lmtp_proxy_settings *set)
{
return conn;
}
return conn;
}
{
const struct lmtp_proxy_recipient *rcpt;
unsigned int i, count;
break;
}
proxy->next_data_reply_idx = i;
return i == count;
}
{
}
{
if (lmtp_proxy_send_data_replies(proxy) &&
}
static void lmtp_conn_finish(void *context)
{
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
const char *line;
for (i = 0; i < count; i++) {
" (%s while waiting for reply to %s)", reason,
break;
}
/* either the whole proxy is destroyed now, or we still have some
DATA input to read. */
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
for (i = 0; i < count; i++) {
" (timeout in DATA input)");
return;
}
}
/* last client failure should have caused the proxy to be destroyed */
i_unreached();
}
static void
{
}
static void
{
}
const struct lmtp_proxy_settings *set)
{
struct lmtp_proxy_connection *conn;
struct lmtp_proxy_recipient *rcpt;
return -1;
return 0;
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
for (i = 0; i < count; i++) {
continue;
}
return max_size;
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
if (max_size == 0)
return FALSE;
/* disconnect all connections that are keeping us from reading
more input. */
for (i = 0; i < count; i++) {
continue;
" (DATA output timeout)");
}
}
return TRUE;
}
{
/* drop the connection with the most unread data */
else {
/* no such connection, so we've already sent everything but
some servers aren't replying to us. disconnect all of
them. */
}
}
{
}
{
case 0:
/* nothing new read */
return FALSE;
return FALSE;
}
/* fall through */
case -2:
/* buffer full. someone's stalling. */
return FALSE;
case -1:
else {
/* finished reading data input. now we'll just have to
wait for replies. */
/* if all RCPT TOs failed, we can finish now */
}
return FALSE;
default:
/* something was read */
return TRUE;
}
}
{
struct lmtp_proxy_connection *const *conns;
do {
} while (lmtp_proxy_data_read(proxy));
}
const char *header,
{
struct lmtp_proxy_connection *const *conns;
conn->data_input =
}
}