client.c revision 5bc0ddc263fc56dcbc5ccf53a7368da7611cf8de
/* Copyright (C) 2002 Timo Sirainen */
#include "common.h"
#include "buffer.h"
#include "hash.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "process-title.h"
#include "safe-memset.h"
#include "strescape.h"
#include "imap-parser.h"
#include "client.h"
#include "client-authenticate.h"
#include "auth-connection.h"
#include "ssl-proxy.h"
/* max. size of one parameter in line */
#define MAX_INBUF_SIZE 512
#define MAX_OUTBUF_SIZE 1024
/* max. number of IMAP argument elements to accept. The maximum memory usage
for command from user is around MAX_INBUF_SIZE * MAX_IMAP_ARG_ELEMENTS */
#define MAX_IMAP_ARG_ELEMENTS 4
/* 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
static struct hash_table *clients;
{
const char *host;
if (!verbose_proctitle || !process_per_connection)
return;
host = "??";
host));
}
{
}
/* Skip incoming data until newline is found,
returns TRUE if newline was found. */
{
const unsigned char *data;
for (i = 0; i < data_size; i++) {
if (data[i] == '\n') {
return TRUE;
}
}
return FALSE;
}
{
const char *capability, *auths;
return TRUE;
}
{
int fd_ssl;
return TRUE;
}
if (!ssl_initialized) {
return TRUE;
}
/* must be removed before ssl_proxy_new(), since it may
io_add() the same fd. */
}
if (fd_ssl != -1) {
/* we skipped it already, so don't ignore next command */
} else {
}
return TRUE;
}
{
return TRUE;
}
{
return TRUE;
}
{
return cmd_capability(client);
return cmd_starttls(client);
return cmd_logout(client);
return FALSE;
}
{
if (client->authenticating)
return FALSE; /* wait until authentication is finished */
if (client->cmd_finished) {
/* clear the previous command from memory. don't do this
immediately after handling command since we need the
cmd_tag to stay some time after authentication commands. */
/* remove \r\n */
if (!client_skip_line(client))
return TRUE;
}
}
return FALSE; /* need more data */
}
return FALSE; /* need more data */
}
case -1:
/* error */
return TRUE;
case -2:
/* not enough data */
return FALSE;
}
"* BYE Too many invalid IMAP commands.");
"Too many invalid commands");
return FALSE;
}
"BAD Error in IMAP command received by server.");
}
return TRUE;
}
{
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;
if (!auth_is_connected()) {
/* we're not yet connected to auth process -
don't allow any commands */
"* OK Waiting for authentication process to respond..");
return;
}
while (client_handle_input(client)) ;
if (client_unref(client))
}
void *context)
{
struct imap_client *const *destroy_clients;
count /= sizeof(struct imap_client *);
for (i = 0; i < count; i++) {
i * sizeof(struct imap_client *),
&client, sizeof(struct imap_client *));
break;
}
}
}
static void client_destroy_oldest(void)
{
struct imap_client *const *destroy_clients;
/* find the oldest clients and put them to destroy-buffer */
sizeof(struct imap_client *) *
/* then kill them */
count /= sizeof(struct imap_client *);
for (i = 0; i < count; i++) {
"Disconnected: Connection queue full");
}
}
{
struct imap_client *client;
/* reached max. users count, kill few of the
oldest connections */
}
/* always use nonblocking I/O */
main_ref();
}
{
return;
}
}
}
{
}
{
return TRUE;
main_unref();
return FALSE;
}
{
}
{
}
{
const char *host;
host = "??";
}
void *context __attr_unused__)
{
}
}
{
}
unsigned int clients_get_count(void)
{
}
void *context __attr_unused__)
{
if (client->input_blocked) {
}
}
void clients_notify_auth_process(void)
{
}
void *context __attr_unused__)
{
}
void clients_destroy_all(void)
{
}
void clients_init(void)
{
}
void clients_deinit(void)
{
}