11 #include <boost/test/unit_test.hpp> 20 std::chrono::milliseconds
delay;
32 TestOp(std::chrono::milliseconds delay_in,
Op op_in,
const std::vector<uint8_t> &data_in,
int error_in):
33 delay(delay_in), op(op_in),
data(data_in), error(error_in) {}
45 const std::optional<CService> local_ipv4{
Lookup(
"192.168.0.6", 1,
false)};
46 const std::optional<CService> local_ipv6{
Lookup(
"2a10:1234:5678:9abc:def0:1234:5678:9abc", 1,
false)};
47 const std::optional<CService> gateway_ipv4{
Lookup(
"192.168.0.1", 1,
false)};
48 const std::optional<CService> gateway_ipv6{
Lookup(
"2a10:1234:5678:9abc:def0:0000:0000:0000", 1,
false)};
49 BOOST_REQUIRE(local_ipv4 && local_ipv6 && gateway_ipv4 && gateway_ipv6);
50 default_local_ipv4 = *local_ipv4;
51 default_local_ipv6 = *local_ipv6;
52 default_gateway_ipv4 = *gateway_ipv4;
53 default_gateway_ipv6 = *gateway_ipv6;
55 struct in_addr inaddr_any;
56 inaddr_any.s_addr = htonl(INADDR_ANY);
57 bind_any_ipv4 =
CNetAddr(inaddr_any);
67 static constexpr
PCPMappingNonce TEST_NONCE{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
90 m_gateway_ip(gateway_ip)
92 ElapseTime(std::chrono::seconds(0));
98 assert(
false &&
"Move of Sock into PCPTestSock not allowed.");
102 ssize_t
Send(
const void*
data,
size_t len,
int)
const override {
103 if (!m_connected)
return -1;
104 Span in_pkt =
Span(static_cast<const uint8_t*>(
data), len);
110 if (CurOp().error)
return -1;
111 if (CurOp().
data.empty() || std::ranges::equal(CurOp().
data, in_pkt)) {
120 ssize_t
Recv(
void* buf,
size_t len,
int flags)
const override 122 if (!m_connected || AtEndOfScript() || CurOp().op !=
TestOp::RECV || m_time_left != 0
s) {
125 if (CurOp().error)
return -1;
126 const auto &recv_pkt = CurOp().data;
127 const size_t consume_bytes{std::min(len, recv_pkt.size())};
129 if ((
flags & MSG_PEEK) == 0) {
132 return consume_bytes;
135 int Connect(
const sockaddr* sa, socklen_t sa_len)
const override {
138 if (m_bound.IsBindAny()) {
141 if (m_bound.GetPort() == 0) {
150 int Bind(
const sockaddr* sa, socklen_t sa_len)
const override {
154 if (!service.
IsBindAny() && service != m_local_ip) {
163 int Listen(
int)
const override {
return -1; }
165 std::unique_ptr<Sock>
Accept(sockaddr* addr, socklen_t* addr_len)
const override 170 int GetSockOpt(
int level,
int opt_name,
void* opt_val, socklen_t* opt_len)
const override 175 int SetSockOpt(
int,
int,
const void*, socklen_t)
const override {
return 0; }
180 return m_bound.GetSockAddr(
name, name_len) ? 0 : -1;
187 bool Wait(std::chrono::milliseconds timeout,
189 Event* occurred =
nullptr)
const override 192 if (AtEndOfScript() || requested !=
Sock::RECV) {
195 std::chrono::milliseconds delay = std::min(m_time_left, timeout);
197 m_time_left -= delay;
198 if (CurOp().op ==
TestOp::RECV && m_time_left == 0
s && occurred !=
nullptr) {
221 mutable size_t m_script_ptr = 0;
224 mutable bool m_connected{
false};
237 BOOST_REQUIRE(m_script_ptr < m_script.size());
238 return m_script[m_script_ptr];
242 if (AtEndOfScript())
return;
243 m_time_left = CurOp().delay;
260 const std::vector<TestOp>
script{
270 0x00, 0x80, 0x00, 0x00,
271 0x66, 0xfd, 0xa1, 0xee,
272 0x01, 0x02, 0x03, 0x04,
278 0x00, 0x02, 0x00, 0x00,
279 0x04, 0xd2, 0x04, 0xd2,
280 0x00, 0x00, 0x03, 0xe8,
286 0x00, 0x82, 0x00, 0x00,
287 0x66, 0xfd, 0xa1, 0xee,
288 0x04, 0xd2, 0x04, 0xd2,
289 0x00, 0x00, 0x01, 0xf4,
294 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
295 return std::unique_ptr<PCPTestSock>();
301 BOOST_REQUIRE(mapping);
311 const std::vector<TestOp>
script{
315 0x02, 0x01, 0x00, 0x00,
316 0x00, 0x00, 0x03, 0xe8,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
318 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
319 0x06, 0x00, 0x00, 0x00,
320 0x04, 0xd2, 0x04, 0xd2,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
327 0x02, 0x81, 0x00, 0x00,
328 0x00, 0x00, 0x01, 0xf4,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
331 0x06, 0x00, 0x00, 0x00,
332 0x04, 0xd2, 0x04, 0xd2,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
338 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
339 return std::unique_ptr<PCPTestSock>();
342 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 1, 1000ms);
345 BOOST_REQUIRE(mapping);
355 const std::vector<TestOp>
script{
359 0x02, 0x01, 0x00, 0x00,
360 0x00, 0x00, 0x03, 0xe8,
361 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
362 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
363 0x06, 0x00, 0x00, 0x00,
364 0x04, 0xd2, 0x04, 0xd2,
365 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
371 0x02, 0x81, 0x00, 0x00,
372 0x00, 0x00, 0x01, 0xf4,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
375 0x06, 0x00, 0x00, 0x00,
376 0x04, 0xd2, 0x04, 0xd2,
377 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
382 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
383 return std::unique_ptr<PCPTestSock>();
386 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv6, default_local_ipv6, 1234, 1000, 1, 1000ms);
389 BOOST_REQUIRE(mapping);
399 const std::vector<TestOp>
script{};
401 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
402 return std::unique_ptr<PCPTestSock>();
409 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 3, 2000ms);
419 const std::vector<TestOp>
script{
432 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
433 return std::unique_ptr<PCPTestSock>();
438 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 3, 2000ms);
448 const std::vector<TestOp>
script{
452 0x02, 0x01, 0x00, 0x00,
453 0x00, 0x00, 0x03, 0xe8,
454 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
455 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
456 0x06, 0x00, 0x00, 0x00,
457 0x04, 0xd2, 0x04, 0xd2,
458 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
468 0x02, 0x01, 0x00, 0x00,
469 0x00, 0x00, 0x03, 0xe8,
470 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
471 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
472 0x06, 0x00, 0x00, 0x00,
473 0x04, 0xd2, 0x04, 0xd2,
474 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
480 0x02, 0x81, 0x00, 0x00,
481 0x00, 0x00, 0x01, 0xf4,
482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
484 0x06, 0x00, 0x00, 0x00,
485 0x04, 0xd2, 0x04, 0xd2,
486 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
491 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
492 return std::unique_ptr<PCPTestSock>();
498 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv6, default_local_ipv6, 1234, 1000, 2, 2000ms);
506 const std::vector<TestOp>
script{
510 0x02, 0x01, 0x00, 0x00,
511 0x00, 0x00, 0x03, 0xe8,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
513 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
514 0x06, 0x00, 0x00, 0x00,
515 0x04, 0xd2, 0x04, 0xd2,
516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
522 0x02, 0x81, 0x00, 0x08,
523 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
526 0x06, 0x00, 0x00, 0x00,
527 0x04, 0xd2, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
533 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
534 return std::unique_ptr<PCPTestSock>();
537 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 3, 1000ms);
547 const std::vector<TestOp>
script{
551 0x02, 0x01, 0x00, 0x00,
552 0x00, 0x00, 0x03, 0xe8,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
554 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
555 0x06, 0x00, 0x00, 0x00,
556 0x04, 0xd2, 0x04, 0xd2,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x81, 0x00, 0x01,
564 0x00, 0x00, 0x00, 0x00,
569 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
570 return std::unique_ptr<PCPTestSock>();
573 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 3, 1000ms);
584 std::vector<TestOp>
script{
594 0x00, 0x80, 0x00, 0x42,
595 0x66, 0xfd, 0xa1, 0xee,
596 0x01, 0x02, 0x03, 0x04,
601 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
602 return std::unique_ptr<PCPTestSock>();
622 0x00, 0x80, 0x00, 0x00,
623 0x66, 0xfd, 0xa1, 0xee,
624 0x01, 0x02, 0x03, 0x04,
630 0x00, 0x02, 0x00, 0x00,
631 0x04, 0xd2, 0x04, 0xd2,
632 0x00, 0x00, 0x03, 0xe8,
638 0x00, 0x82, 0x00, 0x43,
639 0x66, 0xfd, 0xa1, 0xee,
640 0x04, 0xd2, 0x04, 0xd2,
641 0x00, 0x00, 0x01, 0xf4,
646 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
647 return std::unique_ptr<PCPTestSock>();
652 err = std::get_if<MappingError>(&res);
660 const std::vector<TestOp>
script{
664 0x02, 0x01, 0x00, 0x00,
665 0x00, 0x00, 0x03, 0xe8,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
667 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
668 0x06, 0x00, 0x00, 0x00,
669 0x04, 0xd2, 0x04, 0xd2,
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
676 0x02, 0x81, 0x00, 0x42,
677 0x00, 0x00, 0x01, 0xf4,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
680 0x06, 0x00, 0x00, 0x00,
681 0x04, 0xd2, 0x04, 0xd2,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
687 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
688 return std::unique_ptr<PCPTestSock>();
691 auto res =
PCPRequestPortMap(TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234, 1000, 1, 1000ms);
static void ClearMockTime()
Clear mock time, go back to system steady clock.
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
CNetAddr default_gateway_ipv4
std::array< uint8_t, PCP_MAP_NONCE_SIZE > PCPMappingNonce
PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
uint32_t lifetime
Granted lifetime of binding (seconds).
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
int Listen(int) const override
listen(2) wrapper.
bool AtEndOfScript() const
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
PCPTestSock(const CNetAddr &local_ip, const CNetAddr &gateway_ip, const std::vector< TestOp > &script)
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock &events_per_sock) const override
Same as Wait(), but wait on many sockets within the same timeout.
static void SetMockTime(std::chrono::milliseconds mock_time_in)
Set mock time for testing.
memcpy(result.begin(), stream.data(), stream.size())
std::variant< MappingResult, MappingError > NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6886 NAT-PMP.
PCPTestSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
Save the value of CreateSock and restore when the test ends.
std::string ToStringAddrPort() const
Any kind of network-level error.
std::chrono::milliseconds delay
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
Any kind of protocol-level error, except unsupported version or no resources.
CNetAddr default_local_ipv6
A combination of a network address (CNetAddr) and a (TCP) port.
BOOST_AUTO_TEST_SUITE_END()
MappingError
Unsuccessful response to a port mapping.
Simple scripted UDP server emulation for testing.
CNetAddr default_local_ipv4
CService internal
Internal host:port.
UDP test server operation.
std::vector< uint8_t > data
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
#define ASSERT_DEBUG_LOG(message)
std::variant< MappingResult, MappingError > PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6887 Port Control Protocol (PCP).
ssize_t Send(const void *data, size_t len, int) const override
send(2) wrapper.
PCPTestingSetup(const ChainType chainType=ChainType::MAIN, TestOpts opts={})
int Bind(const sockaddr *sa, socklen_t sa_len) const override
bind(2) wrapper.
bool IsConnected(std::string &) const override
Check if still connected.
static constexpr std::chrono::milliseconds INITIAL_MOCK_TIME
std::vector< CService > Lookup(const std::string &name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
Resolve a service string to its corresponding service.
CNetAddr default_gateway_ipv6
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
const std::vector< TestOp > m_script
std::chrono::milliseconds m_time_left
#define BOOST_CHECK_EQUAL(v1, v2)
int SetSockOpt(int, int, const void *, socklen_t) const override
setsockopt(2) wrapper.
bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const override
Wait for readiness for input (recv) or output (send).
BOOST_AUTO_TEST_CASE(natpmp_ipv4)
uint8_t version
Protocol version, one of NATPMP_VERSION or PCP_VERSION.
RAII helper class that manages a socket and closes it automatically when it goes out of scope...
std::function< std::unique_ptr< Sock >int, int, int)> CreateSock
Socket factory.
A Span is an object that can refer to a contiguous sequence of objects.
const TestOp & CurOp() const
decltype(CreateSock) const m_create_sock_orig
Unsupported protocol version.
No resources available (port probably already mapped).
TestOp(std::chrono::milliseconds delay_in, Op op_in, const std::vector< uint8_t > &data_in, int error_in)
Span(T *, EndOrSize) -> Span< T >
void ElapseTime(std::chrono::milliseconds duration) const
int Connect(const sockaddr *sa, socklen_t sa_len) const override
connect(2) wrapper.
CService external
External host:port.
Successful response to a port mapping.
#define BOOST_CHECK(expr)