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 <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 : 4 : struct ConnmanTestMsg : public CConnman {
35 [ + - ]: 169 : using CConnman::CConnman;
36 : :
37 : : void SetMsgProc(NetEventsInterface* msgproc)
38 : : {
39 : : m_msgproc = msgproc;
40 : : }
41 : :
42 : 1 : void SetPeerConnectTimeout(std::chrono::seconds timeout)
43 : : {
44 [ + - ]: 1 : m_peer_connect_timeout = timeout;
45 : : }
46 : :
47 : 4 : std::vector<CNode*> TestNodes()
48 : : {
49 : 4 : LOCK(m_nodes_mutex);
50 [ + - ]: 4 : return m_nodes;
51 : 4 : }
52 : :
53 : 23 : void AddTestNode(CNode& node)
54 : : {
55 : 23 : LOCK(m_nodes_mutex);
56 [ + - ]: 23 : m_nodes.push_back(&node);
57 : :
58 [ + + + - ]: 23 : if (node.IsManualOrFullOutboundConn()) ++m_network_conn_counts[node.addr.GetNetwork()];
59 : 23 : }
60 : :
61 : 4 : void ClearTestNodes()
62 : : {
63 : 4 : LOCK(m_nodes_mutex);
64 [ + + ]: 27 : for (CNode* node : m_nodes) {
65 [ + - ]: 23 : delete node;
66 : : }
67 [ + - + - ]: 8 : m_nodes.clear();
68 : 4 : }
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 : 2 : bool ProcessMessagesOnce(CNode& node) EXCLUSIVE_LOCKS_REQUIRED(NetEventsInterface::g_msgproc_mutex)
79 : : {
80 : 2 : return m_msgproc->ProcessMessages(&node, flagInterruptMsgProc);
81 : : }
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 [ + - ]: 6 : 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 : 16 : explicit StaticContentsSock(const std::string& contents)
145 : 16 : : Sock{INVALID_SOCKET},
146 [ + - ]: 16 : m_contents{contents}
147 : : {
148 : 16 : }
149 : :
150 : 32 : ~StaticContentsSock() override { m_socket = INVALID_SOCKET; }
151 : :
152 : 0 : StaticContentsSock& operator=(Sock&& other) override
153 : : {
154 : 0 : assert(false && "Move of Sock into MockSock not allowed.");
155 : : return *this;
156 : : }
157 : :
158 : 32 : ssize_t Send(const void*, size_t len, int) const override { return len; }
159 : :
160 : 332 : ssize_t Recv(void* buf, size_t len, int flags) const override
161 : : {
162 [ + + ]: 332 : const size_t consume_bytes{std::min(len, m_contents.size() - m_consumed)};
163 [ + + ]: 332 : std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes);
164 [ + + ]: 332 : if ((flags & MSG_PEEK) == 0) {
165 : 166 : m_consumed += consume_bytes;
166 : : }
167 : 332 : return consume_bytes;
168 : : }
169 : :
170 : 16 : 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 : 0 : std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override
177 : : {
178 [ # # ]: 0 : if (addr != nullptr) {
179 : : // 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 : : }
189 : : }
190 : 0 : return std::make_unique<StaticContentsSock>("");
191 : : };
192 : :
193 : 0 : int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override
194 : : {
195 : 0 : std::memset(opt_val, 0x0, *opt_len);
196 : 0 : return 0;
197 : : }
198 : :
199 : 0 : int SetSockOpt(int, int, const void*, socklen_t) const override { return 0; }
200 : :
201 : 0 : int GetSockName(sockaddr* name, socklen_t* name_len) const override
202 : : {
203 : 0 : std::memset(name, 0x0, *name_len);
204 : 0 : return 0;
205 : : }
206 : :
207 : 0 : bool SetNonBlocking() const override { return true; }
208 : :
209 : 0 : bool IsSelectable() const override { return true; }
210 : :
211 : 135 : bool Wait(std::chrono::milliseconds timeout,
212 : : Event requested,
213 : : Event* occurred = nullptr) const override
214 : : {
215 [ + + ]: 135 : if (occurred != nullptr) {
216 : 5 : *occurred = requested;
217 : : }
218 : 135 : return true;
219 : : }
220 : :
221 : 0 : bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override
222 : : {
223 [ # # ]: 0 : for (auto& [sock, events] : events_per_sock) {
224 : 0 : (void)sock;
225 : 0 : events.occurred = events.requested;
226 : : }
227 : 0 : return true;
228 : : }
229 : :
230 : 0 : bool IsConnected(std::string&) const override
231 : : {
232 : 0 : return true;
233 : : }
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
|