client.c revision c979eeda1f46483d9c963e265786b701d7683d77
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2002 Timo Sirainen */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "common.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "buffer.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "ioloop.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "network.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "istream.h"
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi#include "ostream.h"
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen#include "str.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "var-expand.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "mail-storage.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "commands.h"
d951320d498ae0800b677b754dde71574102123bTimo Sirainen#include "mail-search.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include "mail-namespace.h"
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <stdlib.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#include <unistd.h>
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* max. length of input command line (spec says 512) */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define MAX_INBUF_SIZE 2048
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Stop reading input when output buffer has this many bytes. Once the buffer
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen size has dropped to half of it, start reading input again. */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define OUTBUF_THROTTLE_SIZE 4096
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* If we can't send anything for 10 minutes, disconnect the client */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define CLIENT_OUTPUT_TIMEOUT (10*60)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Disconnect client when it sends too many bad commands in a row */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define CLIENT_MAX_BAD_COMMANDS 20
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen/* Disconnect client after idling this many seconds */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen#define CLIENT_IDLE_TIMEOUT (10*60)
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic struct client *my_client; /* we don't need more than one currently */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic struct timeout *to_idle;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic void client_input(struct client *client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int client_output(struct client *client);
a21f618de284dc22a480af1371d5f5cea50a39dfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenstatic int sync_mailbox(struct mailbox *box, struct mailbox_status *status)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_sync_context *ctx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_sync_rec sync_rec;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ctx = mailbox_sync_init(box, MAILBOX_SYNC_FLAG_FULL_READ);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen while (mailbox_sync_next(ctx, &sync_rec))
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen ;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return mailbox_sync_deinit(&ctx, STATUS_UIDVALIDITY, status);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen}
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainenstatic int init_mailbox(struct client *client)
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mail_search_arg search_arg;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_transaction_context *t;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mail_search_context *ctx;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mailbox_status status;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen struct mail *mail;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen buffer_t *message_sizes_buf;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int i;
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen bool failed;
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen message_sizes_buf = buffer_create_dynamic(default_pool, 512);
091a2dea9d89734a7c1225eed511b3851693a757Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen memset(&search_arg, 0, sizeof(search_arg));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen search_arg.type = SEARCH_ALL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen for (i = 0; i < 2; i++) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (sync_mailbox(client->mailbox, &status) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_send_storage_error(client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->uid_validity = status.uidvalidity;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen t = mailbox_transaction_begin(client->mailbox, 0);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ctx = mailbox_search_init(t, NULL, &search_arg, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->last_seen = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->total_size = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen buffer_set_used_size(message_sizes_buf, 0);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
15dd18994a8a4933e39e2f87233255d0ca82ba3eTimo Sirainen failed = FALSE;
15dd18994a8a4933e39e2f87233255d0ca82ba3eTimo Sirainen mail = mail_alloc(t, MAIL_FETCH_VIRTUAL_SIZE, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen while (mailbox_search_next(ctx, mail) > 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen uoff_t size = mail_get_virtual_size(mail);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (size == (uoff_t)-1) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen failed = TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if ((mail_get_flags(mail) & MAIL_SEEN) != 0)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->last_seen = mail->seq;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->total_size += size;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen buffer_append(message_sizes_buf, &size, sizeof(size));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->messages_count =
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen message_sizes_buf->used / sizeof(uoff_t);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail_free(&mail);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (mailbox_search_deinit(&ctx) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_send_storage_error(client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen (void)mailbox_transaction_commit(&t, 0);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (!failed) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->trans = t;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->message_sizes =
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen buffer_free_without_data(message_sizes_buf);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen /* well, sync and try again. we might have cached virtual
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen sizes, make sure they get committed. */
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen (void)mailbox_transaction_commit(&t, 0);
a5b64f1abb1cb0a9718d5bf7f0ae808072237259Timo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (i == 2)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_send_line(client, "-ERR [IN-USE] Couldn't sync mailbox.");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen buffer_free(message_sizes_buf);
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch return FALSE;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch}
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Boschstruct client *client_create(int fd_in, int fd_out,
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch struct mail_namespace *namespaces)
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch{
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch struct mail_storage *storage;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch const char *inbox;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch struct client *client;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch enum mailbox_open_flags flags;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch const char *errmsg;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch enum mail_error error;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch /* always use nonblocking I/O */
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch net_set_nonblock(fd_in, TRUE);
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch net_set_nonblock(fd_out, TRUE);
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch client = i_new(struct client, 1);
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch client->fd_in = fd_in;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch client->fd_out = fd_out;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->input = i_stream_create_fd(fd_in, MAX_INBUF_SIZE, FALSE);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_set_flush_callback(client->output, client_output, client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->io = io_add(fd_in, IO_READ, client_input, client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->last_input = ioloop_time;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->namespaces = namespaces;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen inbox = "INBOX";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->inbox_ns = mail_namespace_find(namespaces, &inbox);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->inbox_ns == NULL) {
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi client_send_line(client, "-ERR No INBOX namespace for user.");
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi client_destroy(client, "No INBOX namespace for user.");
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi return NULL;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi }
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi storage = client->inbox_ns->storage;
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen
36e5cd9ab4c86cf9da0762fa327cd5be04397676Aki Tuomi flags = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (no_flag_updates)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen flags |= MAILBOX_OPEN_KEEP_RECENT;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi if (lock_session)
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi flags |= MAILBOX_OPEN_KEEP_LOCKED;
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi client->mailbox = mailbox_open(storage, "INBOX", NULL, flags);
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi if (client->mailbox == NULL) {
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi errmsg = t_strdup_printf("Couldn't open INBOX: %s",
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi mail_storage_get_last_error(storage,
a327d9301f593433c228c4cc8cca05c95b37f6fbTimo Sirainen &error));
8a4a0ef8264d95ffb2ba8f6f109f94ea7f3454e8Timo Sirainen i_error("%s", errmsg);
d48e40d6c77d673ad402d96571198d1cce4da225Timo Sirainen client_send_line(client, "-ERR [IN-USE] %s", errmsg);
36e5cd9ab4c86cf9da0762fa327cd5be04397676Aki Tuomi client_destroy(client, "Couldn't open INBOX");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return NULL;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch if (!init_mailbox(client)) {
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch i_error("Couldn't init INBOX: %s",
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch mail_storage_get_last_error(storage, &error));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_destroy(client, "Mailbox init failed");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(my_client == NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen my_client = client;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen if (hook_client_created != NULL)
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen hook_client_created(&client);
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen return client;
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen}
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainenstatic const char *client_stats(struct client *client)
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch{
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch static struct var_expand_table static_tab[] = {
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen { 'p', NULL },
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen { 't', NULL },
ed567dac7e55ab3e8dd53d9c86c31ebb2032d4dfTimo Sirainen { 'b', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { 'r', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { 'd', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { 'm', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { 's', NULL },
2c5c70e12365d7910848259f88eb237ce3a15947Timo Sirainen { 'i', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { 'o', NULL },
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen { '\0', NULL }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen };
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen struct var_expand_table *tab;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen string_t *str;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen tab = t_malloc(sizeof(static_tab));
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen tab[0].value = dec2str(client->top_bytes);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen tab[1].value = dec2str(client->top_count);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[2].value = dec2str(client->retr_bytes);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[3].value = dec2str(client->retr_count);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[4].value = dec2str(client->expunged_count);
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch tab[5].value = dec2str(client->messages_count);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[6].value = dec2str(client->total_size);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[7].value = dec2str(client->input->v_offset);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch tab[8].value = dec2str(client->output->offset);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch str = t_str_new(128);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch var_expand(str, logout_format, tab);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch return str_c(str);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch}
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Boschvoid client_destroy(struct client *client, const char *reason)
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch{
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch if (!client->disconnected) {
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch if (reason == NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen reason = "Disconnected";
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_info("%s %s", reason, client_stats(client));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->cmd != NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* deinitialize command */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_stream_close(client->input);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch o_stream_close(client->output);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch client->cmd(client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_assert(client->cmd == NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->trans != NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen /* client didn't QUIT, but we still want to save any changes
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen done in this transaction. especially the cached virtual
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen message sizes. */
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch (void)mailbox_transaction_commit(&client->trans, 0);
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch }
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch if (client->mailbox != NULL)
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch mailbox_close(&client->mailbox);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail_namespaces_deinit(&client->namespaces);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_free(client->message_sizes);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch i_free(client->deleted_bitmask);
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->io != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen io_remove(&client->io);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_stream_destroy(&client->input);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_destroy(&client->output);
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch if (close(client->fd_in) < 0)
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch i_error("close(client in) failed: %m");
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch if (client->fd_in != client->fd_out) {
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch if (close(client->fd_out) < 0)
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch i_error("close(client out) failed: %m");
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch }
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch i_free(client);
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch /* quit the program */
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch my_client = NULL;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen io_loop_stop(ioloop);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid client_disconnect(struct client *client, const char *reason)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->disconnected)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return;
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch client->disconnected = TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_info("Disconnected: %s %s", reason, client_stats(client));
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
fa33df8230c2f27ae863ff83d4251923428d53c7Aki Tuomi (void)o_stream_flush(client->output);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen i_stream_close(client->input);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch o_stream_close(client->output);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch}
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Boschint client_send_line(struct client *client, const char *fmt, ...)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch{
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch va_list va;
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch string_t *str;
4b9e7a8752803928aa0897f8cc1fc34592452f07Stephan Bosch ssize_t ret;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch if (client->output->closed)
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch return -1;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch t_push();
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch va_start(va, fmt);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch str = t_str_new(256);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch str_vprintfa(str, fmt, va);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch str_append(str, "\r\n");
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch ret = o_stream_send(client->output, str_data(str), str_len(str));
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch if (ret >= 0) {
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch i_assert((size_t)ret == str_len(str));
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch if (o_stream_get_buffer_used_size(client->output) <
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch OUTBUF_THROTTLE_SIZE) {
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch ret = 1;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch client->last_output = ioloop_time;
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch } else {
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch ret = 0;
c85f67cfb8e1cef2de2b681debf4703d5818dc01Stephan Bosch if (client->io != NULL) {
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch /* no more input until client has read
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch our output */
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch io_remove(&client->io);
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch
67e0afe62b26d222614b8d817155bf5c74bd7fe0Stephan Bosch /* If someone happens to flush output,
6793538c389d3e725456e3eabb697e2743233646Stephan Bosch we want to get our IO handler back in
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen flush callback */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_set_flush_pending(client->output,
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek TRUE);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen }
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen va_end(va);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen t_pop();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return (int)ret;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainenvoid client_send_storage_error(struct client *client)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen enum mail_error error;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch if (mailbox_is_inconsistent(client->mailbox)) {
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch client_send_line(client, "-ERR Mailbox is in inconsistent "
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch "state, please relogin.");
54c6a8135c0ded324f7ae7d0cdf1ef177004ee2dStephan Bosch client_disconnect(client, "Mailbox is in inconsistent state.");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return;
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainen }
4487c66123ca4830f8afbf4efcd7a260848d0e05Timo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_send_line(client, "-ERR %s",
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen mail_storage_get_last_error(client->inbox_ns->storage,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen &error));
2c5c70e12365d7910848259f88eb237ce3a15947Timo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainenstatic void client_input(struct client *client)
cb3ab2fd5668700a89b274a43595cfbfa1616e4bTimo Sirainen{
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch char *line, *args;
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch int ret;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch if (client->cmd != NULL) {
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch /* we're still processing a command. wait until it's
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch finished. */
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen io_remove(&client->io);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->waiting_input = TRUE;
7db7fbea5d8a07463b625f93d69166d56018dadfTimo Sirainen return;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->waiting_input = FALSE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->last_input = ioloop_time;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen switch (i_stream_read(client->input)) {
a2d962e729a1c162145b86b3b6a666ef0a139e52Timo Sirainen case -1:
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* disconnected */
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek client_destroy(client, NULL);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek return;
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek case -2:
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek /* line too long, kill it */
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek client_send_line(client, "-ERR Input line too long.");
9a84b90d894a741ae6e090de104d31382a41d0aaJosef 'Jeff' Sipek client_destroy(client, "Input line too long");
33a80622828063f5be6f743855d5273fabe8ae58Timo Sirainen return;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_cork(client->output);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen while (!client->output->closed &&
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen (line = i_stream_next_line(client->input)) != NULL) {
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen args = strchr(line, ' ');
a618726eb3eb09a3866fe93208baf923d593f4d3Timo Sirainen if (args != NULL)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen *args++ = '\0';
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen t_push();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen ret = client_command_execute(client, line,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen args != NULL ? args : "");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen t_pop();
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (ret >= 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->bad_counter = 0;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->cmd != NULL) {
a238c6fede2022e5a4af707107ffb8f047b7753fTimo Sirainen o_stream_set_flush_pending(client->output,
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen TRUE);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->waiting_input = TRUE;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen break;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen } else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_send_line(client, "-ERR Too many bad commands.");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_disconnect(client, "Too many bad commands.");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_uncork(client->output);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->output->closed)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_destroy(client, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen}
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
48325adac125d7ff275ec69b05b7a92be9637630Timo Sirainenstatic int client_output(struct client *client)
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen int ret;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_destroy(client, NULL);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen return 1;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->last_output = ioloop_time;
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->cmd != NULL) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_cork(client->output);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client->cmd(client);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen o_stream_uncork(client->output);
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (client->cmd == NULL) {
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen if (o_stream_get_buffer_used_size(client->output) <
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen OUTBUF_THROTTLE_SIZE/2 && client->io == NULL) {
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen /* enable input again */
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen client->io = io_add(i_stream_get_fd(client->input),
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen IO_READ, client_input, client);
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen }
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen if (client->io != NULL && client->waiting_input)
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen client_input(client);
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen }
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen return client->cmd == NULL;
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen}
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainenstatic void idle_timeout(void *context __attr_unused__)
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen{
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen if (my_client == NULL)
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen return;
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen if (my_client->cmd != NULL) {
c61779cfa45c1684b1f7c462011088bad0b8318cTimo Sirainen if (ioloop_time - my_client->last_output >=
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen CLIENT_OUTPUT_TIMEOUT) {
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_destroy(my_client, "Disconnected for inactivity "
d951320d498ae0800b677b754dde71574102123bTimo Sirainen "in reading our output");
d951320d498ae0800b677b754dde71574102123bTimo Sirainen }
d951320d498ae0800b677b754dde71574102123bTimo Sirainen } else {
d951320d498ae0800b677b754dde71574102123bTimo Sirainen if (ioloop_time - my_client->last_input >=
d951320d498ae0800b677b754dde71574102123bTimo Sirainen CLIENT_IDLE_TIMEOUT) {
d951320d498ae0800b677b754dde71574102123bTimo Sirainen client_send_line(my_client,
d951320d498ae0800b677b754dde71574102123bTimo Sirainen "-ERR Disconnected for inactivity.");
d951320d498ae0800b677b754dde71574102123bTimo Sirainen client_destroy(my_client, "Disconnected for inactivity");
d951320d498ae0800b677b754dde71574102123bTimo Sirainen }
d951320d498ae0800b677b754dde71574102123bTimo Sirainen }
d951320d498ae0800b677b754dde71574102123bTimo Sirainen}
d951320d498ae0800b677b754dde71574102123bTimo Sirainen
d951320d498ae0800b677b754dde71574102123bTimo Sirainenvoid clients_init(void)
d951320d498ae0800b677b754dde71574102123bTimo Sirainen{
d951320d498ae0800b677b754dde71574102123bTimo Sirainen my_client = NULL;
d951320d498ae0800b677b754dde71574102123bTimo Sirainen to_idle = timeout_add(10000, idle_timeout, NULL);
d951320d498ae0800b677b754dde71574102123bTimo Sirainen}
d951320d498ae0800b677b754dde71574102123bTimo Sirainen
ddaf416216a83e71bc1bfc1b6faf2ead9d774613Stephan Boschvoid clients_deinit(void)
ddaf416216a83e71bc1bfc1b6faf2ead9d774613Stephan Bosch{
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen if (my_client != NULL) {
086b73efd1a5812a64acc951366a499d325509a6Stephan Bosch client_send_line(my_client, "-ERR Server shutting down.");
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen client_destroy(my_client, "Server shutting down");
ddaf416216a83e71bc1bfc1b6faf2ead9d774613Stephan Bosch }
96f89d51e8315f644f46804a9f0fc4f685ac48bfTimo Sirainen
ddaf416216a83e71bc1bfc1b6faf2ead9d774613Stephan Bosch timeout_remove(&to_idle);
959eca738ab09d2760fd96ba329263fe589f84b0Timo Sirainen}
ddaf416216a83e71bc1bfc1b6faf2ead9d774613Stephan Bosch