MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / ProcessPCP

Function ProcessPCP

src/mapport.cpp:33–120  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

31static constexpr auto PORT_MAPPING_RETRY_PERIOD{5min};
32
33static void ProcessPCP()
34{
35 // The same nonce is used for all mappings, this is allowed by the spec, and simplifies keeping track of them.
36 PCPMappingNonce pcp_nonce;
37 GetRandBytes(pcp_nonce);
38
39 bool ret = false;
40 bool no_resources = false;
41 const uint16_t private_port = GetListenPort();
42 // Multiply the reannounce period by two, as we'll try to renew approximately halfway.
43 const uint32_t requested_lifetime = std::chrono::seconds(PORT_MAPPING_REANNOUNCE_PERIOD * 2).count();
44 uint32_t actual_lifetime = 0;
45 std::chrono::milliseconds sleep_time;
46
47 // Local functor to handle result from PCP/NATPMP mapping.
48 auto handle_mapping = [&](std::variant<MappingResult, MappingError> &res) -> void {
49 if (MappingResult* mapping = std::get_if<MappingResult>(&res)) {
50 LogInfo("portmap: Added mapping %s", mapping->ToString());
51 AddLocal(mapping->external, LOCAL_MAPPED);
52 ret = true;
53 actual_lifetime = std::min(actual_lifetime, mapping->lifetime);
54 } else if (MappingError *err = std::get_if<MappingError>(&res)) {
55 // Detailed error will already have been logged internally in respective Portmap function.
56 if (*err == MappingError::NO_RESOURCES) {
57 no_resources = true;
58 }
59 }
60 };
61
62 do {
63 actual_lifetime = requested_lifetime;
64 no_resources = false; // Set to true if there was any "no resources" error.
65 ret = false; // Set to true if any mapping succeeds.
66
67 // IPv4
68 std::optional<CNetAddr> gateway4 = QueryDefaultGateway(NET_IPV4);
69 if (!gateway4) {
70 LogDebug(BCLog::NET, "portmap: Could not determine IPv4 default gateway\n");
71 } else {
72 LogDebug(BCLog::NET, "portmap: gateway [IPv4]: %s\n", gateway4->ToStringAddr());
73
74 // Open a port mapping on whatever local address we have toward the gateway.
75 struct in_addr inaddr_any;
76 inaddr_any.s_addr = htonl(INADDR_ANY);
77 auto res = PCPRequestPortMap(pcp_nonce, *gateway4, CNetAddr(inaddr_any), private_port, requested_lifetime, g_mapport_interrupt);
78 MappingError* pcp_err = std::get_if<MappingError>(&res);
79 if (pcp_err && *pcp_err == MappingError::UNSUPP_VERSION) {
80 LogDebug(BCLog::NET, "portmap: Got unsupported PCP version response, falling back to NAT-PMP\n");
81 res = NATPMPRequestPortMap(*gateway4, private_port, requested_lifetime, g_mapport_interrupt);
82 }
83 handle_mapping(res);
84 }
85
86 // IPv6
87 std::optional<CNetAddr> gateway6 = QueryDefaultGateway(NET_IPV6);
88 if (!gateway6) {
89 LogDebug(BCLog::NET, "portmap: Could not determine IPv6 default gateway\n");
90 } else {

Callers 1

ThreadMapPortFunction · 0.85

Calls 14

GetRandBytesFunction · 0.85
GetListenPortFunction · 0.85
AddLocalFunction · 0.85
QueryDefaultGatewayFunction · 0.85
PCPRequestPortMapFunction · 0.85
CNetAddrClass · 0.85
NATPMPRequestPortMapFunction · 0.85
GetLocalAddressesFunction · 0.85
countMethod · 0.80
ToStringAddrMethod · 0.80
IsRoutableMethod · 0.80
FastRandomContextClass · 0.70

Tested by

no test coverage detected