lmtp-proxy.c revision 2a9bb54dc4e7bb031dd08c6a161bae7cc1377ee0
/* 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;
/* points to proxy->rcpt_to array. */
unsigned int rcpt_next_reply_low_idx;
unsigned int data_next_reply_low_idx;
struct lmtp_client *client;
struct istream *data_input;
unsigned int failed:1;
};
struct lmtp_proxy {
const char *mail_from, *my_hostname;
unsigned int rcpt_next_reply_idx;
struct istream *data_input;
struct ostream *client_output;
struct tee_istream *tee_data_input;
unsigned int max_timeout_msecs;
void (*finish_callback)(void *);
void *finish_context;
unsigned int finished:1;
};
const char *reason);
struct lmtp_proxy *
{
struct lmtp_proxy *proxy;
return proxy;
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
for (i = 0; i < count; i++)
}
{
}
{
}
static struct lmtp_proxy_connection *
const struct lmtp_proxy_settings *set)
{
unsigned int i, count;
for (i = 0; i < count; i++) {
return conns[i];
}
return conn;
}
const char *reason)
{
struct lmtp_proxy_recipient *rcpt;
/* set failure replies to all recipients in this connection */
}
}
{
const struct lmtp_proxy_recipient *rcpt;
unsigned int i, count;
break;
}
proxy->rcpt_next_reply_idx = i;
return i == count;
}
{
}
{
}
{
struct lmtp_proxy_recipient *rcpt;
unsigned int i, count;
bool ret;
if (!rcpt[i].rcpt_to_failed) {
}
}
}
{
}
{
}
static void
{
struct lmtp_proxy_recipient *rcpt;
unsigned int i, count;
break;
}
}
/* send replies only if we've already sent DATA. */
}
static void
{
struct lmtp_proxy_recipient *rcpt;
unsigned int i, count;
break;
}
}
}
const struct lmtp_proxy_settings *set)
{
struct lmtp_proxy_connection *conn;
struct lmtp_proxy_recipient *rcpt;
return -1;
return 0;
}
{
unsigned int i, count;
/* drop the connection with the most unread data */
for (i = 0; i < count; i++) {
}
}
" (timeout)");
}
{
}
}
{
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;
case 0:
/* nothing new read */
}
return FALSE;
default:
/* something was read */
return TRUE;
}
}
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
do {
for (i = 0; i < count; i++)
} while (lmtp_proxy_data_read(proxy));
}
const char *header,
void (*finish_callback)(void *), void *context)
{
struct lmtp_proxy_connection *const *conns;
unsigned int i, count;
for (i = 0; i < count; i++) {
conns[i]->data_input =
}
}