user-directory.c revision 7d8c1ba766770ea1c6d4d6770a31832b5b518648
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen/* n% of timeout_secs */
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen/* but min/max. of this many secs */
105addcb709523868418cc3e3baad7ad3453a91eTimo Sirainen/* This shouldn't matter what it is exactly, just try it sometimes later. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* unsigned int username_hash => user */
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen /* sorted by time */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* If user's expire time is less than this many seconds away,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen don't assume that other directors haven't yet expired it */
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainenstatic void user_move_iters(struct user_directory *dir, struct user *user)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void user_free(struct user_directory *dir, struct user *user)
659fe5d24825b160cae512538088020d97a60239Timo Sirainen hash_table_remove(dir->hash, POINTER_CAST(user->username_hash));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic bool user_directory_user_has_connections(struct user_directory *dir,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen time_t expire_timestamp = user->timestamp + dir->timeout_secs;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *retry_secs_r = expire_timestamp - ioloop_time;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* don't free this user until the kill is finished */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen *retry_secs_r = USER_BEING_KILLED_EXPIRE_RETRY_SECS;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (expire_timestamp + USER_NEAR_EXPIRING_MAX > ioloop_time) {
838f56174b963779a88083a0d0e85b30d2d846e7Timo Sirainen i_warning("User %u weakness appears to be stuck, removing it",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic void user_directory_drop_expired(struct user_directory *dir)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen unsigned int retry_secs = 0;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen !user_directory_user_has_connections(dir, dir->head, &retry_secs))
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen dir->to_expire = timeout_add(retry_secs * 1000,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenunsigned int user_directory_count(struct user_directory *dir)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstruct user *user_directory_lookup(struct user_directory *dir,
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen user = hash_table_lookup(dir->hash, POINTER_CAST(username_hash));
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen if (user != NULL && !user_directory_user_has_connections(dir, user, &retry_secs)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenuser_directory_insert_backwards(struct user_directory *dir,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen DLLIST2_PREPEND(&dir->head, &dir->tail, user);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenuser_directory_insert_forwards(struct user_directory *dir,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenuser_directory_add(struct user_directory *dir, unsigned int username_hash,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen /* make sure we don't add timestamps higher than ioloop time */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen if (dir->tail == NULL || (time_t)dir->tail->timestamp <= timestamp)
c9c24293550541307f1bb41bba4a0fdfe2fa59e0Timo Sirainen /* need to insert to correct position. we should get here
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen only when handshaking. the handshaking USER requests should
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen come sorted by timestamp. so keep track of the previous
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen insert position, the next USER should be inserted after
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen /* find the position starting from tail */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen user_directory_insert_backwards(dir, dir->tail, user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (timestamp < (time_t)dir->prev_insert_pos->timestamp) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user_directory_insert_backwards(dir, dir->prev_insert_pos,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user_directory_insert_forwards(dir, dir->prev_insert_pos,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dir->to_expire = timeout_add(dir->timeout_secs * 1000,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hash_table_insert(dir->hash, POINTER_CAST(user->username_hash), user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid user_directory_refresh(struct user_directory *dir, struct user *user)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid user_directory_remove_host(struct user_directory *dir,
if (users_count == 0) {
struct user_directory *
return dir;
struct user_directory_iter *
return iter;
return NULL;
return user;
unsigned int i, count;
for (i = 0; i < count; i++) {