/root/bitcoin/src/banman.cpp
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present The Bitcoin Core developers |
3 | | // Distributed under the MIT software license, see the accompanying |
4 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | | |
6 | | #include <banman.h> |
7 | | |
8 | | #include <common/system.h> |
9 | | #include <netaddress.h> |
10 | | #include <node/interface_ui.h> |
11 | | #include <sync.h> |
12 | | #include <util/log.h> |
13 | | #include <util/time.h> |
14 | | #include <util/translation.h> |
15 | | |
16 | | |
17 | | BanMan::BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time) |
18 | 4.61k | : m_client_interface(client_interface), m_ban_db(std::move(ban_file)), m_default_ban_time(default_ban_time) |
19 | 4.61k | { |
20 | 4.61k | LoadBanlist(); |
21 | 4.61k | DumpBanlist(); |
22 | 4.61k | } |
23 | | |
24 | | BanMan::~BanMan() |
25 | 4.64k | { |
26 | 4.64k | DumpBanlist(); |
27 | 4.64k | } |
28 | | |
29 | | void BanMan::LoadBanlist() |
30 | 4.61k | { |
31 | 4.61k | LOCK(m_banned_mutex); |
32 | | |
33 | 4.61k | if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist…")); Branch (33:9): [True: 0, False: 4.61k]
|
34 | | |
35 | 4.61k | const auto start{SteadyClock::now()}; |
36 | 4.61k | if (m_ban_db.Read(m_banned)) { Branch (36:9): [True: 2.61k, False: 1.99k]
|
37 | 2.61k | SweepBanned(); // sweep out unused entries |
38 | | |
39 | 2.61k | LogDebug(BCLog::NET, "Loaded %d banned node addresses/subnets %dms", m_banned.size(), |
40 | 2.61k | Ticks<std::chrono::milliseconds>(SteadyClock::now() - start)); |
41 | 2.61k | } else { |
42 | 1.99k | LogInfo("Recreating the banlist database"); |
43 | 1.99k | m_banned = {}; |
44 | 1.99k | m_is_dirty = true; |
45 | 1.99k | } |
46 | 4.61k | } |
47 | | |
48 | | void BanMan::DumpBanlist() |
49 | 50.2k | { |
50 | 50.2k | static Mutex dump_mutex; |
51 | 50.2k | LOCK(dump_mutex); |
52 | | |
53 | 50.2k | banmap_t banmap; |
54 | 50.2k | { |
55 | 50.2k | LOCK(m_banned_mutex); |
56 | 50.2k | SweepBanned(); |
57 | 50.2k | if (!m_is_dirty) return; Branch (57:13): [True: 10.2k, False: 40.0k]
|
58 | 40.0k | banmap = m_banned; |
59 | 40.0k | m_is_dirty = false; |
60 | 40.0k | } |
61 | | |
62 | 0 | const auto start{SteadyClock::now()}; |
63 | 40.0k | if (!m_ban_db.Write(banmap)) { Branch (63:9): [True: 8.56k, False: 31.4k]
|
64 | 8.56k | LOCK(m_banned_mutex); |
65 | 8.56k | m_is_dirty = true; |
66 | 8.56k | } |
67 | | |
68 | 40.0k | LogDebug(BCLog::NET, "Flushed %d banned node addresses/subnets to disk %dms", banmap.size(), |
69 | 40.0k | Ticks<std::chrono::milliseconds>(SteadyClock::now() - start)); |
70 | 40.0k | } |
71 | | |
72 | | void BanMan::ClearBanned() |
73 | 4.98k | { |
74 | 4.98k | { |
75 | 4.98k | LOCK(m_banned_mutex); |
76 | 4.98k | m_banned.clear(); |
77 | 4.98k | m_is_dirty = true; |
78 | 4.98k | } |
79 | 4.98k | DumpBanlist(); //store banlist to disk |
80 | 4.98k | if (m_client_interface) m_client_interface->BannedListChanged(); Branch (80:9): [True: 0, False: 4.98k]
|
81 | 4.98k | } |
82 | | |
83 | | bool BanMan::IsDiscouraged(const CNetAddr& net_addr) |
84 | 6.44k | { |
85 | 6.44k | LOCK(m_banned_mutex); |
86 | 6.44k | return m_discouraged.contains(net_addr.GetAddrBytes()); |
87 | 6.44k | } |
88 | | |
89 | | bool BanMan::IsBanned(const CNetAddr& net_addr) |
90 | 6.43k | { |
91 | 6.43k | auto current_time = GetTime(); |
92 | 6.43k | LOCK(m_banned_mutex); |
93 | 103k | for (const auto& it : m_banned) { Branch (93:25): [True: 103k, False: 4.57k]
|
94 | 103k | CSubNet sub_net = it.first; |
95 | 103k | CBanEntry ban_entry = it.second; |
96 | | |
97 | 103k | if (current_time < ban_entry.nBanUntil && sub_net.Match(net_addr)) { Branch (97:13): [True: 94.8k, False: 8.34k]
Branch (97:51): [True: 1.85k, False: 93.0k]
|
98 | 1.85k | return true; |
99 | 1.85k | } |
100 | 103k | } |
101 | 4.57k | return false; |
102 | 6.43k | } |
103 | | |
104 | | bool BanMan::IsBanned(const CSubNet& sub_net) |
105 | 4.59k | { |
106 | 4.59k | auto current_time = GetTime(); |
107 | 4.59k | LOCK(m_banned_mutex); |
108 | 4.59k | banmap_t::iterator i = m_banned.find(sub_net); |
109 | 4.59k | if (i != m_banned.end()) { Branch (109:9): [True: 1.81k, False: 2.78k]
|
110 | 1.81k | CBanEntry ban_entry = (*i).second; |
111 | 1.81k | if (current_time < ban_entry.nBanUntil) { Branch (111:13): [True: 1.08k, False: 728]
|
112 | 1.08k | return true; |
113 | 1.08k | } |
114 | 1.81k | } |
115 | 3.51k | return false; |
116 | 4.59k | } |
117 | | |
118 | | void BanMan::Ban(const CNetAddr& net_addr, int64_t ban_time_offset, bool since_unix_epoch) |
119 | 34.6k | { |
120 | 34.6k | CSubNet sub_net(net_addr); |
121 | 34.6k | Ban(sub_net, ban_time_offset, since_unix_epoch); |
122 | 34.6k | } |
123 | | |
124 | | void BanMan::Discourage(const CNetAddr& net_addr) |
125 | 4.72k | { |
126 | 4.72k | LOCK(m_banned_mutex); |
127 | 4.72k | m_discouraged.insert(net_addr.GetAddrBytes()); |
128 | 4.72k | } |
129 | | |
130 | | void BanMan::Ban(const CSubNet& sub_net, int64_t ban_time_offset, bool since_unix_epoch) |
131 | 42.2k | { |
132 | 42.2k | CBanEntry ban_entry(GetTime()); |
133 | | |
134 | 42.2k | int64_t normalized_ban_time_offset = ban_time_offset; |
135 | 42.2k | bool normalized_since_unix_epoch = since_unix_epoch; |
136 | 42.2k | if (ban_time_offset <= 0) { Branch (136:9): [True: 41.1k, False: 1.08k]
|
137 | 41.1k | normalized_ban_time_offset = m_default_ban_time; |
138 | 41.1k | normalized_since_unix_epoch = false; |
139 | 41.1k | } |
140 | 42.2k | ban_entry.nBanUntil = (normalized_since_unix_epoch ? 0 : GetTime()) + normalized_ban_time_offset; Branch (140:28): [True: 716, False: 41.5k]
|
141 | | |
142 | 42.2k | { |
143 | 42.2k | LOCK(m_banned_mutex); |
144 | 42.2k | if (m_banned[sub_net].nBanUntil < ban_entry.nBanUntil) { Branch (144:13): [True: 25.8k, False: 16.4k]
|
145 | 25.8k | m_banned[sub_net] = ban_entry; |
146 | 25.8k | m_is_dirty = true; |
147 | 25.8k | } else |
148 | 16.4k | return; |
149 | 42.2k | } |
150 | 25.8k | if (m_client_interface) m_client_interface->BannedListChanged(); Branch (150:9): [True: 0, False: 25.8k]
|
151 | | |
152 | | //store banlist to disk immediately |
153 | 25.8k | DumpBanlist(); |
154 | 25.8k | } |
155 | | |
156 | | bool BanMan::Unban(const CNetAddr& net_addr) |
157 | 6.05k | { |
158 | 6.05k | CSubNet sub_net(net_addr); |
159 | 6.05k | return Unban(sub_net); |
160 | 6.05k | } |
161 | | |
162 | | bool BanMan::Unban(const CSubNet& sub_net) |
163 | 8.83k | { |
164 | 8.83k | { |
165 | 8.83k | LOCK(m_banned_mutex); |
166 | 8.83k | if (m_banned.erase(sub_net) == 0) return false; Branch (166:13): [True: 6.77k, False: 2.05k]
|
167 | 2.05k | m_is_dirty = true; |
168 | 2.05k | } |
169 | 2.05k | if (m_client_interface) m_client_interface->BannedListChanged(); Branch (169:9): [True: 0, False: 2.05k]
|
170 | 2.05k | DumpBanlist(); //store banlist to disk immediately |
171 | 2.05k | return true; |
172 | 8.83k | } |
173 | | |
174 | | void BanMan::GetBanned(banmap_t& banmap) |
175 | 6.53k | { |
176 | 6.53k | LOCK(m_banned_mutex); |
177 | | // Sweep the banlist so expired bans are not returned |
178 | 6.53k | SweepBanned(); |
179 | 6.53k | banmap = m_banned; //create a thread safe copy |
180 | 6.53k | } |
181 | | |
182 | | void BanMan::SweepBanned() |
183 | 59.3k | { |
184 | 59.3k | AssertLockHeld(m_banned_mutex); |
185 | | |
186 | 59.3k | int64_t now = GetTime(); |
187 | 59.3k | bool notify_ui = false; |
188 | 59.3k | banmap_t::iterator it = m_banned.begin(); |
189 | 1.61M | while (it != m_banned.end()) { Branch (189:12): [True: 1.55M, False: 59.3k]
|
190 | 1.55M | CSubNet sub_net = (*it).first; |
191 | 1.55M | CBanEntry ban_entry = (*it).second; |
192 | 1.55M | if (!sub_net.IsValid() || now > ban_entry.nBanUntil) { Branch (192:13): [True: 2.69k, False: 1.55M]
Branch (192:35): [True: 5.93k, False: 1.54M]
|
193 | 8.62k | m_banned.erase(it++); |
194 | 8.62k | m_is_dirty = true; |
195 | 8.62k | notify_ui = true; |
196 | 8.62k | LogDebug(BCLog::NET, "Removed banned node address/subnet: %s\n", sub_net.ToString()); |
197 | 1.54M | } else { |
198 | 1.54M | ++it; |
199 | 1.54M | } |
200 | 1.55M | } |
201 | | |
202 | | // update UI |
203 | 59.3k | if (notify_ui && m_client_interface) { Branch (203:9): [True: 4.48k, False: 54.8k]
Branch (203:22): [True: 0, False: 4.48k]
|
204 | 0 | m_client_interface->BannedListChanged(); |
205 | 0 | } |
206 | 59.3k | } |