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