user-directory.c revision 2dcf09e68a6d84aba506b0a93897b186ea11520f
5e0ce63bb65db34d7f48b34bbb5545fa791781c4Timo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen/* n% of timeout_secs */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen/* but min/max. of this many secs */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* unsigned int username_hash => user */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* sorted by time */
2c25e1360d4b5cc55eda969a3a7204d950de5a8fTimo Sirainen /* If user's expire time is less than this many seconds away,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen don't assume that other directors haven't yet expired it */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void user_move_iters(struct user_directory *dir, struct user *user)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void user_free(struct user_directory *dir, struct user *user)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hash_table_remove(dir->hash, POINTER_CAST(user->username_hash));
e11a64ffc7f08b4cb05bcc27668d154d33d0c2e0Timo Sirainenstatic bool user_directory_user_has_connections(struct user_directory *dir,
e11a64ffc7f08b4cb05bcc27668d154d33d0c2e0Timo Sirainen time_t expire_timestamp = user->timestamp + dir->timeout_secs;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (user->kill_state != USER_KILL_STATE_NONE) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* don't free this user until the kill is finished */
af81f402ddc897c74c1e85abd02879612ce44882Timo Sirainen if (expire_timestamp + USER_NEAR_EXPIRING_MAX >= ioloop_time)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_warning("User %u weakness appears to be stuck, removing it",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void user_directory_drop_expired(struct user_directory *dir)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen !user_directory_user_has_connections(dir, dir->head))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstruct user *user_directory_lookup(struct user_directory *dir,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen user = hash_table_lookup(dir->hash, POINTER_CAST(username_hash));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (user != NULL && !user_directory_user_has_connections(dir, user)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenuser_directory_insert_backwards(struct user_directory *dir,
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen DLLIST2_PREPEND(&dir->head, &dir->tail, user);
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainenuser_directory_insert_forwards(struct user_directory *dir,
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainenuser_directory_add(struct user_directory *dir, unsigned int username_hash,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* make sure we don't add timestamps higher than ioloop time */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (dir->tail == NULL || (time_t)dir->tail->timestamp <= timestamp)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* need to insert to correct position. we should get here
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen only when handshaking. the handshaking USER requests should
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen come sorted by timestamp. so keep track of the previous
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen insert position, the next USER should be inserted after
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* find the position starting from tail */
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen user_directory_insert_backwards(dir, dir->tail, user);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen } else if (timestamp < (time_t)dir->prev_insert_pos->timestamp) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen user_directory_insert_backwards(dir, dir->prev_insert_pos,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen user_directory_insert_forwards(dir, dir->prev_insert_pos,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen hash_table_insert(dir->hash, POINTER_CAST(user->username_hash), user);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenvoid user_directory_refresh(struct user_directory *dir, struct user *user)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid user_directory_remove_host(struct user_directory *dir,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (user = dir->head; user != NULL; user = next) {
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenunsigned int user_directory_get_username_hash(struct user_directory *dir,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return mail_user_hash(username, dir->username_hash_fmt);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenbool user_directory_user_is_recently_updated(struct user_directory *dir,
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainen return (time_t)(user->timestamp + dir->timeout_secs/2) >= ioloop_time;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenbool user_directory_user_is_near_expiring(struct user_directory *dir,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (dir->timeout_secs - dir->user_near_expiring_secs);
03f5c621d06d6b6d77a145196c9633a7aa64dc78Timo Sirainenuser_directory_init(unsigned int timeout_secs, const char *username_hash_fmt)
return dir;
struct user_directory_iter *
return iter;
return FALSE;
return user;
unsigned int i, count;
for (i = 0; i < count; i++) {