Coverage Report

Created: 2024-10-29 12:15

/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