Unverified Commit 5ebeb85c authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #885

Add IPv4 and IPv6 endpoint abstraction
parents de6f5b7d 220fb237
...@@ -66,8 +66,10 @@ set(LIBCAF_CORE_SRCS ...@@ -66,8 +66,10 @@ set(LIBCAF_CORE_SRCS
src/ini_consumer.cpp src/ini_consumer.cpp
src/invoke_result_visitor.cpp src/invoke_result_visitor.cpp
src/ipv4_address.cpp src/ipv4_address.cpp
src/ipv4_endpoint.cpp
src/ipv4_subnet.cpp src/ipv4_subnet.cpp
src/ipv6_address.cpp src/ipv6_address.cpp
src/ipv6_endpoint.cpp
src/ipv6_subnet.cpp src/ipv6_subnet.cpp
src/local_actor.cpp src/local_actor.cpp
src/logger.cpp src/logger.cpp
......
...@@ -113,8 +113,10 @@ class group; ...@@ -113,8 +113,10 @@ class group;
class group_module; class group_module;
class inbound_path; class inbound_path;
class ipv4_address; class ipv4_address;
class ipv4_endpoint;
class ipv4_subnet; class ipv4_subnet;
class ipv6_address; class ipv6_address;
class ipv6_endpoint;
class ipv6_subnet; class ipv6_subnet;
class local_actor; class local_actor;
class mailbox_element; class mailbox_element;
...@@ -142,7 +144,8 @@ class uri_builder; ...@@ -142,7 +144,8 @@ class uri_builder;
// -- templates with default parameters ---------------------------------------- // -- templates with default parameters ----------------------------------------
template <class, class = event_based_actor> class stateful_actor; template <class, class = event_based_actor>
class stateful_actor;
// -- structs ------------------------------------------------------------------ // -- structs ------------------------------------------------------------------
...@@ -241,7 +244,6 @@ class abstract_coordinator; ...@@ -241,7 +244,6 @@ class abstract_coordinator;
} // namespace scheduler } // namespace scheduler
// -- OpenSSL classes ---------------------------------------------------------- // -- OpenSSL classes ----------------------------------------------------------
namespace openssl { namespace openssl {
...@@ -254,8 +256,10 @@ class manager; ...@@ -254,8 +256,10 @@ class manager;
namespace detail { namespace detail {
template <class> class type_erased_value_impl; template <class>
template <class> class stream_distribution_tree; class type_erased_value_impl;
template <class>
class stream_distribution_tree;
class abstract_worker; class abstract_worker;
class abstract_worker_hub; class abstract_worker_hub;
...@@ -292,4 +296,3 @@ using type_erased_value_ptr = std::unique_ptr<type_erased_value>; ...@@ -292,4 +296,3 @@ using type_erased_value_ptr = std::unique_ptr<type_erased_value>;
using mailbox_element_ptr = std::unique_ptr<mailbox_element, detail::disposer>; using mailbox_element_ptr = std::unique_ptr<mailbox_element, detail::disposer>;
} // namespace caf } // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/ipv6_endpoint.hpp"
namespace caf {
/// An IP endpoint that contains an ::ipv6_address and a port.
using ip_endpoint = ipv6_endpoint;
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/detail/comparable.hpp"
#include "caf/ipv4_address.hpp"
#include "caf/meta/type_name.hpp"
namespace caf {
/// An IP endpoint that contains an ::ipv4_address and a port.
class ipv4_endpoint : detail::comparable<ipv4_endpoint> {
public:
// -- constructors -----------------------------------------------------------
ipv4_endpoint(ipv4_address address, uint16_t port);
ipv4_endpoint() = default;
ipv4_endpoint(const ipv4_endpoint&) = default;
ipv4_endpoint& operator=(const ipv4_endpoint&) = default;
// -- properties -------------------------------------------------------------
/// Returns the IPv4 address.
ipv4_address address() const noexcept {
return address_;
}
/// Sets the address of this endpoint.
void address(ipv4_address x) noexcept {
address_ = x;
}
/// Returns the port of this endpoint.
uint16_t port() const noexcept {
return port_;
}
/// Sets the port of this endpoint.
void port(uint16_t x) noexcept {
port_ = x;
}
/// Returns a hash for this object
size_t hash_code() const noexcept;
/// Compares this endpoint to `x`.
/// @returns 0 if `*this == x`, a positive value if `*this > x` and a negative
/// value otherwise.
long compare(ipv4_endpoint x) const noexcept;
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f,
ipv4_endpoint& x) {
return f(meta::type_name("ipv4_endpoint"), x.address_, x.port_);
}
private:
ipv4_address address_; /// The address of this endpoint.
uint16_t port_; /// The port of this endpoint.
};
std::string to_string(const ipv4_endpoint& ep);
} // namespace caf
namespace std {
template <>
struct hash<caf::ipv4_endpoint> {
size_t operator()(const caf::ipv4_endpoint& ep) const noexcept {
return ep.hash_code();
}
};
} // namespace std
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/detail/comparable.hpp"
#include "caf/ipv6_address.hpp"
#include "caf/meta/type_name.hpp"
namespace caf {
/// An IP endpoint that contains an ::ipv6_address and a port.
class ipv6_endpoint : detail::comparable<ipv6_endpoint> {
public:
// -- constructors -----------------------------------------------------------
ipv6_endpoint(ipv6_address address, uint16_t port);
ipv6_endpoint() = default;
ipv6_endpoint(const ipv6_endpoint&) = default;
ipv6_endpoint& operator=(const ipv6_endpoint&) = default;
// -- properties -------------------------------------------------------------
/// Returns the IPv6 address.
ipv6_address address() const noexcept {
return address_;
}
/// Sets the address of this endpoint.
void address(ipv6_address x) noexcept {
address_ = x;
}
/// Returns the port of this endpoint.
uint16_t port() const noexcept {
return port_;
}
/// Sets the port of this endpoint.
void port(uint16_t x) noexcept {
port_ = x;
}
/// Returns a hash for this object.
size_t hash_code() const noexcept;
/// Compares this endpoint to `x`.
/// @returns 0 if `*this == x`, a positive value if `*this > x` and a negative
/// value otherwise.
long compare(ipv6_endpoint x) const noexcept;
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f,
ipv6_endpoint& x) {
return f(meta::type_name("ipv6_endpoint"), x.address_, x.port_);
}
private:
/// The address of this endpoint.
ipv6_address address_;
/// The port of this endpoint.
uint16_t port_;
};
std::string to_string(const ipv6_endpoint& ep);
} // namespace caf
namespace std {
template <>
struct hash<caf::ipv6_endpoint> {
size_t operator()(const caf::ipv6_endpoint& ep) const noexcept {
return ep.hash_code();
}
};
} // namespace std
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/ipv4_endpoint.hpp"
#include "caf/detail/fnv_hash.hpp"
namespace caf {
ipv4_endpoint::ipv4_endpoint(ipv4_address address, uint16_t port)
: address_(address), port_(port) {
// nop
}
size_t ipv4_endpoint::hash_code() const noexcept {
auto result = detail::fnv_hash(address_.data());
return detail::fnv_hash_append(result, port_);
}
long ipv4_endpoint::compare(ipv4_endpoint x) const noexcept {
auto res = address_.compare(x.address());
return res == 0 ? port_ - x.port() : res;
}
std::string to_string(const ipv4_endpoint& ep) {
return to_string(ep.address()) + ":" + std::to_string(ep.port());
}
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/ipv6_endpoint.hpp"
#include "caf/detail/fnv_hash.hpp"
namespace caf {
ipv6_endpoint::ipv6_endpoint(ipv6_address address, uint16_t port)
: address_(address), port_(port) {
// nop
}
size_t ipv6_endpoint::hash_code() const noexcept {
auto result = detail::fnv_hash(address_.data());
return detail::fnv_hash_append(result, port_);
}
long ipv6_endpoint::compare(ipv6_endpoint x) const noexcept {
auto res = address_.compare(x.address());
return res == 0 ? port_ - x.port() : res;
}
std::string to_string(const ipv6_endpoint& x) {
std::string result;
auto addr = x.address();
if (addr.embeds_v4()) {
result += to_string(addr);
result += ":";
result += std::to_string(x.port());
} else {
result += '[';
result += to_string(addr);
result += "]:";
result += std::to_string(x.port());
}
return result;
}
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE ipv4_endpoint
#include "caf/ipv4_endpoint.hpp"
#include "caf/test/dsl.hpp"
#include "caf/test/unit_test.hpp"
#include <cassert>
#include <vector>
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/byte.hpp"
#include "caf/ipv4_address.hpp"
#include "caf/serializer_impl.hpp"
#include "caf/span.hpp"
using namespace caf;
namespace {
ipv4_endpoint operator"" _ep(const char* str, size_t) {
std::array<uint8_t, 4> bytes;
char* next = nullptr;
bytes[0] = static_cast<uint8_t>(strtol(str, &next, 10));
for (size_t n = 1; n < 4; ++n) {
assert(*next == '.');
str = next + 1;
bytes[n] = static_cast<uint8_t>(strtol(str, &next, 10));
}
assert(*next == ':');
auto port = static_cast<uint16_t>(strtol(next + 1, nullptr, 10));
return ipv4_endpoint{ipv4_address{bytes}, port};
}
struct fixture {
actor_system_config cfg;
actor_system sys{cfg};
template <class T>
T roundtrip(T x) {
using container_type = std::vector<byte>;
container_type buf;
serializer_impl<container_type> sink(sys, buf);
if (auto err = sink(x))
CAF_FAIL("serialization failed: " << sys.render(err));
binary_deserializer source(sys, make_span(buf));
T y;
if (auto err = source(y))
CAF_FAIL("deserialization failed: " << sys.render(err));
return y;
}
};
#define CHECK_TO_STRING(addr) CAF_CHECK_EQUAL(addr, to_string(addr##_ep))
#define CHECK_COMPARISON(addr1, addr2) \
CAF_CHECK_GREATER(addr2##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr2##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr1##_ep, addr2##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_NOT_EQUAL(addr1##_ep, addr2##_ep); \
CAF_CHECK_NOT_EQUAL(addr2##_ep, addr1##_ep);
#define CHECK_SERIALIZATION(addr) \
CAF_CHECK_EQUAL(addr##_ep, roundtrip(addr##_ep))
} // namespace
CAF_TEST_FIXTURE_SCOPE(ipv4_endpoint_tests, fixture)
CAF_TEST(constructing assigning and hash_code) {
const uint16_t port = 8888;
auto addr = make_ipv4_address(127, 0, 0, 1);
ipv4_endpoint ep1(addr, port);
CAF_CHECK_EQUAL(ep1.address(), addr);
CAF_CHECK_EQUAL(ep1.port(), port);
ipv4_endpoint ep2;
ep2.address(addr);
ep2.port(port);
CAF_CHECK_EQUAL(ep2.address(), addr);
CAF_CHECK_EQUAL(ep2.port(), port);
CAF_CHECK_EQUAL(ep1, ep2);
CAF_CHECK_EQUAL(ep1.hash_code(), ep2.hash_code());
}
CAF_TEST(to string) {
CHECK_TO_STRING("127.0.0.1:8888");
CHECK_TO_STRING("192.168.178.1:8888");
CHECK_TO_STRING("255.255.255.1:17");
CHECK_TO_STRING("192.168.178.1:8888");
CHECK_TO_STRING("127.0.0.1:111");
CHECK_TO_STRING("123.123.123.123:8888");
CHECK_TO_STRING("127.0.0.1:8888");
}
CAF_TEST(comparison) {
CHECK_COMPARISON("127.0.0.1:8888", "127.0.0.2:8888");
CHECK_COMPARISON("192.168.178.1:8888", "245.114.2.89:8888");
CHECK_COMPARISON("188.56.23.97:1211", "189.22.36.0:1211");
CHECK_COMPARISON("0.0.0.0:8888", "255.255.255.1:8888");
CHECK_COMPARISON("127.0.0.1:111", "127.0.0.1:8888");
CHECK_COMPARISON("192.168.178.1:8888", "245.114.2.89:8888");
CHECK_COMPARISON("123.123.123.123:8888", "123.123.123.123:8889");
}
CAF_TEST(serialization) {
CHECK_SERIALIZATION("127.0.0.1:8888");
CHECK_SERIALIZATION("192.168.178.1:8888");
CHECK_SERIALIZATION("255.255.255.1:17");
CHECK_SERIALIZATION("192.168.178.1:8888");
CHECK_SERIALIZATION("127.0.0.1:111");
CHECK_SERIALIZATION("123.123.123.123:8888");
CHECK_SERIALIZATION("127.0.0.1:8888");
}
CAF_TEST_FIXTURE_SCOPE_END()
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE ipv6_endpoint
#include "caf/ipv6_endpoint.hpp"
#include "caf/test/unit_test.hpp"
#include <cassert>
#include <vector>
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/byte.hpp"
#include "caf/ipv6_address.hpp"
#include "caf/serializer_impl.hpp"
#include "caf/span.hpp"
using namespace caf;
namespace {
ipv6_endpoint operator"" _ep(const char* str, size_t) {
union {
std::array<uint8_t, 16> xs_bytes;
std::array<uint16_t, 8> xs;
};
union {
std::array<uint8_t, 16> ys_bytes;
std::array<uint16_t, 8> ys;
};
memset(xs_bytes.data(), 0, xs_bytes.size());
memset(ys_bytes.data(), 0, xs_bytes.size());
assert(*str == '[');
++str;
char* next = nullptr;
auto pull = [&] {
auto x = static_cast<uint16_t>(strtol(str, &next, 16));
return detail::to_network_order(x);
};
size_t n = 0;
do {
xs[n++] = pull();
assert(next != nullptr);
str = next + 1;
} while (*str != ':' && *str != ']');
if (*str == ':') {
++str;
do {
ys[0] = pull();
std::rotate(ys.begin(), ys.begin() + 1, ys.end());
assert(next != nullptr);
str = next + 1;
} while (*next != ']');
}
assert(*next == ']');
assert(*str == ':');
++str;
auto port = static_cast<uint16_t>(strtol(str, nullptr, 10));
std::array<uint8_t, 16> bytes;
for (size_t i = 0; i < 16; ++i)
bytes[i] = xs_bytes[i] | ys_bytes[i];
return ipv6_endpoint{ipv6_address{bytes}, port};
}
struct fixture {
actor_system_config cfg;
actor_system sys{cfg};
template <class T>
T roundtrip(T x) {
using container_type = std::vector<byte>;
container_type buf;
serializer_impl<container_type> sink(sys, buf);
if (auto err = sink(x))
CAF_FAIL("serialization failed: " << sys.render(err));
binary_deserializer source(sys, make_span(buf));
T y;
if (auto err = source(y))
CAF_FAIL("deserialization failed: " << sys.render(err));
return y;
}
};
#define CHECK_TO_STRING(addr) CAF_CHECK_EQUAL(addr, to_string(addr##_ep))
#define CHECK_COMPARISON(addr1, addr2) \
CAF_CHECK_GREATER(addr2##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr2##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_GREATER_OR_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr1##_ep, addr2##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr1##_ep, addr1##_ep); \
CAF_CHECK_LESS_OR_EQUAL(addr2##_ep, addr2##_ep); \
CAF_CHECK_NOT_EQUAL(addr1##_ep, addr2##_ep); \
CAF_CHECK_NOT_EQUAL(addr2##_ep, addr1##_ep);
#define CHECK_SERIALIZATION(addr) \
CAF_CHECK_EQUAL(addr##_ep, roundtrip(addr##_ep))
} // namespace
CAF_TEST_FIXTURE_SCOPE(comparison_scope, fixture)
CAF_TEST(constructing assigning and hash_code) {
const uint16_t port = 8888;
ipv6_address::array_type bytes{0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
auto addr = ipv6_address{bytes};
ipv6_endpoint ep1(addr, port);
CAF_CHECK_EQUAL(ep1.address(), addr);
CAF_CHECK_EQUAL(ep1.port(), port);
ipv6_endpoint ep2;
ep2.address(addr);
ep2.port(port);
CAF_CHECK_EQUAL(ep2.address(), addr);
CAF_CHECK_EQUAL(ep2.port(), port);
CAF_CHECK_EQUAL(ep1, ep2);
CAF_CHECK_EQUAL(ep1.hash_code(), ep2.hash_code());
}
CAF_TEST(to_string) {
CHECK_TO_STRING("[::1]:8888");
CHECK_TO_STRING("[4e::d00:0:ed00:0:1]:1234");
CHECK_TO_STRING("[::1]:1111");
CHECK_TO_STRING("[4432::33:1]:8732");
CHECK_TO_STRING("[::2]:8888");
CHECK_TO_STRING("[4f::d00:12:ed00:0:1]:1234");
CHECK_TO_STRING("[4f::1]:2222");
CHECK_TO_STRING("[4432:8d::33:1]:8732");
CHECK_TO_STRING("[4e::d00:0:ed00:0:1]:5678");
CHECK_TO_STRING("[::1]:2221");
CHECK_TO_STRING("[::1]:2222");
CHECK_TO_STRING("[4432::33:1]:872");
CHECK_TO_STRING("[4432::33:1]:999");
}
CAF_TEST(comparison) {
CHECK_COMPARISON("[::1]:8888", "[::2]:8888");
CHECK_COMPARISON("[4e::d00:0:ed00:0:1]:1234", "[4f::d00:12:ed00:0:1]:1234");
CHECK_COMPARISON("[::1]:1111", "[4f::1]:2222");
CHECK_COMPARISON("[4432::33:1]:8732", "[4432:8d::33:1]:8732");
CHECK_COMPARISON("[::1]:1111", "[::1]:8888");
CHECK_COMPARISON("[4e::d00:0:ed00:0:1]:1234", "[4e::d00:0:ed00:0:1]:5678");
CHECK_COMPARISON("[::1]:2221", "[::1]:2222");
CHECK_COMPARISON("[4432::33:1]:872", "[4432::33:1]:999");
}
CAF_TEST(serialization) {
CHECK_SERIALIZATION("[::1]:8888");
CHECK_SERIALIZATION("[4e::d00:0:ed00:0:1]:1234");
CHECK_SERIALIZATION("[::1]:1111");
CHECK_SERIALIZATION("[4432::33:1]:8732");
CHECK_SERIALIZATION("[::2]:8888");
CHECK_SERIALIZATION("[4f::d00:12:ed00:0:1]:1234");
CHECK_SERIALIZATION("[4f::1]:2222");
CHECK_SERIALIZATION("[4432:8d::33:1]:8732");
CHECK_SERIALIZATION("[4e::d00:0:ed00:0:1]:5678");
CHECK_SERIALIZATION("[::1]:2221");
CHECK_SERIALIZATION("[::1]:2222");
CHECK_SERIALIZATION("[4432::33:1]:872");
CHECK_SERIALIZATION("[4432::33:1]:999");
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment