#ifndef IMAP_CLIENT_H
#define IMAP_CLIENT_H
#include "imap-commands.h"
#define CLIENT_COMMAND_QUEUE_MAX_SIZE 4
#define CLIENT_MAX_SEARCH_UPDATES 10
struct client;
struct mail_storage;
struct imap_parser;
struct imap_arg;
struct mailbox_keywords {
const ARRAY_TYPE(keywords) *names;
unsigned int announce_count;
};
struct imap_search_update {
char *tag;
struct mail_search_result *result;
bool return_uids;
};
enum client_command_state {
CLIENT_COMMAND_STATE_WAIT_INPUT,
CLIENT_COMMAND_STATE_WAIT_OUTPUT,
CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY,
CLIENT_COMMAND_STATE_WAIT_SYNC,
CLIENT_COMMAND_STATE_DONE
};
struct imap_module_register {
unsigned int id;
};
union imap_module_context {
struct imap_module_register *reg;
};
extern struct imap_module_register imap_module_register;
struct client_command_context {
struct client_command_context *prev, *next;
struct client *client;
pool_t pool;
const char *tag;
const char *name;
const char *args;
enum command_flags cmd_flags;
command_func_t *func;
void *context;
ARRAY_DEFINE(module_contexts, union imap_module_context *);
struct imap_parser *parser;
enum client_command_state state;
struct client_sync_context *sync;
unsigned int uid:1;
unsigned int cancel:1;
unsigned int param_error:1;
unsigned int search_save_result:1;
unsigned int search_save_result_used:1;
unsigned int temp_executed:1;
};
struct client {
struct client *prev, *next;
int fd_in, fd_out;
struct io *io;
struct istream *input;
struct ostream *output;
struct timeout *to_idle, *to_idle_output;
pool_t pool;
struct mail_storage_service_user *service_user;
const struct imap_settings *set;
string_t *capability_string;
struct mail_user *user;
struct mailbox *mailbox;
struct mailbox_keywords keywords;
unsigned int select_counter;
unsigned int sync_counter;
uint32_t messages_count, recent_count, uidvalidity;
enum mailbox_feature enabled_features;
time_t last_input, last_output;
unsigned int bad_counter;
struct imap_parser *free_parser;
pool_t command_pool;
struct client_command_context *command_queue;
unsigned int command_queue_size;
uint64_t sync_last_full_modseq;
uint64_t highest_fetch_modseq;
ARRAY_TYPE(seq_range) search_saved_uidset;
ARRAY_DEFINE(search_updates, struct imap_search_update);
struct client_command_context *input_lock;
struct client_command_context *output_lock;
struct client_command_context *mailbox_change_lock;
ARRAY_DEFINE(module_contexts, union imap_module_context *);
unsigned int sync_seen_deletes:1;
unsigned int sync_seen_expunges:1;
unsigned int disconnected:1;
unsigned int destroyed:1;
unsigned int handling_input:1;
unsigned int syncing:1;
unsigned int id_logged:1;
unsigned int mailbox_examined:1;
unsigned int anvil_sent:1;
unsigned int tls_compression:1;
unsigned int input_skip_line:1;
unsigned int modseqs_sent_since_sync:1;
unsigned int output_squelch:1;
unsigned int submit:1;
unsigned int ignore:1;
};
extern struct client *imap_clients;
extern unsigned int imap_client_count;
struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
struct mail_storage_service_user *service_user,
const struct imap_settings *set);
void client_destroy(struct client *client, const char *reason);
void client_disconnect(struct client *client, const char *reason);
void client_disconnect_with_error(struct client *client, const char *msg);
int client_send_line(struct client *client, const char *data);
void client_send_tagline(struct client_command_context *cmd, const char *data);
void client_send_command_error(struct client_command_context *cmd,
const char *msg);
bool client_read_args(struct client_command_context *cmd, unsigned int count,
unsigned int flags, const struct imap_arg **args_r);
bool client_read_string_args(struct client_command_context *cmd,
unsigned int count, ...);
bool client_handle_search_save_ambiguity(struct client_command_context *cmd);
void client_enable(struct client *client, enum mailbox_feature features);
struct imap_search_update *
client_search_update_lookup(struct client *client, const char *tag,
unsigned int *idx_r);
void client_search_updates_free(struct client *client);
void client_command_cancel(struct client_command_context **cmd);
void client_command_free(struct client_command_context **cmd);
bool client_handle_unfinished_cmd(struct client_command_context *cmd);
void client_continue_pending_input(struct client *client);
bool client_skip_line(struct client *client);
void client_input(struct client *client);
bool client_handle_input(struct client *client);
int client_output(struct client *client);
void clients_destroy_all(void);
#endif