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