Branch data Line data Source code
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 <netmessagemaker.h>
10 : : #include <net.h>
11 : : #include <net_permissions.h>
12 : : #include <net_processing.h>
13 : : #include <netaddress.h>
14 : : #include <node/connection_types.h>
15 : : #include <node/eviction.h>
16 : : #include <span.h>
17 : : #include <sync.h>
18 : : #include <util/sock.h>
19 : :
20 : : #include <algorithm>
21 : : #include <array>
22 : : #include <cassert>
23 : : #include <chrono>
24 : : #include <condition_variable>
25 : : #include <cstdint>
26 : : #include <cstring>
27 : : #include <memory>
28 : : #include <optional>
29 : : #include <string>
30 : : #include <unordered_map>
31 : : #include <vector>
32 : :
33 : : class FastRandomContext;
34 : :
35 : 4 : struct ConnmanTestMsg : public CConnman {
36 [ + - ]: 174 : using CConnman::CConnman;
37 : :
38 : : void SetMsgProc(NetEventsInterface* msgproc)
39 : : {
40 : : m_msgproc = msgproc;
41 : : }
42 : :
43 : 1 : void SetPeerConnectTimeout(std::chrono::seconds timeout)
44 : : {
45 [ + - ]: 1 : m_peer_connect_timeout = timeout;
46 : : }
47 : :
48 : 4 : std::vector<CNode*> TestNodes()
49 : : {
50 : 4 : LOCK(m_nodes_mutex);
51 [ + - ]: 4 : return m_nodes;
52 : 4 : }
53 : :
54 : 23 : void AddTestNode(CNode& node)
55 : : {
56 : 23 : LOCK(m_nodes_mutex);
57 [ + - ]: 23 : m_nodes.push_back(&node);
58 : :
59 [ + + + - ]: 23 : if (node.IsManualOrFullOutboundConn()) ++m_network_conn_counts[node.addr.GetNetwork()];
60 : 23 : }
61 : :
62 : 4 : void ClearTestNodes()
63 : : {
64 : 4 : LOCK(m_nodes_mutex);
65 [ + + ]: 27 : for (CNode* node : m_nodes) {
66 [ + - ]: 23 : delete node;
67 : : }
68 [ + - + - ]: 8 : m_nodes.clear();
69 : 4 : }
70 : :
71 : : void Handshake(CNode& node,
72 : : bool successfully_connected,
73 : : ServiceFlags remote_services,
74 : : ServiceFlags local_services,
75 : : int32_t version,
76 : : bool relay_txs)
77 : : EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex);
78 : :
79 : 2 : bool ProcessMessagesOnce(CNode& node) EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex)
80 : : {
81 : 2 : return m_msgproc->ProcessMessages(&node, flagInterruptMsgProc);
82 : : }
83 : :
84 : : void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const;
85 : :
86 : : bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) const;
87 : : void FlushSendBuffer(CNode& node) const;
88 : :
89 [ + - ]: 6 : bool AlreadyConnectedPublic(const CAddress& addr) { return AlreadyConnectedToAddress(addr); };
90 : :
91 : : CNode* ConnectNodePublic(PeerManager& peerman, const char* pszDest, ConnectionType conn_type)
92 : : EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
93 : : };
94 : :
95 : : constexpr ServiceFlags ALL_SERVICE_FLAGS[]{
96 : : NODE_NONE,
97 : : NODE_NETWORK,
98 : : NODE_BLOOM,
99 : : NODE_WITNESS,
100 : : NODE_COMPACT_FILTERS,
101 : : NODE_NETWORK_LIMITED,
102 : : NODE_P2P_V2,
103 : : };
104 : :
105 : : constexpr NetPermissionFlags ALL_NET_PERMISSION_FLAGS[]{
106 : : NetPermissionFlags::None,
107 : : NetPermissionFlags::BloomFilter,
108 : : NetPermissionFlags::Relay,
109 : : NetPermissionFlags::ForceRelay,
110 : : NetPermissionFlags::NoBan,
111 : : NetPermissionFlags::Mempool,
112 : : NetPermissionFlags::Addr,
113 : : NetPermissionFlags::Download,
114 : : NetPermissionFlags::Implicit,
115 : : NetPermissionFlags::All,
116 : : };
117 : :
118 : : constexpr ConnectionType ALL_CONNECTION_TYPES[]{
119 : : ConnectionType::INBOUND,
120 : : ConnectionType::OUTBOUND_FULL_RELAY,
121 : : ConnectionType::MANUAL,
122 : : ConnectionType::FEELER,
123 : : ConnectionType::BLOCK_RELAY,
124 : : ConnectionType::ADDR_FETCH,
125 : : };
126 : :
127 : : constexpr auto ALL_NETWORKS = std::array{
128 : : Network::NET_UNROUTABLE,
129 : : Network::NET_IPV4,
130 : : Network::NET_IPV6,
131 : : Network::NET_ONION,
132 : : Network::NET_I2P,
133 : : Network::NET_CJDNS,
134 : : Network::NET_INTERNAL,
135 : : };
136 : :
137 : : /**
138 : : * A mocked Sock alternative that succeeds on all operations.
139 : : * Returns infinite amount of 0x0 bytes on reads.
140 : : */
141 : : class ZeroSock : public Sock
142 : : {
143 : : public:
144 : : ZeroSock();
145 : :
146 : : ~ZeroSock() override;
147 : :
148 : : ssize_t Send(const void*, size_t len, int) const override;
149 : :
150 : : ssize_t Recv(void* buf, size_t len, int flags) const override;
151 : :
152 : : int Connect(const sockaddr*, socklen_t) const override;
153 : :
154 : : int Bind(const sockaddr*, socklen_t) const override;
155 : :
156 : : int Listen(int) const override;
157 : :
158 : : std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
159 : :
160 : : int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
161 : :
162 : : int SetSockOpt(int, int, const void*, socklen_t) const override;
163 : :
164 : : int GetSockName(sockaddr* name, socklen_t* name_len) const override;
165 : :
166 : : bool SetNonBlocking() const override;
167 : :
168 : : bool IsSelectable() const override;
169 : :
170 : : bool Wait(std::chrono::milliseconds timeout,
171 : : Event requested,
172 : : Event* occurred = nullptr) const override;
173 : :
174 : : bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
175 : :
176 : : private:
177 : : ZeroSock& operator=(Sock&& other) override;
178 : : };
179 : :
180 : : /**
181 : : * A mocked Sock alternative that returns a statically contained data upon read and succeeds
182 : : * and ignores all writes. The data to be returned is given to the constructor and when it is
183 : : * exhausted an EOF is returned by further reads.
184 : : */
185 : : class StaticContentsSock : public ZeroSock
186 : : {
187 : : public:
188 : : explicit StaticContentsSock(const std::string& contents);
189 : :
190 : : /**
191 : : * Return parts of the contents that was provided at construction until it is exhausted
192 : : * and then return 0 (EOF).
193 : : */
194 : : ssize_t Recv(void* buf, size_t len, int flags) const override;
195 : :
196 : 0 : bool IsConnected(std::string&) const override
197 : : {
198 : 0 : return true;
199 : : }
200 : :
201 : : private:
202 : : StaticContentsSock& operator=(Sock&& other) override;
203 : :
204 : : const std::string m_contents;
205 : : mutable size_t m_consumed{0};
206 : : };
207 : :
208 : : /**
209 : : * A mocked Sock alternative that allows providing the data to be returned by Recv()
210 : : * and inspecting the data that has been supplied to Send().
211 : : */
212 : : class DynSock : public ZeroSock
213 : : {
214 : : public:
215 : : /**
216 : : * Unidirectional bytes or CNetMessage queue (FIFO).
217 : : */
218 : : class Pipe
219 : : {
220 : : public:
221 : : /**
222 : : * Get bytes and remove them from the pipe.
223 : : * @param[in] buf Destination to write bytes to.
224 : : * @param[in] len Write up to this number of bytes.
225 : : * @param[in] flags Same as the flags of `recv(2)`. Just `MSG_PEEK` is honored.
226 : : * @return The number of bytes written to `buf`. `0` if `Eof()` has been called.
227 : : * If no bytes are available then `-1` is returned and `errno` is set to `EAGAIN`.
228 : : */
229 : : ssize_t GetBytes(void* buf, size_t len, int flags = 0) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
230 : :
231 : : /**
232 : : * Deserialize a `CNetMessage` and remove it from the pipe.
233 : : * If not enough bytes are available then the function will wait. If parsing fails
234 : : * or EOF is signaled to the pipe, then `std::nullopt` is returned.
235 : : */
236 : : std::optional<CNetMessage> GetNetMsg() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
237 : :
238 : : /**
239 : : * Push bytes to the pipe.
240 : : */
241 : : void PushBytes(const void* buf, size_t len) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
242 : :
243 : : /**
244 : : * Construct and push CNetMessage to the pipe.
245 : : */
246 : : template <typename... Args>
247 : : void PushNetMsg(const std::string& type, Args&&... payload) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
248 : :
249 : : /**
250 : : * Signal end-of-file on the receiving end (`GetBytes()` or `GetNetMsg()`).
251 : : */
252 : : void Eof() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
253 : :
254 : : private:
255 : : /**
256 : : * Return when there is some data to read or EOF has been signaled.
257 : : * @param[in,out] lock Unique lock that must have been derived from `m_mutex` by `WAIT_LOCK(m_mutex, lock)`.
258 : : */
259 : : void WaitForDataOrEof(UniqueLock<Mutex>& lock) EXCLUSIVE_LOCKS_REQUIRED(m_mutex);
260 : :
261 : : Mutex m_mutex;
262 : : std::condition_variable m_cond;
263 : : std::vector<uint8_t> m_data GUARDED_BY(m_mutex);
264 : : bool m_eof GUARDED_BY(m_mutex){false};
265 : : };
266 : :
267 : : struct Pipes {
268 : : Pipe recv;
269 : : Pipe send;
270 : : };
271 : :
272 : : /**
273 : : * A basic thread-safe queue, used for queuing sockets to be returned by Accept().
274 : : */
275 : : class Queue
276 : : {
277 : : public:
278 : : using S = std::unique_ptr<DynSock>;
279 : :
280 : : void Push(S s) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
281 : : {
282 : : LOCK(m_mutex);
283 : : m_queue.push(std::move(s));
284 : : }
285 : :
286 : 0 : std::optional<S> Pop() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
287 : : {
288 : 0 : LOCK(m_mutex);
289 [ # # ]: 0 : if (m_queue.empty()) {
290 : 0 : return std::nullopt;
291 : : }
292 : 0 : S front{std::move(m_queue.front())};
293 : 0 : m_queue.pop();
294 : 0 : return front;
295 : 0 : }
296 : :
297 : 0 : bool Empty() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
298 : : {
299 : 0 : LOCK(m_mutex);
300 [ # # ]: 0 : return m_queue.empty();
301 : 0 : }
302 : :
303 : : private:
304 : : mutable Mutex m_mutex;
305 : : std::queue<S> m_queue GUARDED_BY(m_mutex);
306 : : };
307 : :
308 : : /**
309 : : * Create a new mocked sock.
310 : : * @param[in] pipes Send/recv pipes used by the Send() and Recv() methods.
311 : : * @param[in] accept_sockets Sockets to return by the Accept() method.
312 : : */
313 : : explicit DynSock(std::shared_ptr<Pipes> pipes, std::shared_ptr<Queue> accept_sockets);
314 : :
315 : : ~DynSock();
316 : :
317 : : ssize_t Recv(void* buf, size_t len, int flags) const override;
318 : :
319 : : ssize_t Send(const void* buf, size_t len, int) const override;
320 : :
321 : : std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
322 : :
323 : : bool Wait(std::chrono::milliseconds timeout,
324 : : Event requested,
325 : : Event* occurred = nullptr) const override;
326 : :
327 : : bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
328 : :
329 : : private:
330 : : DynSock& operator=(Sock&&) override;
331 : :
332 : : std::shared_ptr<Pipes> m_pipes;
333 : : std::shared_ptr<Queue> m_accept_sockets;
334 : : };
335 : :
336 : : template <typename... Args>
337 : : void DynSock::Pipe::PushNetMsg(const std::string& type, Args&&... payload)
338 : : {
339 : : auto msg = NetMsg::Make(type, std::forward<Args>(payload)...);
340 : : V1Transport transport{NodeId{0}};
341 : :
342 : : const bool queued{transport.SetMessageToSend(msg)};
343 : : assert(queued);
344 : :
345 : : LOCK(m_mutex);
346 : :
347 : : for (;;) {
348 : : const auto& [bytes, _more, _msg_type] = transport.GetBytesToSend(/*have_next_message=*/true);
349 : : if (bytes.empty()) {
350 : : break;
351 : : }
352 : : m_data.insert(m_data.end(), bytes.begin(), bytes.end());
353 : : transport.MarkBytesSent(bytes.size());
354 : : }
355 : :
356 : : m_cond.notify_all();
357 : : }
358 : :
359 : : std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candidates, FastRandomContext& random_context);
360 : :
361 : : #endif // BITCOIN_TEST_UTIL_NET_H
|