12#include <boost/test/unit_test.hpp>
17using namespace std::literals;
23 std::chrono::milliseconds
delay;
35 TestOp(std::chrono::milliseconds delay_in,
Op op_in,
const std::vector<uint8_t> &data_in,
int error_in):
48 const std::optional<CService> local_ipv4{
Lookup(
"192.168.0.6", 1,
false)};
49 const std::optional<CService> local_ipv6{
Lookup(
"2a10:1234:5678:9abc:def0:1234:5678:9abc", 1,
false)};
50 const std::optional<CService> gateway_ipv4{
Lookup(
"192.168.0.1", 1,
false)};
51 const std::optional<CService> gateway_ipv6{
Lookup(
"2a10:1234:5678:9abc:def0:0000:0000:0000", 1,
false)};
52 BOOST_REQUIRE(local_ipv4 && local_ipv6 && gateway_ipv4 && gateway_ipv6);
58 struct in_addr inaddr_any;
59 inaddr_any.s_addr = htonl(INADDR_ANY);
70 static constexpr PCPMappingNonce TEST_NONCE{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc};
101 assert(
false &&
"Move of Sock into PCPTestSock not allowed.");
105 ssize_t
Send(
const void*
data,
size_t len,
int)
const override {
107 std::span in_pkt = std::span(
static_cast<const uint8_t*
>(
data), len);
113 if (
CurOp().error)
return -1;
123 ssize_t
Recv(
void* buf,
size_t len,
int flags)
const override
128 if (
CurOp().error)
return -1;
130 const size_t consume_bytes{std::min(len, recv_pkt.size())};
131 std::memcpy(buf, recv_pkt.data(), consume_bytes);
132 if ((
flags & MSG_PEEK) == 0) {
135 return consume_bytes;
138 int Connect(
const sockaddr* sa, socklen_t sa_len)
const override {
153 int Bind(
const sockaddr* sa, socklen_t sa_len)
const override {
166 int Listen(
int)
const override {
return -1; }
168 std::unique_ptr<Sock>
Accept(sockaddr* addr, socklen_t* addr_len)
const override
173 int GetSockOpt(
int level,
int opt_name,
void* opt_val, socklen_t* opt_len)
const override
178 int SetSockOpt(
int,
int,
const void*, socklen_t)
const override {
return 0; }
190 bool Wait(std::chrono::milliseconds timeout,
192 Event* occurred =
nullptr)
const override
198 std::chrono::milliseconds delay = std::min(
m_time_left, timeout);
263 const std::vector<TestOp>
script{
273 0x00, 0x80, 0x00, 0x00,
274 0x66, 0xfd, 0xa1, 0xee,
275 0x01, 0x02, 0x03, 0x04,
281 0x00, 0x02, 0x00, 0x00,
282 0x04, 0xd2, 0x04, 0xd2,
283 0x00, 0x00, 0x03, 0xe8,
289 0x00, 0x82, 0x00, 0x00,
290 0x66, 0xfd, 0xa1, 0xee,
291 0x04, 0xd2, 0x04, 0xd2,
292 0x00, 0x00, 0x01, 0xf4,
297 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
298 return std::unique_ptr<PCPTestSock>();
304 BOOST_REQUIRE(mapping);
314 const std::vector<TestOp>
script{
318 0x02, 0x01, 0x00, 0x00,
319 0x00, 0x00, 0x03, 0xe8,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
321 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
322 0x06, 0x00, 0x00, 0x00,
323 0x04, 0xd2, 0x04, 0xd2,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
330 0x02, 0x81, 0x00, 0x00,
331 0x00, 0x00, 0x01, 0xf4,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
334 0x06, 0x00, 0x00, 0x00,
335 0x04, 0xd2, 0x04, 0xd2,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
341 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
342 return std::unique_ptr<PCPTestSock>();
348 BOOST_REQUIRE(mapping);
358 const std::vector<TestOp>
script{
362 0x02, 0x01, 0x00, 0x00,
363 0x00, 0x00, 0x03, 0xe8,
364 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
365 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
366 0x06, 0x00, 0x00, 0x00,
367 0x04, 0xd2, 0x04, 0xd2,
368 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
374 0x02, 0x81, 0x00, 0x00,
375 0x00, 0x00, 0x01, 0xf4,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
378 0x06, 0x00, 0x00, 0x00,
379 0x04, 0xd2, 0x04, 0xd2,
380 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
385 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
386 return std::unique_ptr<PCPTestSock>();
392 BOOST_REQUIRE(mapping);
402 const std::vector<TestOp>
script{};
404 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
405 return std::unique_ptr<PCPTestSock>();
422 const std::vector<TestOp>
script{
435 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
436 return std::unique_ptr<PCPTestSock>();
451 const std::vector<TestOp>
script{
455 0x02, 0x01, 0x00, 0x00,
456 0x00, 0x00, 0x03, 0xe8,
457 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
458 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
459 0x06, 0x00, 0x00, 0x00,
460 0x04, 0xd2, 0x04, 0xd2,
461 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
471 0x02, 0x01, 0x00, 0x00,
472 0x00, 0x00, 0x03, 0xe8,
473 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
474 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
475 0x06, 0x00, 0x00, 0x00,
476 0x04, 0xd2, 0x04, 0xd2,
477 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
483 0x02, 0x81, 0x00, 0x00,
484 0x00, 0x00, 0x01, 0xf4,
485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
486 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
487 0x06, 0x00, 0x00, 0x00,
488 0x04, 0xd2, 0x04, 0xd2,
489 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
494 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
495 return std::unique_ptr<PCPTestSock>();
509 const std::vector<TestOp>
script{
513 0x02, 0x01, 0x00, 0x00,
514 0x00, 0x00, 0x03, 0xe8,
515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
516 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
517 0x06, 0x00, 0x00, 0x00,
518 0x04, 0xd2, 0x04, 0xd2,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
525 0x02, 0x81, 0x00, 0x08,
526 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
529 0x06, 0x00, 0x00, 0x00,
530 0x04, 0xd2, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
537 return std::unique_ptr<PCPTestSock>();
550 const std::vector<TestOp>
script{
554 0x02, 0x01, 0x00, 0x00,
555 0x00, 0x00, 0x03, 0xe8,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
557 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
558 0x06, 0x00, 0x00, 0x00,
559 0x04, 0xd2, 0x04, 0xd2,
560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
566 0x00, 0x81, 0x00, 0x01,
567 0x00, 0x00, 0x00, 0x00,
572 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
573 return std::unique_ptr<PCPTestSock>();
587 std::vector<TestOp>
script{
597 0x00, 0x80, 0x00, 0x42,
598 0x66, 0xfd, 0xa1, 0xee,
599 0x01, 0x02, 0x03, 0x04,
604 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
605 return std::unique_ptr<PCPTestSock>();
625 0x00, 0x80, 0x00, 0x00,
626 0x66, 0xfd, 0xa1, 0xee,
627 0x01, 0x02, 0x03, 0x04,
633 0x00, 0x02, 0x00, 0x00,
634 0x04, 0xd2, 0x04, 0xd2,
635 0x00, 0x00, 0x03, 0xe8,
641 0x00, 0x82, 0x00, 0x43,
642 0x66, 0xfd, 0xa1, 0xee,
643 0x04, 0xd2, 0x04, 0xd2,
644 0x00, 0x00, 0x01, 0xf4,
649 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
650 return std::unique_ptr<PCPTestSock>();
655 err = std::get_if<MappingError>(&res);
663 const std::vector<TestOp>
script{
667 0x02, 0x01, 0x00, 0x00,
668 0x00, 0x00, 0x03, 0xe8,
669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
670 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
671 0x06, 0x00, 0x00, 0x00,
672 0x04, 0xd2, 0x04, 0xd2,
673 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
679 0x02, 0x81, 0x00, 0x42,
680 0x00, 0x00, 0x01, 0xf4,
681 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
683 0x06, 0x00, 0x00, 0x00,
684 0x04, 0xd2, 0x04, 0xd2,
685 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
690 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
691 return std::unique_ptr<PCPTestSock>();
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
A helper class for interruptible sleeps.
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().
std::variant< MappingResult, MappingError > NATPMPRequestPortMap(const CNetAddr &gateway, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6886 NAT-PMP.
std::variant< MappingResult, MappingError > PCPRequestPortMap(const PCPMappingNonce &nonce, const CNetAddr &gateway, const CNetAddr &bind, uint16_t port, uint32_t lifetime, CThreadInterrupt &interrupt, int num_tries, std::chrono::milliseconds timeout_per_try)
Try to open a port using RFC 6887 Port Control Protocol (PCP).
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.
static CThreadInterrupt g_interrupt
BOOST_AUTO_TEST_CASE(natpmp_ipv4)
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 void SetMockTime(mock_time_point::duration mock_time_in)
Set mock time for testing.
static constexpr mock_time_point::duration INITIAL_MOCK_TIME
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)