director.h revision 05b7b8f14426b5fe5d016940eb5916033f0bc841
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#ifndef DIRECTOR_H
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_H
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#include "net.h"
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#include "director-settings.h"
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_NAME "director"
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_MAJOR 1
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_MINOR 9
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* weak users supported in protocol */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_WEAK_USERS 1
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* director ring remove supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_RING_REMOVE 2
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* quit reason supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_QUIT 3
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* user-kick supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_USER_KICK 4
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* options supported in handshake */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_OPTIONS 5
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* user tags supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_TAGS 5
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* up/down state is tracked */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_UPDOWN 6
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* user tag version 2 supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_TAGS_V2 7
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* user-kick-alt supported */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_USER_KICK_ALT 8
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* Users are sent as "U" command in handshake */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_VERSION_HANDSHAKE_U_CMD 9
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* Minimum time between even attempting to communicate with a director that
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes failed due to a protocol error. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_PROTOCOL_FAILURE_RETRY_SECS 60
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct director;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct mail_host;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct user;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct director_user_init;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesenum user_kill_state {
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* User isn't being killed */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_NONE,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* We're still killing the user's connections */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_KILLING,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Like above, but our left side already announced it was finished
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes with killing its user connections */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_KILLING_NOTIFY_RECEIVED,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* We're done killing, but we have to wait for the left side to
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes finish killing its user connections before sending USER-KILLED to
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes our right side */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_KILLED_WAITING_FOR_NOTIFY,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* We're done killing, but waiting for USER-KILLED-EVERYWHERE
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes notification until this state gets reset. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_KILLED_WAITING_FOR_EVERYONE,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Waiting for the flush socket to finish. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_FLUSHING,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Wait for a while for the user connections to actually die. Note that
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes only at this stage we can be sure that all the directors know about
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes the user move (although it could be earlier if we added a new
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER-MOVED notification). */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes USER_KILL_STATE_DELAY
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* NOTE: remember to update also user_kill_state_names[] */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes};
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesextern const char *user_kill_state_names[USER_KILL_STATE_DELAY+1];
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholestypedef void director_state_change_callback_t(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholestypedef director_state_change_callback_t director_kick_callback_t;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* When a user gets freed, the kill_ctx may still be left alive. It's also
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes possible for the user to come back, in which case the kill_ctx is usually
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes NULL, but another kill could have also started. The previous kill_ctx is
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes valid only if it matches the current user's kill_ctx. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes#define DIRECTOR_KILL_CONTEXT_IS_VALID(user, ctx) \
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ((user) != NULL && (user)->kill_ctx == ctx)
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct director_kill_context {
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director *dir;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_tag *tag;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int username_hash;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct ip_addr old_host_ip;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int old_host_vhost_count;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool old_host_down;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool kill_is_self_initiated;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool callback_pending;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes enum user_kill_state kill_state;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Move timeout to make sure user's connections won't silently hang
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes indefinitely if there is some trouble moving it. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_move;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* these are set only for director_flush_socket handling: */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct ip_addr host_ip;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct program_client *pclient;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct ostream *reply;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes char *socket_path;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes};
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct director {
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes const struct director_settings *set;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* IP and port of this director. self_host->ip/port must equal these. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct ip_addr self_ip;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes in_port_t self_port;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes in_port_t test_port;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *self_host;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* left and right connections are set only after they have finished
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes handshaking. until then they're in the connections list, although
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes updates are still sent to them during handshaking if the USER list
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes is long. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_connection *left, *right;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* all director connections */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ARRAY(struct director_connection *) connections;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_reconnect;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_sync;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_callback;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* current mail hosts */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host_list *mail_hosts;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* original mail hosts configured in config file.
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes this is used only for doveadm lookups */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host_list *orig_config_hosts;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Number of users currently being moved */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int users_moving_count;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Number of users currently being kicked */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int users_kicking_count;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Number of requests currently delayed */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int requests_delayed_count;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* these requests are waiting for directors to be in synced */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ARRAY(struct director_request *) pending_requests;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_request;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_handshake_warning;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes director_state_change_callback_t *state_change_callback;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes director_kick_callback_t *kick_callback;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* director hosts are sorted by IP (and port) */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ARRAY(struct director_host *) dir_hosts;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeout *to_remove_dirs;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct ipc_client *ipc_proxy;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int sync_seq;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int ring_change_counter;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int last_sync_sent_ring_change_counter;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Timestamp when the last SYNC was initiated by us */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct timeval last_sync_start_time;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* the lowest minor version supported by the ring */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int ring_min_version;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* Timestamp when ring became synced or unsynced the last time */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes time_t ring_last_sync_time;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* How many milliseconds it took for the last SYNC to travel through
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes the ring. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int last_sync_msecs;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes time_t ring_first_alone;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes uint64_t num_requests;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes uint64_t ring_traffic_input, ring_traffic_output;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes /* director ring handshaking is complete.
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes director can start serving clients. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool ring_handshaked:1;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool ring_handshake_warning_sent:1;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool ring_synced:1;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool sync_frozen:1;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes bool sync_pending:1;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes};
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesextern bool director_debug;
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* Create a new director. If listen_ip specifies an actual IP, it's used with
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes listen_port for finding ourself from the director_servers setting.
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes listen_port is used regardless by director_host_add_from_string() for hosts
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes without specified port. */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesstruct director *
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesdirector_init(const struct director_settings *set,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes const struct ip_addr *listen_ip, in_port_t listen_port,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes director_state_change_callback_t *callback,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes director_kick_callback_t *kick_callback);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_deinit(struct director **dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_find_self(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* Start connecting to other directors */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_connect(struct director *dir, const char *reason);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_set_ring_handshaked(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_set_ring_synced(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_set_ring_unsynced(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_set_state_changed(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_sync_send(struct director *dir, struct director_host *host,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes uint32_t seq, unsigned int minor_version,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int timestamp, unsigned int hosts_hash);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesbool director_resend_sync(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_notify_ring_added(struct director_host *added_host,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *src, bool log);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_ring_remove(struct director_host *removed_host,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *src);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_update_host(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host *host) ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_resend_hosts(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_remove_host(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host *host) ATTR_NULL(2, 3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_flush_host(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host *host) ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_update_user(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct user *user);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_update_user_weak(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_connection *src_conn,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct user *user) ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_kill_user(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct user *user, struct mail_tag *tag,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct mail_host *old_host, bool forced_kick);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_move_user(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int username_hash, struct mail_host *host)
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_kick_user(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src, const char *username)
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_kick_user_alt(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes const char *field, const char *value)
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_kick_user_hash(struct director *dir, struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int username_hash,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes const struct ip_addr *except_ip)
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_user_killed(struct director *dir, unsigned int username_hash);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_user_killed_everywhere(struct director *dir,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes struct director_host *orig_src,
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes unsigned int username_hash) ATTR_NULL(3);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_user_weak(struct director *dir, struct user *user);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_sync_freeze(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_sync_thaw(struct director *dir);
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes/* Send data to all directors using both left and right connections
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholes (unless they're the same). */
3c937b528ca923d5b51e63def9f888af4a77bb40bnicholesvoid director_update_send(struct director *dir, struct director_host *src,
const char *cmd);
void director_update_send_version(struct director *dir,
struct director_host *src,
unsigned int min_version, const char *cmd);
int director_connect_host(struct director *dir, struct director_host *host,
const char *reason);
bool
director_get_username_hash(struct director *dir, const char *username,
unsigned int *hash_r);
void directors_init(void);
void directors_deinit(void);
void dir_debug(const char *fmt, ...) ATTR_FORMAT(1, 2);
struct director_user_iter *director_iterate_users_init(struct director *dir);
struct user *director_iterate_users_next(struct director_user_iter *iter);
void director_iterate_users_deinit(struct director_user_iter **_iter);
#endif