static void idle_client_input_more(struct cmd_idle_context *ctx) { struct client *client = ctx->client; client->last_input = ioloop_time; timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: /* disconnected */ client_disconnect(client, "Disconnected in IDLE"); return; case -2: client->input_skip_line = TRUE; idle_finish(ctx, FALSE, TRUE); client_continue_pending_input(client); return; } if (ctx->sync_ctx != NULL) { /* we're still sending output to client. wait until it's all sent so we don't lose any changes. */ io_remove(&client->io); return; } if (idle_client_handle_input(ctx, TRUE)) { if (!client->disconnected) client_continue_pending_input(client); } }
int client_output(struct client *client) { int ret; i_assert(!client->destroyed); client->last_output = ioloop_time; timeout_reset(client->to_idle); if (client->to_idle_output != NULL) timeout_reset(client->to_idle_output); o_stream_cork(client->output); if ((ret = o_stream_flush(client->output)) < 0) { client_destroy(client, NULL); return 1; } client_output_commands(client); (void)cmd_sync_delayed(client); o_stream_uncork(client->output); imap_refresh_proctitle(); if (client->disconnected) client_destroy(client, NULL); else client_continue_pending_input(client); return ret; }
void client_continue_pending_input(struct client *client) { i_assert(!client->handling_input); if (client->input_lock != NULL) { /* there's a command that has locked the input */ struct client_command_context *cmd = client->input_lock; if (cmd->state != CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY) return; /* the command is waiting for existing ambiguity causing commands to finish. */ if (client_command_is_ambiguous(cmd)) { /* we could be waiting for existing sync to finish */ if (!cmd_sync_delayed(client)) return; if (client_command_is_ambiguous(cmd)) return; } cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT; } client_add_missing_io(client); /* if there's unread data in buffer, handle it. */ if (i_stream_get_data_size(client->input) > 0 && !client->disconnected) { if (client_handle_input(client)) client_continue_pending_input(client); } }
static void client_input_append(struct client_command_context *cmd) { struct cmd_append_context *ctx = cmd->context; struct client *client = cmd->client; const char *reason; bool finished; uoff_t lit_offset; i_assert(!client->destroyed); client->last_input = ioloop_time; timeout_reset(client->to_idle); switch (i_stream_read(client->input)) { case -1: /* disconnected */ lit_offset = ctx->litinput == NULL ? 0 : ctx->litinput->v_offset; reason = get_disconnect_reason(ctx, lit_offset); cmd_append_finish(cmd->context); /* Reset command so that client_destroy() doesn't try to call cmd_append_continue_message() anymore. */ client_command_free(&cmd); client_destroy(client, reason); return; case -2: if (ctx->message_input) { /* message data, this is handled internally by mailbox_save_continue() */ break; } cmd_append_finish(cmd->context); /* parameter word is longer than max. input buffer size. this is most likely an error, so skip the new data until newline is found. */ client->input_skip_line = TRUE; if (!ctx->failed) client_send_command_error(cmd, "Too long argument."); cmd->param_error = TRUE; client_command_free(&cmd); return; } o_stream_cork(client->output); finished = command_exec(cmd); if (!finished) (void)client_handle_unfinished_cmd(cmd); else client_command_free(&cmd); cmd_sync_delayed(client); o_stream_uncork(client->output); if (client->disconnected) client_destroy(client, NULL); else client_continue_pending_input(client); }
void client_input(struct client *client) { struct client_command_context *cmd; struct ostream *output = client->output; ssize_t bytes; i_assert(client->io != NULL); client->last_input = ioloop_time; timeout_reset(client->to_idle); if (client->to_delayed_input != NULL) timeout_remove(&client->to_delayed_input); bytes = i_stream_read(client->input); if (bytes == -1) { /* disconnected */ client_destroy(client, NULL); return; } o_stream_ref(output); o_stream_cork(output); if (!client_handle_input(client) && bytes == -2) { /* parameter word is longer than max. input buffer size. this is most likely an error, so skip the new data until newline is found. */ client->input_skip_line = TRUE; cmd = client->input_lock != NULL ? client->input_lock : client_command_new(client); cmd->param_error = TRUE; client_send_command_error(cmd, "Too long argument."); client_command_free(&cmd); } o_stream_uncork(output); o_stream_unref(&output); imap_refresh_proctitle(); if (client->disconnected) client_destroy(client, NULL); else client_continue_pending_input(client); }