/Users/mcomp/contrib/bitcoin/src/common/pcp.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2024 The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or https://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_COMMON_PCP_H |
6 | | #define BITCOIN_COMMON_PCP_H |
7 | | |
8 | | #include <netaddress.h> |
9 | | |
10 | | #include <variant> |
11 | | |
12 | | // RFC6886 NAT-PMP and RFC6887 Port Control Protocol (PCP) implementation. |
13 | | // NAT-PMP and PCP use network byte order (big-endian). |
14 | | |
15 | | //! Mapping nonce size in bytes (see RFC6887 section 11.1). |
16 | | constexpr size_t PCP_MAP_NONCE_SIZE = 12; |
17 | | |
18 | | //! PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping. |
19 | | typedef std::array<uint8_t, PCP_MAP_NONCE_SIZE> PCPMappingNonce; |
20 | | |
21 | | //! Unsuccessful response to a port mapping. |
22 | | enum class MappingError { |
23 | | NETWORK_ERROR, ///< Any kind of network-level error. |
24 | | PROTOCOL_ERROR, ///< Any kind of protocol-level error, except unsupported version or no resources. |
25 | | UNSUPP_VERSION, ///< Unsupported protocol version. |
26 | | NO_RESOURCES, ///< No resources available (port probably already mapped). |
27 | | }; |
28 | | |
29 | | //! Successful response to a port mapping. |
30 | | struct MappingResult { |
31 | | MappingResult(uint8_t version, const CService &internal_in, const CService &external_in, uint32_t lifetime_in): |
32 | 0 | version(version), internal(internal_in), external(external_in), lifetime(lifetime_in) {} |
33 | | //! Protocol version, one of NATPMP_VERSION or PCP_VERSION. |
34 | | uint8_t version; |
35 | | //! Internal host:port. |
36 | | CService internal; |
37 | | //! External host:port. |
38 | | CService external; |
39 | | //! Granted lifetime of binding (seconds). |
40 | | uint32_t lifetime; |
41 | | |
42 | | //! Format mapping as string for logging. |
43 | | std::string ToString() const; |
44 | | }; |
45 | | |
46 | | //! Try to open a port using RFC 6886 NAT-PMP. IPv4 only. |
47 | | //! |
48 | | //! * gateway: Destination address for PCP requests (usually the default gateway). |
49 | | //! * port: Internal port, and desired external port. |
50 | | //! * lifetime: Requested lifetime in seconds for mapping. The server may assign as shorter or longer lifetime. A lifetime of 0 deletes the mapping. |
51 | | //! * num_tries: Number of tries in case of no response. |
52 | | //! |
53 | | //! Returns the external_ip:external_port of the mapping if successful, otherwise a MappingError. |
54 | | std::variant<MappingResult, MappingError> NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, int num_tries = 3, std::chrono::milliseconds timeout_per_try = std::chrono::milliseconds(1000)); |
55 | | |
56 | | //! Try to open a port using RFC 6887 Port Control Protocol (PCP). Handles IPv4 and IPv6. |
57 | | //! |
58 | | //! * nonce: Mapping cookie. Keep this the same over renewals. |
59 | | //! * gateway: Destination address for PCP requests (usually the default gateway). |
60 | | //! * bind: Specific local bind address for IPv6 pinholing. Set this as INADDR_ANY for IPv4. |
61 | | //! * port: Internal port, and desired external port. |
62 | | //! * lifetime: Requested lifetime in seconds for mapping. The server may assign as shorter or longer lifetime. A lifetime of 0 deletes the mapping. |
63 | | //! * num_tries: Number of tries in case of no response. |
64 | | //! |
65 | | //! Returns the external_ip:external_port of the mapping if successful, otherwise a MappingError. |
66 | | std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, int num_tries = 3, std::chrono::milliseconds timeout_per_try = std::chrono::milliseconds(1000)); |
67 | | |
68 | | #endif // BITCOIN_COMMON_PCP_H |