client.c revision 2b1d4aea1ab37aae26059dc2d529451debb93936
/* Copyright (C) 2002 Timo Sirainen */
#include "common.h"
#include "base64.h"
#include "buffer.h"
#include "hash.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "randgen.h"
#include "process-title.h"
#include "safe-memset.h"
#include "strescape.h"
#include "client.h"
#include "client-authenticate.h"
#include "auth-client.h"
#include "ssl-proxy.h"
#include "pop3-proxy.h"
#include "hostpid.h"
/* max. length of input command line (spec says 512), or max reply length in
SASL authentication */
#define MAX_INBUF_SIZE 4096
/* max. size of output buffer. if it gets full, the client is disconnected.
SASL authentication gives the largest output. */
#define MAX_OUTBUF_SIZE 4096
/* Disconnect client after idling this many seconds */
#define CLIENT_LOGIN_IDLE_TIMEOUT 60
/* Disconnect client when it sends too many bad commands */
#define CLIENT_MAX_BAD_COMMANDS 10
/* When max. number of simultaneous connections is reached, few of the
oldest connections are disconnected. Since we have to go through the whole
client hash, it's faster if we disconnect multiple clients. */
#define CLIENT_DESTROY_OLDEST_COUNT 16
#endif
const char *login_protocol = "POP3";
static struct hash_table *clients;
{
const char *addr;
if (!verbose_proctitle || !process_per_connection)
return;
addr = "??";
}
{
}
{
int fd_ssl;
if (fd_ssl == -1) {
return;
}
}
static int client_output_starttls(void *context)
{
int ret;
return 1;
}
if (ret > 0) {
}
return 1;
}
{
return TRUE;
}
if (!ssl_initialized) {
return TRUE;
}
/* remove input handler, SSL proxy gives us a new fd. we also have to
remove it in case we have to wait for buffer to be flushed */
/* uncork the old fd */
/* the buffer has to be flushed */
} else {
}
return TRUE;
}
{
return TRUE;
}
const char *args)
{
return FALSE;
}
{
case -2:
/* buffer full */
return FALSE;
case -1:
/* disconnected */
return FALSE;
default:
/* something was read */
return TRUE;
}
}
void client_input(void *context)
{
if (!client_read(client))
return;
args = "";
else
*args++ = '\0';
client->bad_counter = 0;
"Disconnected: Too many bad commands");
}
}
if (client_unref(client))
}
static void client_destroy_oldest(void)
{
struct hash_iterate_context *iter;
int i;
/* find the oldest clients and put them to destroy-buffer */
for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
if (destroy_buf[i] == NULL ||
/* @UNSAFE */
sizeof(destroy_buf) -
(i+1) * sizeof(struct pop3_client *));
destroy_buf[i] = client;
break;
}
}
}
/* then kill them */
for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
if (destroy_buf[i] == NULL)
break;
"Disconnected: Connection queue full");
}
}
{
unsigned char buffer[16];
char *ret;
return NULL;
t_push();
(unsigned long)ioloop_time,
t_pop();
return ret;
}
{
}
{
struct pop3_client *client;
const char *addr;
/* reached max. users count, kill few of the
oldest connections */
}
/* always use nonblocking I/O */
main_ref();
if (client->auth_connected)
}
{
return;
}
}
}
}
}
{
"Refer to server log for more information.");
}
{
}
{
return TRUE;
main_unref();
return FALSE;
}
{
/* either disconnection or buffer full. in either case we
want this connection destroyed. however destroying it here
might break things if client is still tried to be accessed
without being referenced.. */
}
}
{
}
{
struct hash_iterate_context *iter;
}
}
unsigned int clients_get_count(void)
{
}
void clients_notify_auth_connected(void)
{
struct hash_iterate_context *iter;
if (!client->auth_connected) {
}
}
}
void clients_destroy_all(void)
{
struct hash_iterate_context *iter;
}
}
void clients_init(void)
{
}
void clients_deinit(void)
{
}