/root/bitcoin/src/test/util/net.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2020-2022 The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_TEST_UTIL_NET_H |
6 | | #define BITCOIN_TEST_UTIL_NET_H |
7 | | |
8 | | #include <compat/compat.h> |
9 | | #include <net.h> |
10 | | #include <net_permissions.h> |
11 | | #include <net_processing.h> |
12 | | #include <netaddress.h> |
13 | | #include <node/connection_types.h> |
14 | | #include <node/eviction.h> |
15 | | #include <sync.h> |
16 | | #include <util/sock.h> |
17 | | |
18 | | #include <algorithm> |
19 | | #include <array> |
20 | | #include <cassert> |
21 | | #include <chrono> |
22 | | #include <cstdint> |
23 | | #include <cstring> |
24 | | #include <memory> |
25 | | #include <string> |
26 | | #include <unordered_map> |
27 | | #include <vector> |
28 | | |
29 | | class FastRandomContext; |
30 | | |
31 | | template <typename C> |
32 | | class Span; |
33 | | |
34 | | struct ConnmanTestMsg : public CConnman { |
35 | | using CConnman::CConnman; |
36 | | |
37 | | void SetMsgProc(NetEventsInterface* msgproc) |
38 | 0 | { |
39 | 0 | m_msgproc = msgproc; |
40 | 0 | } |
41 | | |
42 | | void SetPeerConnectTimeout(std::chrono::seconds timeout) |
43 | 0 | { |
44 | 0 | m_peer_connect_timeout = timeout; |
45 | 0 | } |
46 | | |
47 | | std::vector<CNode*> TestNodes() |
48 | 0 | { |
49 | 0 | LOCK(m_nodes_mutex); |
50 | 0 | return m_nodes; |
51 | 0 | } |
52 | | |
53 | | void AddTestNode(CNode& node) |
54 | 0 | { |
55 | 0 | LOCK(m_nodes_mutex); |
56 | 0 | m_nodes.push_back(&node); |
57 | |
|
58 | 0 | if (node.IsManualOrFullOutboundConn()) ++m_network_conn_counts[node.addr.GetNetwork()]; |
59 | 0 | } |
60 | | |
61 | | void ClearTestNodes() |
62 | 0 | { |
63 | 0 | LOCK(m_nodes_mutex); |
64 | 0 | for (CNode* node : m_nodes) { |
65 | 0 | delete node; |
66 | 0 | } |
67 | 0 | m_nodes.clear(); |
68 | 0 | } |
69 | | |
70 | | void Handshake(CNode& node, |
71 | | bool successfully_connected, |
72 | | ServiceFlags remote_services, |
73 | | ServiceFlags local_services, |
74 | | int32_t version, |
75 | | bool relay_txs) |
76 | | EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex); |
77 | | |
78 | | bool ProcessMessagesOnce(CNode& node) EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex) |
79 | 0 | { |
80 | 0 | return m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); |
81 | 0 | } |
82 | | |
83 | | void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const; |
84 | | |
85 | | bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) const; |
86 | | void FlushSendBuffer(CNode& node) const; |
87 | | |
88 | 0 | bool AlreadyConnectedPublic(const CAddress& addr) { return AlreadyConnectedToAddress(addr); }; |
89 | | |
90 | | CNode* ConnectNodePublic(PeerManager& peerman, const char* pszDest, ConnectionType conn_type) |
91 | | EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); |
92 | | }; |
93 | | |
94 | | constexpr ServiceFlags ALL_SERVICE_FLAGS[]{ |
95 | | NODE_NONE, |
96 | | NODE_NETWORK, |
97 | | NODE_BLOOM, |
98 | | NODE_WITNESS, |
99 | | NODE_COMPACT_FILTERS, |
100 | | NODE_NETWORK_LIMITED, |
101 | | NODE_P2P_V2, |
102 | | }; |
103 | | |
104 | | constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]{ |
105 | | NetPermissionFlags::None, |
106 | | NetPermissionFlags::BloomFilter, |
107 | | NetPermissionFlags::Relay, |
108 | | NetPermissionFlags::ForceRelay, |
109 | | NetPermissionFlags::NoBan, |
110 | | NetPermissionFlags::Mempool, |
111 | | NetPermissionFlags::Addr, |
112 | | NetPermissionFlags::Download, |
113 | | NetPermissionFlags::Implicit, |
114 | | NetPermissionFlags::All, |
115 | | }; |
116 | | |
117 | | constexpr ConnectionType ALL_CONNECTION_TYPES[]{ |
118 | | ConnectionType::INBOUND, |
119 | | ConnectionType::OUTBOUND_FULL_RELAY, |
120 | | ConnectionType::MANUAL, |
121 | | ConnectionType::FEELER, |
122 | | ConnectionType::BLOCK_RELAY, |
123 | | ConnectionType::ADDR_FETCH, |
124 | | }; |
125 | | |
126 | | constexpr auto ALL_NETWORKS = std::array{ |
127 | | Network::NET_UNROUTABLE, |
128 | | Network::NET_IPV4, |
129 | | Network::NET_IPV6, |
130 | | Network::NET_ONION, |
131 | | Network::NET_I2P, |
132 | | Network::NET_CJDNS, |
133 | | Network::NET_INTERNAL, |
134 | | }; |
135 | | |
136 | | /** |
137 | | * A mocked Sock alternative that returns a statically contained data upon read and succeeds |
138 | | * and ignores all writes. The data to be returned is given to the constructor and when it is |
139 | | * exhausted an EOF is returned by further reads. |
140 | | */ |
141 | | class StaticContentsSock : public Sock |
142 | | { |
143 | | public: |
144 | | explicit StaticContentsSock(const std::string& contents) |
145 | | : Sock{INVALID_SOCKET}, |
146 | | m_contents{contents} |
147 | 0 | { |
148 | 0 | } |
149 | | |
150 | 0 | ~StaticContentsSock() override { m_socket = INVALID_SOCKET; } |
151 | | |
152 | | StaticContentsSock& operator=(Sock&& other) override |
153 | 0 | { |
154 | 0 | assert(false && "Move of Sock into MockSock not allowed."); |
155 | 0 | return *this; |
156 | 0 | } |
157 | | |
158 | 0 | ssize_t Send(const void*, size_t len, int) const override { return len; } |
159 | | |
160 | | ssize_t Recv(void* buf, size_t len, int flags) const override |
161 | 0 | { |
162 | 0 | const size_t consume_bytes{std::min(len, m_contents.size() - m_consumed)}; |
163 | 0 | std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes); |
164 | 0 | if ((flags & MSG_PEEK) == 0) { |
165 | 0 | m_consumed += consume_bytes; |
166 | 0 | } |
167 | 0 | return consume_bytes; |
168 | 0 | } |
169 | | |
170 | 0 | int Connect(const sockaddr*, socklen_t) const override { return 0; } |
171 | | |
172 | 0 | int Bind(const sockaddr*, socklen_t) const override { return 0; } |
173 | | |
174 | 0 | int Listen(int) const override { return 0; } |
175 | | |
176 | | std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override |
177 | 0 | { |
178 | 0 | if (addr != nullptr) { |
179 | 0 | // Pretend all connections come from 5.5.5.5:6789 |
180 | 0 | memset(addr, 0x00, *addr_len); |
181 | 0 | const socklen_t write_len = static_cast<socklen_t>(sizeof(sockaddr_in)); |
182 | 0 | if (*addr_len >= write_len) { |
183 | 0 | *addr_len = write_len; |
184 | 0 | sockaddr_in* addr_in = reinterpret_cast<sockaddr_in*>(addr); |
185 | 0 | addr_in->sin_family = AF_INET; |
186 | 0 | memset(&addr_in->sin_addr, 0x05, sizeof(addr_in->sin_addr)); |
187 | 0 | addr_in->sin_port = htons(6789); |
188 | 0 | } |
189 | 0 | } |
190 | 0 | return std::make_unique<StaticContentsSock>(""); |
191 | 0 | }; |
192 | | |
193 | | int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override |
194 | 0 | { |
195 | 0 | std::memset(opt_val, 0x0, *opt_len); |
196 | 0 | return 0; |
197 | 0 | } |
198 | | |
199 | 0 | int SetSockOpt(int, int, const void*, socklen_t) const override { return 0; } |
200 | | |
201 | | int GetSockName(sockaddr* name, socklen_t* name_len) const override |
202 | 0 | { |
203 | 0 | std::memset(name, 0x0, *name_len); |
204 | 0 | return 0; |
205 | 0 | } |
206 | | |
207 | 0 | bool SetNonBlocking() const override { return true; } |
208 | | |
209 | 0 | bool IsSelectable() const override { return true; } |
210 | | |
211 | | bool Wait(std::chrono::milliseconds timeout, |
212 | | Event requested, |
213 | | Event* occurred = nullptr) const override |
214 | 0 | { |
215 | 0 | if (occurred != nullptr) { |
216 | 0 | *occurred = requested; |
217 | 0 | } |
218 | 0 | return true; |
219 | 0 | } |
220 | | |
221 | | bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override |
222 | 0 | { |
223 | 0 | for (auto& [sock, events] : events_per_sock) { |
224 | 0 | (void)sock; |
225 | 0 | events.occurred = events.requested; |
226 | 0 | } |
227 | 0 | return true; |
228 | 0 | } |
229 | | |
230 | | bool IsConnected(std::string&) const override |
231 | 0 | { |
232 | 0 | return true; |
233 | 0 | } |
234 | | |
235 | | private: |
236 | | const std::string m_contents; |
237 | | mutable size_t m_consumed{0}; |
238 | | }; |
239 | | |
240 | | std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context); |
241 | | |
242 | | #endif // BITCOIN_TEST_UTIL_NET_H |