Inside Bitcoin
Opening the selected file…
Inside Bitcoin
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.
251void FailScript() const { m_script_ptr = m_script.size(); }252};254BOOST_FIXTURE_TEST_SUITE(pcp_tests, PCPTestingSetup)256// NAT-PMP IPv4 good-weather scenario.257BOOST_AUTO_TEST_CASE(natpmp_ipv4)258{259const std::vector<TestOp> script{260{2610ms, TestOp::SEND,262{2630x00, 0x00, // version, opcode (request external IP)264}, 0265},266{2672ms, TestOp::RECV,268{2690x00, 0x80, 0x00, 0x00, // version, opcode (external IP), result code (success)2700x66, 0xfd, 0xa1, 0xee, // seconds sinds start of epoch2710x01, 0x02, 0x03, 0x04, // external IP address272}, 0273},274{2750ms, TestOp::SEND,276{2770x00, 0x02, 0x00, 0x00, // version, opcode (request map TCP)2780x04, 0xd2, 0x04, 0xd2, // internal port, suggested external port2790x00, 0x00, 0x03, 0xe8, // requested mapping lifetime in seconds280}, 0281},282{2832ms, TestOp::RECV,284{2850x00, 0x82, 0x00, 0x00, // version, opcode (mapped TCP)2860x66, 0xfd, 0xa1, 0xee, // seconds sinds start of epoch2870x04, 0xd2, 0x04, 0xd2, // internal port, mapped external port2880x00, 0x00, 0x01, 0xf4, // mapping lifetime in seconds289}, 0290},291};292CreateSock = [this, &script](int domain, int type, int protocol) {293if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);294return std::unique_ptr<PCPTestSock>();295};297auto res = NATPMPRequestPortMap(default_gateway_ipv4, 1234, 1000, g_interrupt, 1, 200ms);299MappingResult* mapping = std::get_if<MappingResult>(&res);300BOOST_REQUIRE(mapping);301BOOST_CHECK_EQUAL(mapping->version, 0);302BOOST_CHECK_EQUAL(mapping->internal.ToStringAddrPort(), "192.168.0.6:1234");303BOOST_CHECK_EQUAL(mapping->external.ToStringAddrPort(), "1.2.3.4:1234");304BOOST_CHECK_EQUAL(mapping->lifetime, 500);305}307// PCP IPv4 good-weather scenario.308BOOST_AUTO_TEST_CASE(pcp_ipv4)309{310const std::vector<TestOp> script{311{3120ms, TestOp::SEND,313{3140x02, 0x01, 0x00, 0x00, // version, opcode3150x00, 0x00, 0x03, 0xe8, // lifetime3160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06, // internal IP3170x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce3180x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved3190x04, 0xd2, 0x04, 0xd2, // internal port, suggested external port3200x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, // suggested external IP321}, 0322},323{324250ms, TestOp::RECV, // 250ms delay before answer325{3260x02, 0x81, 0x00, 0x00, // version, opcode, result success3270x00, 0x00, 0x01, 0xf4, // granted lifetime3280x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved3290x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce3300x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved3310x04, 0xd2, 0x04, 0xd2, // internal port, assigned external port3320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04, // assigned external IP333}, 0334},335};336CreateSock = [this, &script](int domain, int type, int protocol) {337if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);338return std::unique_ptr<PCPTestSock>();339};341auto res = PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, g_interrupt, 1, 1000ms);343MappingResult* mapping = std::get_if<MappingResult>(&res);344BOOST_REQUIRE(mapping);345BOOST_CHECK_EQUAL(mapping->version, 2);346BOOST_CHECK_EQUAL(mapping->internal.ToStringAddrPort(), "192.168.0.6:1234");347BOOST_CHECK_EQUAL(mapping->external.ToStringAddrPort(), "1.2.3.4:1234");348BOOST_CHECK_EQUAL(mapping->lifetime, 500);349}351// PCP IPv6 good-weather scenario.352BOOST_AUTO_TEST_CASE(pcp_ipv6)353{354const std::vector<TestOp> script{355{3560ms, TestOp::SEND,357{3580x02, 0x01, 0x00, 0x00, // version, opcode3590x00, 0x00, 0x03, 0xe8, // lifetime3600x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // internal IP3610x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce3620x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved3630x04, 0xd2, 0x04, 0xd2, // internal port, suggested external port3640x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // suggested external IP365}, 0366},367{368500ms, TestOp::RECV, // 500ms delay before answer369{3700x02, 0x81, 0x00, 0x00, // version, opcode, result success3710x00, 0x00, 0x01, 0xf4, // granted lifetime3720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved3730x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce3740x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved3750x04, 0xd2, 0x04, 0xd2, // internal port, assigned external port3760x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // suggested external IP377}, 0378},379};380CreateSock = [this, &script](int domain, int type, int protocol) {381if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6, script);382return std::unique_ptr<PCPTestSock>();383};385auto res = PCPRequestPortMap(TEST_NONCE, default_gateway_ipv6, default_local_ipv6, 1234, 1000, g_interrupt, 1, 1000ms);387MappingResult* mapping = std::get_if<MappingResult>(&res);388BOOST_REQUIRE(mapping);389BOOST_CHECK_EQUAL(mapping->version, 2);390BOOST_CHECK_EQUAL(mapping->internal.ToStringAddrPort(), "[2a10:1234:5678:9abc:def0:1234:5678:9abc]:1234");391BOOST_CHECK_EQUAL(mapping->external.ToStringAddrPort(), "[2a10:1234:5678:9abc:def0:1234:5678:9abc]:1234");392BOOST_CHECK_EQUAL(mapping->lifetime, 500);393}395// PCP timeout.396BOOST_AUTO_TEST_CASE(pcp_timeout)397{398const std::vector<TestOp> script{};399CreateSock = [this, &script](int domain, int type, int protocol) {400if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);401return std::unique_ptr<PCPTestSock>();402};404ASSERT_DEBUG_LOG("pcp: Retrying (1)");405ASSERT_DEBUG_LOG("pcp: Retrying (2)");406ASSERT_DEBUG_LOG("pcp: Timeout");408auto res = PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, g_interrupt, 3, 2000ms);410MappingError* err = std::get_if<MappingError>(&res);411BOOST_REQUIRE(err);412BOOST_CHECK_EQUAL(*err, MappingError::NETWORK_ERROR);413}415// PCP failure receiving (router sends ICMP port closed).416BOOST_AUTO_TEST_CASE(pcp_connrefused)417{418const std::vector<TestOp> script{419{4200ms, TestOp::SEND,421{ // May send anything.422}, 0423},424{4250ms, TestOp::RECV,426{427}, ECONNREFUSED428},429};430CreateSock = [this, &script](int domain, int type, int protocol) {431if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);432return std::unique_ptr<PCPTestSock>();433};435ASSERT_DEBUG_LOG("pcp: Could not receive response");437auto res = PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, g_interrupt, 3, 2000ms);439MappingError* err = std::get_if<MappingError>(&res);440BOOST_REQUIRE(err);441BOOST_CHECK_EQUAL(*err, MappingError::NETWORK_ERROR);442}444// PCP IPv6 success after one timeout.445BOOST_AUTO_TEST_CASE(pcp_ipv6_timeout_success)446{447const std::vector<TestOp> script{448{4490ms, TestOp::SEND,450{4510x02, 0x01, 0x00, 0x00, // version, opcode4520x00, 0x00, 0x03, 0xe8, // lifetime4530x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // internal IP4540x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce4550x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved4560x04, 0xd2, 0x04, 0xd2, // internal port, suggested external port4570x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // suggested external IP458}, 0459},460{4612001ms, TestOp::NOP, // Takes longer to respond than timeout of 2000ms462{}, 0463},464{4650ms, TestOp::SEND, // Repeated send (try 2)466{4670x02, 0x01, 0x00, 0x00, // version, opcode4680x00, 0x00, 0x03, 0xe8, // lifetime4690x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // internal IP4700x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce4710x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved4720x04, 0xd2, 0x04, 0xd2, // internal port, suggested external port4730x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // suggested external IP474}, 0475},476{477200ms, TestOp::RECV, // This time we're in time478{4790x02, 0x81, 0x00, 0x00, // version, opcode, result success4800x00, 0x00, 0x01, 0xf4, // granted lifetime4810x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved4820x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, // nonce4830x06, 0x00, 0x00, 0x00, // protocol (TCP), reserved4840x04, 0xd2, 0x04, 0xd2, // internal port, assigned external port4850x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, // suggested external IP486}, 0487},488};489CreateSock = [this, &script](int domain, int type, int protocol) {490if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6, script);491return std::unique_ptr<PCPTestSock>();492};494ASSERT_DEBUG_LOG("pcp: Retrying (1)");495ASSERT_DEBUG_LOG("pcp: Timeout");497auto res = PCPRequestPortMap(TEST_NONCE, default_gateway_ipv6, default_local_ipv6, 1234, 1000, g_interrupt, 2, 2000ms);499BOOST_CHECK(std::get_if<MappingResult>(&res));500}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.