client.c revision ee32cb2843bf6be232e418591100f0297c7ead83
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
296dca49e4fe6046e0328c67ef1cf4b8077dec9cTimo Sirainenextern struct mail_storage_callbacks mail_storage_callbacks;
7fd51f7b0b4d990ec3cfef4e60ee685bf9fb32deTimo Sirainenstatic struct client *my_client; /* we don't need more than one currently */
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainenstatic bool client_handle_input(struct client *client);
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainenstatic void client_idle_timeout(struct client *client)
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen client_send_line(client, "* BYE Disconnected for inactivity.");
4ac2d38239cea8090154e17faefd77de5a71d882Timo Sirainen client_destroy(client, "Disconnected for inactivity");
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainenstruct client *client_create(int fd_in, int fd_out,
16db188cfddce117500a161302f17ae691b4500eTimo Sirainen /* always use nonblocking I/O */
16db188cfddce117500a161302f17ae691b4500eTimo Sirainen client->input = i_stream_create_fd(fd_in, imap_max_line_length, FALSE);
16db188cfddce117500a161302f17ae691b4500eTimo Sirainen client->output = o_stream_create_fd(fd_out, (size_t)-1, FALSE);
296dca49e4fe6046e0328c67ef1cf4b8077dec9cTimo Sirainen o_stream_set_flush_callback(client->output, client_output, client);
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen client->io = io_add(fd_in, IO_READ, client_input, client);
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen client->command_pool = pool_alloconly_create("client command", 1024*12);
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen mail_storage_set_callbacks(namespaces->storage,
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainenvoid client_command_cancel(struct client_command_context *cmd)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen cmd_ret = cmd->func == NULL ? TRUE : cmd->func(cmd);
6145bd3b17b9135b77b0b42409a0cc3fa0d1b946Timo Sirainen if (!cmd_ret && cmd->state != CLIENT_COMMAND_STATE_DONE) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen i_panic("command didn't cancel itself: %s", cmd->name);
092018b35bb1dc5bd61848a38189fe6ac8f791ddTimo Sirainenstatic const char *client_stats(struct client *client)
7327394e30c1020b9a2a49c72a7e3d0f7803e680Timo Sirainen static struct var_expand_table static_tab[] = {
6145bd3b17b9135b77b0b42409a0cc3fa0d1b946Timo Sirainen tab[0].value = dec2str(client->input->v_offset);
6145bd3b17b9135b77b0b42409a0cc3fa0d1b946Timo Sirainen tab[1].value = dec2str(client->output->offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic const char *client_get_disconnect_reason(struct client *client)
c8cf8a605e0ddea7cb36fe04551aeca5090e684bTimo Sirainen return errno == 0 || errno == EPIPE ? "Connection closed" :
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenvoid client_destroy(struct client *client, const char *reason)
9b706b345064ce8e8a657f54633f009a101298eaTimo Sirainen reason = client_get_disconnect_reason(client);
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen i_info("%s %s", reason, client_stats(client));
288d6ef592719f2be3cad9f034e9be05f9839785Timo Sirainen /* finish off all the queued commands. */
14b551180cb4ac7acac8b048d8d6d7278541d1f6Timo Sirainen /* quit the program */
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainenvoid client_disconnect(struct client *client, const char *reason)
const char *msg)
bool fatal;
if (fatal) {
int ret;
return TRUE;
return FALSE;
return FALSE;
unsigned int count, ...)
const char *str;
return FALSE;
for (i = 0; i < count; i++) {
return i == count;
static struct client_command_context *
return cmd;
return NULL;
return FALSE;
return TRUE;
return TRUE;
return FALSE;
if (broken_client) {
return TRUE;
static struct client_command_context *
return cmd;
if (size > 0)
const unsigned char *data;
for (i = 0; i < data_size; i++) {
return FALSE;
return TRUE;
return TRUE;
return TRUE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
if (size == 0)
return FALSE;
return FALSE;
T_BEGIN {
} T_END;
if (ret)
return TRUE;
if (remove_io)
if (!handled_commands)
return FALSE;
if (ret)
return TRUE;
bool finished;
if (!finished)
int ret;
return ret;
void clients_init(void)
void clients_deinit(void)