Skip to content

Commit c652332

Browse files
committed
Merge bitcoin/bitcoin#31022: test: Add mockable steady clock, tests for PCP and NATPMP implementations
0f716f2 qa: cover PROTOCOL_ERROR variant in PCP unit tests (Antoine Poinsot) fc700bb test: Add tests for PCP and NATPMP implementations (laanwj) caf9521 net: Use mockable steady clock in PCP implementation (laanwj) 0364832 util: Add mockable steady_clock (laanwj) ab1d3ec net: Add optional length checking to CService::SetSockAddr (laanwj) Pull request description: Add a NodeSteadyClock, a steady_clock that can be mocked with millisecond precision. Use this in the PCP implementation. Then add a mock for a simple scriptable UDP server,, which is used to test various code paths (including successful mappings, timeouts and errors) in the PCP and NATPMP implementations. Includes "net: Add optional length checking to CService::SetSockAddr" from #31014 as a prerequisite. ACKs for top commit: darosior: re-ACK 0f716f2 i-am-yuvi: Concept ACK 0f716f2 achow101: ACK 0f716f2 Tree-SHA512: 6f91b24e6fe46a3fded7a13972efd77c98e6ef235f8898e4ae44068c5df32d1cdabb22cb66c351b338dc98cb2073b624e43607a28107f4999302bfbe7a138229
2 parents 8652893 + 0f716f2 commit c652332

File tree

9 files changed

+767
-15
lines changed

9 files changed

+767
-15
lines changed

src/common/netif.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,9 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
169169

170170
std::optional<CNetAddr> FromSockAddr(const struct sockaddr* addr)
171171
{
172-
// Check valid length. Note that sa_len is not part of POSIX, and exists on MacOS and some BSDs only, so we can't
173-
// do this check in SetSockAddr.
174-
if (!(addr->sa_family == AF_INET && addr->sa_len == sizeof(struct sockaddr_in)) &&
175-
!(addr->sa_family == AF_INET6 && addr->sa_len == sizeof(struct sockaddr_in6))) {
176-
return std::nullopt;
177-
}
178-
179172
// Fill in a CService from the sockaddr, then drop the port part.
180173
CService service;
181-
if (service.SetSockAddr(addr)) {
174+
if (service.SetSockAddr(addr, addr->sa_len)) {
182175
return (CNetAddr)service;
183176
}
184177
return std::nullopt;

src/common/pcp.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,9 @@ std::optional<std::vector<uint8_t>> PCPSendRecv(Sock &sock, const std::string &p
235235
}
236236

237237
// Wait for response(s) until we get a valid response, a network error, or time out.
238-
auto cur_time = time_point_cast<milliseconds>(steady_clock::now());
238+
auto cur_time = time_point_cast<milliseconds>(MockableSteadyClock::now());
239239
auto deadline = cur_time + timeout_per_try;
240-
while ((cur_time = time_point_cast<milliseconds>(steady_clock::now())) < deadline) {
240+
while ((cur_time = time_point_cast<milliseconds>(MockableSteadyClock::now())) < deadline) {
241241
Sock::Event occurred = 0;
242242
if (!sock.Wait(deadline - cur_time, Sock::RECV, &occurred)) {
243243
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "%s: Could not wait on socket: %s\n", protocol, NetworkErrorString(WSAGetLastError()));
@@ -426,7 +426,7 @@ std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonc
426426
return MappingError::NETWORK_ERROR;
427427
}
428428
CService internal;
429-
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr)) return MappingError::NETWORK_ERROR;
429+
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr, internal_addrlen)) return MappingError::NETWORK_ERROR;
430430
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "pcp: Internal address after connect: %s\n", internal.ToStringAddr());
431431

432432
// Build request packet. Make sure the packet is zeroed so that reserved fields are zero

src/net.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ static CAddress GetBindAddress(const Sock& sock)
387387
struct sockaddr_storage sockaddr_bind;
388388
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
389389
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
390-
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
390+
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind, sockaddr_bind_len);
391391
} else {
392392
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
393393
}
@@ -1746,7 +1746,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
17461746
return;
17471747
}
17481748

1749-
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
1749+
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) {
17501750
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n");
17511751
} else {
17521752
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};

src/netaddress.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,13 +807,15 @@ CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, a
807807
assert(addr.sin6_family == AF_INET6);
808808
}
809809

810-
bool CService::SetSockAddr(const struct sockaddr *paddr)
810+
bool CService::SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
811811
{
812812
switch (paddr->sa_family) {
813813
case AF_INET:
814+
if (addrlen != sizeof(struct sockaddr_in)) return false;
814815
*this = CService(*(const struct sockaddr_in*)paddr);
815816
return true;
816817
case AF_INET6:
818+
if (addrlen != sizeof(struct sockaddr_in6)) return false;
817819
*this = CService(*(const struct sockaddr_in6*)paddr);
818820
return true;
819821
default:

src/netaddress.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,14 @@ class CService : public CNetAddr
539539
explicit CService(const struct sockaddr_in& addr);
540540
uint16_t GetPort() const;
541541
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
542-
bool SetSockAddr(const struct sockaddr* paddr);
542+
/**
543+
* Set CService from a network sockaddr.
544+
* @param[in] paddr Pointer to sockaddr structure
545+
* @param[in] addrlen Length of sockaddr structure in bytes. This will be checked to exactly match the length of
546+
* a socket address of the provided family, unless std::nullopt is passed
547+
* @returns true on success
548+
*/
549+
bool SetSockAddr(const struct sockaddr* paddr, socklen_t addrlen);
543550
/**
544551
* Get the address family
545552
* @returns AF_UNSPEC if unspecified

src/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ add_executable(test_bitcoin
8787
netbase_tests.cpp
8888
node_warnings_tests.cpp
8989
orphanage_tests.cpp
90+
pcp_tests.cpp
9091
peerman_tests.cpp
9192
pmt_tests.cpp
9293
policy_fee_tests.cpp

0 commit comments

Comments
 (0)