27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#ifndef USER_DIRECTORY_H
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#define USER_DIRECTORY_H
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek#define USER_IS_BEING_KILLED(user) \
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek ((user)->kill_ctx != NULL)
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozekstruct user {
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* Approximately sorted by time (except during handshaking).
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek The sorting order may be constantly wrong a few seconds here and
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek there. */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct user *prev, *next;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* first 32 bits of MD5(username). collisions are quite unlikely, but
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek even if they happen it doesn't matter - the users are just
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek redirected to same server */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek unsigned int username_hash;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek unsigned int timestamp;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct mail_host *host;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* If non-NULL, don't allow new connections until all
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek directors have killed the user's connections. */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek struct director_kill_context *kill_ctx;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek /* TRUE, if the user's timestamp was close to being expired and we're
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek now doing a ring-wide sync for this user to make sure we don't
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek assign conflicting hosts to it */
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek bool weak:1;
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek};
27e89b6925334565c73c407a9ae2809358789c81Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozektypedef void user_free_hook_t(struct user *);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek/* Create a new directory. Users are dropped if their time gets older
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek than timeout_secs. */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstruct user_directory *
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekuser_directory_init(unsigned int timeout_secs,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek user_free_hook_t *user_free_hook);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid user_directory_deinit(struct user_directory **dir);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Returns the number of users currently in directory. */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekunsigned int user_directory_count(struct user_directory *dir);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Look up username from directory. Returns NULL if not found. */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekstruct user *user_directory_lookup(struct user_directory *dir,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek unsigned int username_hash);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Add a user to directory and return it. */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekstruct user *
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekuser_directory_add(struct user_directory *dir, unsigned int username_hash,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_host *host, time_t timestamp);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Refresh user's timestamp */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid user_directory_refresh(struct user_directory *dir, struct user *user);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Remove all users that have pointers to given host */
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekvoid user_directory_remove_host(struct user_directory *dir,
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek struct mail_host *host);
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek/* Sort users based on the timestamp. This is called only after updating
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek timestamps based on remote director's user list after handshake. */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekvoid user_directory_sort(struct user_directory *dir);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekbool user_directory_user_is_recently_updated(struct user_directory *dir,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct user *user);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekbool user_directory_user_is_near_expiring(struct user_directory *dir,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek struct user *user);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek/* Iterate through users in the directory. It's safe to modify user directory
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek while iterators are running. The removed users will just be skipped over.
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek Users that are refreshed (= moved to end of list) may be processed twice.
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek Using iter_until_current_tail=TRUE causes the iterator to not iterate
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek through any users that were added/refreshed since the iteration began.
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek Note that this may skip some users entirely. */
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstruct user_directory_iter *
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekuser_directory_iter_init(struct user_directory *dir,
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek bool iter_until_current_tail);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekstruct user *user_directory_iter_next(struct user_directory_iter *iter);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozekvoid user_directory_iter_deinit(struct user_directory_iter **iter);
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek#endif
05d935cc9d04f03522d0bb44598d22d99b085926Jakub Hrozek