1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "hash.h"
#include "llist.h"
#include "global-memory.h"
#include "stats-settings.h"
#include "mail-stats.h"
#include "mail-ip.h"
static HASH_TABLE(struct ip_addr *, struct mail_ip *) mail_ips_hash;
/* ips are sorted by their last_update timestamp, oldest first */
static struct mail_ip *mail_ips_head, *mail_ips_tail;
struct mail_ip *stable_mail_ips;
static size_t mail_ip_memsize(const struct mail_ip *ip)
{
return sizeof(*ip);
}
struct mail_ip *mail_ip_login(const struct ip_addr *ip_addr)
{
struct mail_ip *ip;
ip = hash_table_lookup(mail_ips_hash, ip_addr);
if (ip != NULL) {
ip->num_logins++;
ip->num_connected_sessions++;
mail_ip_refresh(ip, NULL);
return ip;
}
ip = i_malloc(MALLOC_ADD(sizeof(struct mail_ip), stats_alloc_size()));
ip->stats = (void *)(ip + 1);
ip->ip = *ip_addr;
ip->reset_timestamp = ioloop_time;
hash_table_insert(mail_ips_hash, &ip->ip, ip);
DLLIST_PREPEND_FULL(&stable_mail_ips, ip, stable_prev, stable_next);
DLLIST2_APPEND_FULL(&mail_ips_head, &mail_ips_tail, ip,
sorted_prev, sorted_next);
ip->num_logins++;
ip->num_connected_sessions++;
ip->last_update = ioloop_timeval;
global_memory_alloc(mail_ip_memsize(ip));
return ip;
}
void mail_ip_disconnected(struct mail_ip *ip)
{
i_assert(ip->num_connected_sessions > 0);
ip->num_connected_sessions--;
}
struct mail_ip *mail_ip_lookup(const struct ip_addr *ip_addr)
{
return hash_table_lookup(mail_ips_hash, ip_addr);
}
void mail_ip_ref(struct mail_ip *ip)
{
ip->refcount++;
}
void mail_ip_unref(struct mail_ip **_ip)
{
struct mail_ip *ip = *_ip;
i_assert(ip->refcount > 0);
ip->refcount--;
*_ip = NULL;
}
static void mail_ip_free(struct mail_ip *ip)
{
i_assert(ip->refcount == 0);
i_assert(ip->sessions == NULL);
global_memory_free(mail_ip_memsize(ip));
hash_table_remove(mail_ips_hash, &ip->ip);
DLLIST_REMOVE_FULL(&stable_mail_ips, ip, stable_prev, stable_next);
DLLIST2_REMOVE_FULL(&mail_ips_head, &mail_ips_tail, ip,
sorted_prev, sorted_next);
i_free(ip);
}
void mail_ip_refresh(struct mail_ip *ip, const struct stats *diff_stats)
{
if (diff_stats != NULL)
stats_add(ip->stats, diff_stats);
ip->last_update = ioloop_timeval;
DLLIST2_REMOVE_FULL(&mail_ips_head, &mail_ips_tail, ip,
sorted_prev, sorted_next);
DLLIST2_APPEND_FULL(&mail_ips_head, &mail_ips_tail, ip,
sorted_prev, sorted_next);
}
void mail_ips_free_memory(void)
{
unsigned int diff;
while (mail_ips_head != NULL && mail_ips_head->refcount == 0) {
mail_ip_free(mail_ips_head);
if (global_used_memory < stats_settings->memory_limit ||
mail_ips_head == NULL)
break;
diff = ioloop_time - mail_ips_head->last_update.tv_sec;
if (diff < stats_settings->ip_min_time)
break;
}
}
void mail_ips_init(void)
{
hash_table_create(&mail_ips_hash, default_pool, 0,
net_ip_hash, net_ip_cmp);
}
void mail_ips_deinit(void)
{
while (mail_ips_head != NULL)
mail_ip_free(mail_ips_head);
hash_table_destroy(&mail_ips_hash);
}
|