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};
100 assert(
false &&
"Move of Sock into PCPTestSock not allowed.");
104 ssize_t
Send(
const void*
data,
size_t len,
int)
const override {
106 std::span in_pkt = std::span(
static_cast<const uint8_t*
>(
data), len);
112 if (
CurOp().error)
return -1;
122 ssize_t
Recv(
void* buf,
size_t len,
int flags)
const override
127 if (
CurOp().error)
return -1;
129 const size_t consume_bytes{std::min(len, recv_pkt.size())};
130 std::memcpy(buf, recv_pkt.data(), consume_bytes);
131 if ((
flags & MSG_PEEK) == 0) {
134 return consume_bytes;
137 int Connect(
const sockaddr* sa, socklen_t sa_len)
const override {
152 int Bind(
const sockaddr* sa, socklen_t sa_len)
const override {
165 int Listen(
int)
const override {
return -1; }
167 std::unique_ptr<Sock>
Accept(sockaddr* addr, socklen_t* addr_len)
const override
172 int GetSockOpt(
int level,
int opt_name,
void* opt_val, socklen_t* opt_len)
const override
177 int SetSockOpt(
int,
int,
const void*, socklen_t)
const override {
return 0; }
189 bool Wait(std::chrono::milliseconds timeout,
191 Event* occurred =
nullptr)
const override
197 std::chrono::milliseconds delay = std::min(
m_time_left, timeout);
256 const std::vector<TestOp>
script{
266 0x00, 0x80, 0x00, 0x00,
267 0x66, 0xfd, 0xa1, 0xee,
268 0x01, 0x02, 0x03, 0x04,
274 0x00, 0x02, 0x00, 0x00,
275 0x04, 0xd2, 0x04, 0xd2,
276 0x00, 0x00, 0x03, 0xe8,
282 0x00, 0x82, 0x00, 0x00,
283 0x66, 0xfd, 0xa1, 0xee,
284 0x04, 0xd2, 0x04, 0xd2,
285 0x00, 0x00, 0x01, 0xf4,
290 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
291 return std::unique_ptr<PCPTestSock>();
297 BOOST_REQUIRE(mapping);
307 const std::vector<TestOp>
script{
311 0x02, 0x01, 0x00, 0x00,
312 0x00, 0x00, 0x03, 0xe8,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
314 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
315 0x06, 0x00, 0x00, 0x00,
316 0x04, 0xd2, 0x04, 0xd2,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
323 0x02, 0x81, 0x00, 0x00,
324 0x00, 0x00, 0x01, 0xf4,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
327 0x06, 0x00, 0x00, 0x00,
328 0x04, 0xd2, 0x04, 0xd2,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
334 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
335 return std::unique_ptr<PCPTestSock>();
341 BOOST_REQUIRE(mapping);
351 const std::vector<TestOp>
script{
355 0x02, 0x01, 0x00, 0x00,
356 0x00, 0x00, 0x03, 0xe8,
357 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
358 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
359 0x06, 0x00, 0x00, 0x00,
360 0x04, 0xd2, 0x04, 0xd2,
361 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
367 0x02, 0x81, 0x00, 0x00,
368 0x00, 0x00, 0x01, 0xf4,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
371 0x06, 0x00, 0x00, 0x00,
372 0x04, 0xd2, 0x04, 0xd2,
373 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
378 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
379 return std::unique_ptr<PCPTestSock>();
385 BOOST_REQUIRE(mapping);
395 const std::vector<TestOp>
script{};
397 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
398 return std::unique_ptr<PCPTestSock>();
415 const std::vector<TestOp>
script{
428 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
429 return std::unique_ptr<PCPTestSock>();
444 const std::vector<TestOp>
script{
448 0x02, 0x01, 0x00, 0x00,
449 0x00, 0x00, 0x03, 0xe8,
450 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
451 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
452 0x06, 0x00, 0x00, 0x00,
453 0x04, 0xd2, 0x04, 0xd2,
454 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
464 0x02, 0x01, 0x00, 0x00,
465 0x00, 0x00, 0x03, 0xe8,
466 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
467 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
468 0x06, 0x00, 0x00, 0x00,
469 0x04, 0xd2, 0x04, 0xd2,
470 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
476 0x02, 0x81, 0x00, 0x00,
477 0x00, 0x00, 0x01, 0xf4,
478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
479 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
480 0x06, 0x00, 0x00, 0x00,
481 0x04, 0xd2, 0x04, 0xd2,
482 0x2a, 0x10, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc,
487 if (domain == AF_INET6 && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv6, default_gateway_ipv6,
script);
488 return std::unique_ptr<PCPTestSock>();
502 const std::vector<TestOp>
script{
506 0x02, 0x01, 0x00, 0x00,
507 0x00, 0x00, 0x03, 0xe8,
508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
509 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
510 0x06, 0x00, 0x00, 0x00,
511 0x04, 0xd2, 0x04, 0xd2,
512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
518 0x02, 0x81, 0x00, 0x08,
519 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
522 0x06, 0x00, 0x00, 0x00,
523 0x04, 0xd2, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
530 return std::unique_ptr<PCPTestSock>();
543 const std::vector<TestOp>
script{
547 0x02, 0x01, 0x00, 0x00,
548 0x00, 0x00, 0x03, 0xe8,
549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
550 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
551 0x06, 0x00, 0x00, 0x00,
552 0x04, 0xd2, 0x04, 0xd2,
553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x81, 0x00, 0x01,
560 0x00, 0x00, 0x00, 0x00,
565 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
566 return std::unique_ptr<PCPTestSock>();
580 std::vector<TestOp>
script{
590 0x00, 0x80, 0x00, 0x42,
591 0x66, 0xfd, 0xa1, 0xee,
592 0x01, 0x02, 0x03, 0x04,
597 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
598 return std::unique_ptr<PCPTestSock>();
618 0x00, 0x80, 0x00, 0x00,
619 0x66, 0xfd, 0xa1, 0xee,
620 0x01, 0x02, 0x03, 0x04,
626 0x00, 0x02, 0x00, 0x00,
627 0x04, 0xd2, 0x04, 0xd2,
628 0x00, 0x00, 0x03, 0xe8,
634 0x00, 0x82, 0x00, 0x43,
635 0x66, 0xfd, 0xa1, 0xee,
636 0x04, 0xd2, 0x04, 0xd2,
637 0x00, 0x00, 0x01, 0xf4,
642 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
643 return std::unique_ptr<PCPTestSock>();
648 err = std::get_if<MappingError>(&res);
656 const std::vector<TestOp>
script{
660 0x02, 0x01, 0x00, 0x00,
661 0x00, 0x00, 0x03, 0xe8,
662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x06,
663 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
664 0x06, 0x00, 0x00, 0x00,
665 0x04, 0xd2, 0x04, 0xd2,
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
672 0x02, 0x81, 0x00, 0x42,
673 0x00, 0x00, 0x01, 0xf4,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
676 0x06, 0x00, 0x00, 0x00,
677 0x04, 0xd2, 0x04, 0xd2,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x02, 0x03, 0x04,
683 if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP)
return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4,
script);
684 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.
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.
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.
SteadyClockContext m_clock
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().
Helper to initialize the global MockableSteadyClock, let a duration elapse, and reset it after use in...
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 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)