Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2024-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_COMMON_PCP_H6#define BITCOIN_COMMON_PCP_H8#include <netaddress.h>9#include <util/time.h>11#include <array>12#include <cstddef>13#include <cstdint>14#include <string>15#include <variant>17class CThreadInterrupt;19// RFC6886 NAT-PMP and RFC6887 Port Control Protocol (PCP) implementation.20// NAT-PMP and PCP use network byte order (big-endian).22//! Mapping nonce size in bytes (see RFC6887 section 11.1).23inline constexpr size_t PCP_MAP_NONCE_SIZE = 12;25//! PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping.26typedef std::array<uint8_t, PCP_MAP_NONCE_SIZE> PCPMappingNonce;28//! Unsuccessful response to a port mapping.29enum class MappingError {30NETWORK_ERROR, ///< Any kind of network-level error.31PROTOCOL_ERROR, ///< Any kind of protocol-level error, except unsupported version or no resources.32UNSUPP_VERSION, ///< Unsupported protocol version.33NO_RESOURCES, ///< No resources available (port probably already mapped).34};36//! Successful response to a port mapping.37struct MappingResult {38MappingResult(uint8_t version, const CService &internal_in, const CService &external_in, uint32_t lifetime_in):39version(version), internal(internal_in), external(external_in), lifetime(lifetime_in) {}40//! Protocol version, one of NATPMP_VERSION or PCP_VERSION.41uint8_t version;42//! Internal host:port.43CService internal;44//! External host:port.45CService external;46//! Granted lifetime of binding (seconds).47uint32_t lifetime;49//! Format mapping as string for logging.50std::string ToString() const;51};53//! Try to open a port using RFC 6886 NAT-PMP. IPv4 only.54//!55//! * gateway: Destination address for PCP requests (usually the default gateway).56//! * port: Internal port, and desired external port.57//! * lifetime: Requested lifetime in seconds for mapping. The server may assign as shorter or longer lifetime. A lifetime of 0 deletes the mapping.58//! * num_tries: Number of tries in case of no response.59//!60//! Returns the external_ip:external_port of the mapping if successful, otherwise a MappingError.61std::variant<MappingResult, MappingError> NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, CThreadInterrupt& interrupt, int num_tries = 3, std::chrono::milliseconds timeout_per_try = std::chrono::milliseconds(1000));63//! Try to open a port using RFC 6887 Port Control Protocol (PCP). Handles IPv4 and IPv6.64//!65//! * nonce: Mapping cookie. Keep this the same over renewals.66//! * gateway: Destination address for PCP requests (usually the default gateway).67//! * bind: Specific local bind address for IPv6 pinholing. Set this as INADDR_ANY for IPv4.68//! * port: Internal port, and desired external port.69//! * lifetime: Requested lifetime in seconds for mapping. The server may assign as shorter or longer lifetime. A lifetime of 0 deletes the mapping.70//! * num_tries: Number of tries in case of no response.71//!72//! Returns the external_ip:external_port of the mapping if successful, otherwise a MappingError.73std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, CThreadInterrupt& interrupt, int num_tries = 3, std::chrono::milliseconds timeout_per_try = std::chrono::milliseconds(1000));75#endif // BITCOIN_COMMON_PCP_H