11#include <boost/test/unit_test.hpp>
16using namespace std::literals;
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):
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);
55 struct in_addr inaddr_any;
56 inaddr_any.s_addr = htonl(INADDR_ANY);
67 static constexpr PCPMappingNonce TEST_NONCE{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
98 assert(
false &&
"Move of Sock into PCPTestSock not allowed.");
102 ssize_t
Send(
const void*
data,
size_t len,
int)
const override {
104 Span in_pkt =
Span(
static_cast<const uint8_t*
>(
data), len);
110 if (
CurOp().error)
return -1;
120 ssize_t
Recv(
void* buf,
size_t len,
int flags)
const override
125 if (
CurOp().error)
return -1;
127 const size_t consume_bytes{std::min(len, recv_pkt.size())};
128 std::memcpy(buf, recv_pkt.data(), consume_bytes);
129 if ((
flags & MSG_PEEK) == 0) {
132 return consume_bytes;
135 int Connect(
const sockaddr* sa, socklen_t sa_len)
const override {
150 int Bind(
const sockaddr* sa, socklen_t sa_len)
const override {
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; }
187 bool Wait(std::chrono::milliseconds timeout,
189 Event* occurred =
nullptr)
const override
195 std::chrono::milliseconds delay = std::min(
m_time_left, timeout);
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);
A combination of a network address (CNetAddr) and a (TCP) port.
bool SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
Set CService from a network sockaddr.
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Obtain the IPv4/6 socket address this represents.
std::string ToStringAddrPort() const
Simple scripted UDP server emulation for testing.
void ElapseTime(std::chrono::milliseconds duration) const
int GetSockName(sockaddr *name, socklen_t *name_len) const override
getsockname(2) wrapper.
int SetSockOpt(int, int, const void *, socklen_t) const override
setsockopt(2) wrapper.
int Bind(const sockaddr *sa, socklen_t sa_len) const override
bind(2) wrapper.
ssize_t Recv(void *buf, size_t len, int flags) const override
recv(2) wrapper.
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock &events_per_sock) const override
Same as Wait(), but wait on many sockets within the same timeout.
int Listen(int) const override
listen(2) wrapper.
PCPTestSock & operator=(Sock &&other) override
Move assignment operator, grab the socket from another object and close ours (if set).
bool SetNonBlocking() const override
Set the non-blocking option on the socket.
int GetSockOpt(int level, int opt_name, void *opt_val, socklen_t *opt_len) const override
getsockopt(2) wrapper.
std::chrono::milliseconds m_time
PCPTestSock(const CNetAddr &local_ip, const CNetAddr &gateway_ip, const std::vector< TestOp > &script)
bool Wait(std::chrono::milliseconds timeout, Event requested, Event *occurred=nullptr) const override
Wait for readiness for input (recv) or output (send).
const std::vector< TestOp > m_script
int Connect(const sockaddr *sa, socklen_t sa_len) const override
connect(2) wrapper.
bool AtEndOfScript() const
std::chrono::milliseconds m_time_left
bool IsSelectable() const override
Check if the underlying socket can be used for select(2) (or the Wait() method).
ssize_t Send(const void *data, size_t len, int) const override
send(2) wrapper.
std::unique_ptr< Sock > Accept(sockaddr *addr, socklen_t *addr_len) const override
accept(2) wrapper.
const TestOp & CurOp() const
bool IsConnected(std::string &) const override
Check if still connected.
Save the value of CreateSock and restore when the test ends.
CNetAddr default_gateway_ipv4
CNetAddr default_local_ipv4
CNetAddr default_gateway_ipv6
static constexpr PCPMappingNonce TEST_NONCE
CNetAddr default_local_ipv6
const decltype(CreateSock) m_create_sock_orig
PCPTestingSetup(const ChainType chainType=ChainType::MAIN, TestOpts opts={})
RAII helper class that manages a socket and closes it automatically when it goes out of scope.
static constexpr Event RECV
If passed to Wait(), then it will wait for readiness to read from the socket.
std::unordered_map< std::shared_ptr< const Sock >, Events, HashSharedPtrSock, EqualSharedPtrSock > EventsPerSock
On which socket to wait for what events in WaitMany().
A Span is an object that can refer to a contiguous sequence of objects.
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).
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.
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
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.
std::function< std::unique_ptr< Sock >(int, int, int)> CreateSock
Socket factory.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
std::array< uint8_t, PCP_MAP_NONCE_SIZE > PCPMappingNonce
PCP mapping nonce. Arbitrary data chosen by the client to identify a mapping.
MappingError
Unsuccessful response to a port mapping.
@ PROTOCOL_ERROR
Any kind of protocol-level error, except unsupported version or no resources.
@ NO_RESOURCES
No resources available (port probably already mapped).
@ UNSUPP_VERSION
Unsupported protocol version.
@ NETWORK_ERROR
Any kind of network-level error.
BOOST_AUTO_TEST_CASE(natpmp_ipv4)
Span(T *, EndOrSize) -> Span< T >
Successful response to a port mapping.
CService external
External host:port.
uint32_t lifetime
Granted lifetime of binding (seconds).
CService internal
Internal host:port.
uint8_t version
Protocol version, one of NATPMP_VERSION or PCP_VERSION.
static constexpr std::chrono::milliseconds INITIAL_MOCK_TIME
static void SetMockTime(std::chrono::milliseconds mock_time_in)
Set mock time for testing.
static void ClearMockTime()
Clear mock time, go back to system steady clock.
UDP test server operation.
std::vector< uint8_t > data
TestOp(std::chrono::milliseconds delay_in, Op op_in, const std::vector< uint8_t > &data_in, int error_in)
std::chrono::milliseconds delay
#define ASSERT_DEBUG_LOG(message)