mirror of
https://github.com/zeromq/libzmq.git
synced 2024-12-12 18:40:27 +01:00
commit
363fa7892d
@ -20,6 +20,69 @@
|
|||||||
|
|
||||||
#include "ip_resolver.hpp"
|
#include "ip_resolver.hpp"
|
||||||
|
|
||||||
|
int zmq::ip_addr_t::family () const
|
||||||
|
{
|
||||||
|
return generic.sa_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zmq::ip_addr_t::is_multicast () const
|
||||||
|
{
|
||||||
|
if (family () == AF_INET) {
|
||||||
|
// IPv4 Multicast: address MSBs are 1110
|
||||||
|
// Range: 224.0.0.0 - 239.255.255.255
|
||||||
|
return IN_MULTICAST (ntohl (ipv4.sin_addr.s_addr));
|
||||||
|
} else {
|
||||||
|
// IPv6 Multicast: ff00::/8
|
||||||
|
return IN6_IS_ADDR_MULTICAST (&ipv6.sin6_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t zmq::ip_addr_t::port () const
|
||||||
|
{
|
||||||
|
if (family () == AF_INET6) {
|
||||||
|
return ntohs (ipv6.sin6_port);
|
||||||
|
} else {
|
||||||
|
return ntohs (ipv4.sin_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zmq::ip_addr_t::set_port (uint16_t port)
|
||||||
|
{
|
||||||
|
if (family () == AF_INET6) {
|
||||||
|
ipv6.sin6_port = htons (port);
|
||||||
|
} else {
|
||||||
|
ipv4.sin_port = htons (port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct an "ANY" address for the given family
|
||||||
|
zmq::ip_addr_t zmq::ip_addr_t::any (int family)
|
||||||
|
{
|
||||||
|
ip_addr_t addr;
|
||||||
|
|
||||||
|
if (family == AF_INET) {
|
||||||
|
sockaddr_in *ip4_addr = &addr.ipv4;
|
||||||
|
memset (ip4_addr, 0, sizeof (*ip4_addr));
|
||||||
|
ip4_addr->sin_family = AF_INET;
|
||||||
|
ip4_addr->sin_addr.s_addr = htonl (INADDR_ANY);
|
||||||
|
} else if (family == AF_INET6) {
|
||||||
|
sockaddr_in6 *ip6_addr = &addr.ipv6;
|
||||||
|
|
||||||
|
memset (ip6_addr, 0, sizeof (*ip6_addr));
|
||||||
|
ip6_addr->sin6_family = AF_INET6;
|
||||||
|
#ifdef ZMQ_HAVE_VXWORKS
|
||||||
|
struct in6_addr newaddr = IN6ADDR_ANY_INIT;
|
||||||
|
memcpy (&ip6_addr->sin6_addr, &newaddr, sizeof (in6_addr));
|
||||||
|
#else
|
||||||
|
memcpy (&ip6_addr->sin6_addr, &in6addr_any, sizeof (in6addr_any));
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
assert (0 == "unsupported address family");
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
zmq::ip_resolver_options_t::ip_resolver_options_t () :
|
zmq::ip_resolver_options_t::ip_resolver_options_t () :
|
||||||
bindable_wanted (false),
|
bindable_wanted (false),
|
||||||
nic_name_allowed (false),
|
nic_name_allowed (false),
|
||||||
@ -176,25 +239,8 @@ int zmq::ip_resolver_t::resolve (ip_addr_t *ip_addr_, const char *name_)
|
|||||||
|
|
||||||
if (options.bindable () && addr == "*") {
|
if (options.bindable () && addr == "*") {
|
||||||
// Return an ANY address
|
// Return an ANY address
|
||||||
|
*ip_addr_ = ip_addr_t::any (options.ipv6 () ? AF_INET6 : AF_INET);
|
||||||
resolved = true;
|
resolved = true;
|
||||||
|
|
||||||
if (options.ipv6 ()) {
|
|
||||||
sockaddr_in6 *ip6_addr = &ip_addr_->ipv6;
|
|
||||||
|
|
||||||
memset (ip6_addr, 0, sizeof (*ip6_addr));
|
|
||||||
ip6_addr->sin6_family = AF_INET6;
|
|
||||||
#ifdef ZMQ_HAVE_VXWORKS
|
|
||||||
struct in6_addr newaddr = IN6ADDR_ANY_INIT;
|
|
||||||
memcpy (&ip6_addr->sin6_addr, &newaddr, sizeof (in6_addr));
|
|
||||||
#else
|
|
||||||
memcpy (&ip6_addr->sin6_addr, &in6addr_any, sizeof (in6addr_any));
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
sockaddr_in *ip4_addr = &ip_addr_->ipv4;
|
|
||||||
memset (ip4_addr, 0, sizeof (*ip4_addr));
|
|
||||||
ip4_addr->sin_family = AF_INET;
|
|
||||||
ip4_addr->sin_addr.s_addr = htonl (INADDR_ANY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resolved && options.allow_nic_name ()) {
|
if (!resolved && options.allow_nic_name ()) {
|
||||||
@ -221,11 +267,10 @@ int zmq::ip_resolver_t::resolve (ip_addr_t *ip_addr_, const char *name_)
|
|||||||
// for us but since we don't resolve service names it's a bit overkill and
|
// for us but since we don't resolve service names it's a bit overkill and
|
||||||
// we'd still have to do it manually when the address is resolved by
|
// we'd still have to do it manually when the address is resolved by
|
||||||
// 'resolve_nic_name'
|
// 'resolve_nic_name'
|
||||||
if (ip_addr_->generic.sa_family == AF_INET6) {
|
ip_addr_->set_port (port);
|
||||||
ip_addr_->ipv6.sin6_port = htons (port);
|
|
||||||
|
if (ip_addr_->family () == AF_INET6) {
|
||||||
ip_addr_->ipv6.sin6_scope_id = zone_id;
|
ip_addr_->ipv6.sin6_scope_id = zone_id;
|
||||||
} else {
|
|
||||||
ip_addr_->ipv4.sin_port = htons (port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (resolved == true);
|
assert (resolved == true);
|
||||||
|
@ -42,6 +42,13 @@ union ip_addr_t
|
|||||||
sockaddr generic;
|
sockaddr generic;
|
||||||
sockaddr_in ipv4;
|
sockaddr_in ipv4;
|
||||||
sockaddr_in6 ipv6;
|
sockaddr_in6 ipv6;
|
||||||
|
|
||||||
|
int family () const;
|
||||||
|
bool is_multicast () const;
|
||||||
|
uint16_t port () const;
|
||||||
|
void set_port (uint16_t);
|
||||||
|
|
||||||
|
static ip_addr_t any (int family);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ip_resolver_options_t
|
class ip_resolver_options_t
|
||||||
|
@ -116,8 +116,7 @@ int zmq::tcp_address_t::resolve (const char *name_, bool local_, bool ipv6_)
|
|||||||
|
|
||||||
int zmq::tcp_address_t::to_string (std::string &addr_)
|
int zmq::tcp_address_t::to_string (std::string &addr_)
|
||||||
{
|
{
|
||||||
if (address.generic.sa_family != AF_INET
|
if (address.family () != AF_INET && address.family () != AF_INET6) {
|
||||||
&& address.generic.sa_family != AF_INET6) {
|
|
||||||
addr_.clear ();
|
addr_.clear ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -132,7 +131,7 @@ int zmq::tcp_address_t::to_string (std::string &addr_)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.generic.sa_family == AF_INET6) {
|
if (address.family () == AF_INET6) {
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "tcp://[" << hbuf << "]:" << ntohs (address.ipv6.sin6_port);
|
s << "tcp://[" << hbuf << "]:" << ntohs (address.ipv6.sin6_port);
|
||||||
addr_ = s.str ();
|
addr_ = s.str ();
|
||||||
@ -164,7 +163,7 @@ const sockaddr *zmq::tcp_address_t::src_addr () const
|
|||||||
|
|
||||||
socklen_t zmq::tcp_address_t::src_addrlen () const
|
socklen_t zmq::tcp_address_t::src_addrlen () const
|
||||||
{
|
{
|
||||||
if (address.generic.sa_family == AF_INET6)
|
if (address.family () == AF_INET6)
|
||||||
return (socklen_t) sizeof (source_address.ipv6);
|
return (socklen_t) sizeof (source_address.ipv6);
|
||||||
else
|
else
|
||||||
return (socklen_t) sizeof (source_address.ipv4);
|
return (socklen_t) sizeof (source_address.ipv4);
|
||||||
@ -181,7 +180,7 @@ unsigned short zmq::tcp_address_t::family () const
|
|||||||
sa_family_t zmq::tcp_address_t::family () const
|
sa_family_t zmq::tcp_address_t::family () const
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return address.generic.sa_family;
|
return address.family ();
|
||||||
}
|
}
|
||||||
|
|
||||||
zmq::tcp_address_mask_t::tcp_address_mask_t () :
|
zmq::tcp_address_mask_t::tcp_address_mask_t () :
|
||||||
@ -228,7 +227,7 @@ int zmq::tcp_address_mask_t::resolve (const char *name_, bool ipv6_)
|
|||||||
|
|
||||||
// Parse the cidr mask number.
|
// Parse the cidr mask number.
|
||||||
if (mask_str.empty ()) {
|
if (mask_str.empty ()) {
|
||||||
if (address.generic.sa_family == AF_INET6)
|
if (address.family () == AF_INET6)
|
||||||
address_mask = 128;
|
address_mask = 128;
|
||||||
else
|
else
|
||||||
address_mask = 32;
|
address_mask = 32;
|
||||||
@ -236,8 +235,8 @@ int zmq::tcp_address_mask_t::resolve (const char *name_, bool ipv6_)
|
|||||||
address_mask = 0;
|
address_mask = 0;
|
||||||
else {
|
else {
|
||||||
const int mask = atoi (mask_str.c_str ());
|
const int mask = atoi (mask_str.c_str ());
|
||||||
if ((mask < 1) || (address.generic.sa_family == AF_INET6 && mask > 128)
|
if ((mask < 1) || (address.family () == AF_INET6 && mask > 128)
|
||||||
|| (address.generic.sa_family != AF_INET6 && mask > 32)) {
|
|| (address.family () != AF_INET6 && mask > 32)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -249,8 +248,7 @@ int zmq::tcp_address_mask_t::resolve (const char *name_, bool ipv6_)
|
|||||||
|
|
||||||
int zmq::tcp_address_mask_t::to_string (std::string &addr_)
|
int zmq::tcp_address_mask_t::to_string (std::string &addr_)
|
||||||
{
|
{
|
||||||
if (address.generic.sa_family != AF_INET
|
if (address.family () != AF_INET && address.family () != AF_INET6) {
|
||||||
&& address.generic.sa_family != AF_INET6) {
|
|
||||||
addr_.clear ();
|
addr_.clear ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -267,7 +265,7 @@ int zmq::tcp_address_mask_t::to_string (std::string &addr_)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.generic.sa_family == AF_INET6) {
|
if (address.family () == AF_INET6) {
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s << "[" << hbuf << "]/" << address_mask;
|
s << "[" << hbuf << "]/" << address_mask;
|
||||||
addr_ = s.str ();
|
addr_ = s.str ();
|
||||||
|
@ -58,53 +58,106 @@ zmq::udp_address_t::~udp_address_t ()
|
|||||||
|
|
||||||
int zmq::udp_address_t::resolve (const char *name_, bool bind_)
|
int zmq::udp_address_t::resolve (const char *name_, bool bind_)
|
||||||
{
|
{
|
||||||
|
// No IPv6 support yet
|
||||||
|
int family = AF_INET;
|
||||||
|
bool ipv6 = family == AF_INET6;
|
||||||
|
bool has_interface = false;
|
||||||
|
ip_addr_t interface_addr;
|
||||||
|
|
||||||
|
// If we have a semicolon then we should have an interface specifier in the
|
||||||
|
// URL
|
||||||
|
const char *src_delimiter = strrchr (name_, ';');
|
||||||
|
if (src_delimiter) {
|
||||||
|
std::string src_name (name_, src_delimiter - name_);
|
||||||
|
|
||||||
|
ip_resolver_options_t src_resolver_opts;
|
||||||
|
|
||||||
|
src_resolver_opts
|
||||||
|
.bindable (true)
|
||||||
|
// Restrict hostname/service to literals to avoid any DNS
|
||||||
|
// lookups or service-name irregularity due to
|
||||||
|
// indeterminate socktype.
|
||||||
|
.allow_dns (false)
|
||||||
|
.allow_nic_name (true)
|
||||||
|
.ipv6 (ipv6)
|
||||||
|
.expect_port (false);
|
||||||
|
|
||||||
|
ip_resolver_t src_resolver (src_resolver_opts);
|
||||||
|
|
||||||
|
const int rc =
|
||||||
|
src_resolver.resolve (&interface_addr, src_name.c_str ());
|
||||||
|
|
||||||
|
if (rc != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interface_addr.is_multicast ()) {
|
||||||
|
// It doesn't make sense to have a multicast address as a source
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_interface = true;
|
||||||
|
name_ = src_delimiter + 1;
|
||||||
|
}
|
||||||
|
|
||||||
ip_resolver_options_t resolver_opts;
|
ip_resolver_options_t resolver_opts;
|
||||||
|
|
||||||
resolver_opts.bindable (bind_)
|
resolver_opts.bindable (bind_)
|
||||||
.allow_dns (!bind_)
|
.allow_dns (!bind_)
|
||||||
.allow_nic_name (bind_)
|
.allow_nic_name (bind_)
|
||||||
.expect_port (true)
|
.expect_port (true)
|
||||||
.ipv6 (false);
|
.ipv6 (ipv6);
|
||||||
|
|
||||||
ip_resolver_t resolver (resolver_opts);
|
ip_resolver_t resolver (resolver_opts);
|
||||||
ip_addr_t addr;
|
|
||||||
|
|
||||||
int rc = resolver.resolve (&addr, name_);
|
ip_addr_t target_addr;
|
||||||
|
|
||||||
|
int rc = resolver.resolve (&target_addr, name_);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr.generic.sa_family != AF_INET) {
|
is_multicast = target_addr.is_multicast ();
|
||||||
// Shouldn't happen
|
uint16_t port = target_addr.port ();
|
||||||
return -1;
|
|
||||||
|
if (has_interface) {
|
||||||
|
// If we have an interface specifier then the target address must be a
|
||||||
|
// multicast address
|
||||||
|
if (!is_multicast) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface_addr.set_port (port);
|
||||||
|
|
||||||
|
dest_address = target_addr.ipv4;
|
||||||
|
bind_address = interface_addr.ipv4;
|
||||||
|
} else {
|
||||||
|
// If we don't have an explicit interface specifier then the URL is
|
||||||
|
// ambiguous: if the target address is multicast then it's the
|
||||||
|
// destination address and the bind address is ANY, if it's unicast
|
||||||
|
// then it's the bind address when 'bind_' is true and the destination
|
||||||
|
// otherwise
|
||||||
|
ip_addr_t any = ip_addr_t::any (family);
|
||||||
|
any.set_port (port);
|
||||||
|
|
||||||
|
if (is_multicast) {
|
||||||
|
dest_address = target_addr.ipv4;
|
||||||
|
bind_address = any.ipv4;
|
||||||
|
} else {
|
||||||
|
if (bind_) {
|
||||||
|
dest_address = target_addr.ipv4;
|
||||||
|
bind_address = target_addr.ipv4;
|
||||||
|
} else {
|
||||||
|
dest_address = target_addr.ipv4;
|
||||||
|
bind_address = any.ipv4;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dest_address = addr.ipv4;
|
if (is_multicast) {
|
||||||
|
|
||||||
// we will check only first byte of IP
|
|
||||||
// and if it from 224 to 239, then it can
|
|
||||||
// represent multicast IP.
|
|
||||||
int i = dest_address.sin_addr.s_addr & 0xFF;
|
|
||||||
if (i >= 224 && i <= 239) {
|
|
||||||
multicast = dest_address.sin_addr;
|
multicast = dest_address.sin_addr;
|
||||||
is_multicast = true;
|
|
||||||
} else
|
|
||||||
is_multicast = false;
|
|
||||||
|
|
||||||
iface.s_addr = htonl (INADDR_ANY);
|
|
||||||
if (iface.s_addr == INADDR_NONE) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a should bind and not a multicast, the dest address
|
|
||||||
// is actually the bind address
|
|
||||||
if (bind_ && !is_multicast)
|
|
||||||
bind_address = dest_address;
|
|
||||||
else {
|
|
||||||
bind_address.sin_family = AF_INET;
|
|
||||||
bind_address.sin_port = dest_address.sin_port;
|
|
||||||
bind_address.sin_addr.s_addr = htonl (INADDR_ANY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
address = name_;
|
address = name_;
|
||||||
|
@ -157,7 +157,7 @@ static void test_resolve (zmq::ip_resolver_options_t opts_,
|
|||||||
|
|
||||||
#if defined ZMQ_HAVE_WINDOWS
|
#if defined ZMQ_HAVE_WINDOWS
|
||||||
if (family == AF_INET6 && expected_addr_v4_failover_ != NULL &&
|
if (family == AF_INET6 && expected_addr_v4_failover_ != NULL &&
|
||||||
addr.generic.sa_family == AF_INET) {
|
addr.family () == AF_INET) {
|
||||||
// We've requested an IPv6 but the system gave us an IPv4, use the
|
// We've requested an IPv6 but the system gave us an IPv4, use the
|
||||||
// failover address
|
// failover address
|
||||||
family = AF_INET;
|
family = AF_INET;
|
||||||
@ -167,7 +167,7 @@ static void test_resolve (zmq::ip_resolver_options_t opts_,
|
|||||||
(void)expected_addr_v4_failover_;
|
(void)expected_addr_v4_failover_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL (family, addr.generic.sa_family);
|
TEST_ASSERT_EQUAL (family, addr.family ());
|
||||||
|
|
||||||
if (family == AF_INET6) {
|
if (family == AF_INET6) {
|
||||||
struct in6_addr expected_addr;
|
struct in6_addr expected_addr;
|
||||||
@ -187,7 +187,6 @@ static void test_resolve (zmq::ip_resolver_options_t opts_,
|
|||||||
|
|
||||||
assert (test_inet_pton (AF_INET, expected_addr_, &expected_addr) == 1);
|
assert (test_inet_pton (AF_INET, expected_addr_, &expected_addr) == 1);
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL (AF_INET, addr.generic.sa_family);
|
|
||||||
TEST_ASSERT_EQUAL (expected_addr.s_addr, ip4_addr->sin_addr.s_addr);
|
TEST_ASSERT_EQUAL (expected_addr.s_addr, ip4_addr->sin_addr.s_addr);
|
||||||
TEST_ASSERT_EQUAL (htons (expected_port_), ip4_addr->sin_port);
|
TEST_ASSERT_EQUAL (htons (expected_port_), ip4_addr->sin_port);
|
||||||
}
|
}
|
||||||
@ -823,6 +822,82 @@ void test_dns_ipv6_scope_port_brackets ()
|
|||||||
"fdf5:d058:d656::1", 4444, 1);
|
"fdf5:d058:d656::1", 4444, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_addr (int family_, const char *addr_, bool multicast_)
|
||||||
|
{
|
||||||
|
if (family_ == AF_INET6 && !is_ipv6_available ()) {
|
||||||
|
TEST_IGNORE_MESSAGE ("ipv6 is not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
zmq::ip_resolver_options_t resolver_opts;
|
||||||
|
|
||||||
|
resolver_opts.ipv6 (family_ == AF_INET6);
|
||||||
|
|
||||||
|
test_ip_resolver_t resolver (resolver_opts);
|
||||||
|
zmq::ip_addr_t addr;
|
||||||
|
|
||||||
|
int rc = resolver.resolve (&addr, addr_);
|
||||||
|
|
||||||
|
assert (rc == 0);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL (family_, addr.family ());
|
||||||
|
TEST_ASSERT_EQUAL (multicast_, addr.is_multicast ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_unicast_ipv4 ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "1.2.3.4", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_unicast_ipv6 ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET6, "abcd::1", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv4 ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "230.1.2.3", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv6 ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET6, "ffab::1234", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv4_min ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "224.0.0.0", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv6_min ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET6, "ff00::", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv4_max ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "239.255.255.255", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv6_max ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv4_sub ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "223.255.255.255", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv6_sub ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET6, "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_addr_multicast_ipv4_over ()
|
||||||
|
{
|
||||||
|
test_addr (AF_INET, "240.0.0.0", false);
|
||||||
|
}
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
zmq::initialize_network ();
|
zmq::initialize_network ();
|
||||||
@ -901,6 +976,17 @@ int main (void)
|
|||||||
RUN_TEST (test_dns_ipv6_scope);
|
RUN_TEST (test_dns_ipv6_scope);
|
||||||
RUN_TEST (test_dns_ipv6_scope_port);
|
RUN_TEST (test_dns_ipv6_scope_port);
|
||||||
RUN_TEST (test_dns_ipv6_scope_port_brackets);
|
RUN_TEST (test_dns_ipv6_scope_port_brackets);
|
||||||
|
RUN_TEST (test_addr_unicast_ipv4);
|
||||||
|
RUN_TEST (test_addr_unicast_ipv6);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv4);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv6);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv4_min);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv6_min);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv4_max);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv6_max);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv4_sub);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv6_sub);
|
||||||
|
RUN_TEST (test_addr_multicast_ipv4_over);
|
||||||
|
|
||||||
zmq::shutdown_network ();
|
zmq::shutdown_network ();
|
||||||
|
|
||||||
|
@ -31,18 +31,16 @@ void tearDown ()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test an UDP address resolution. If 'bind_addr_' is not NULL
|
// Test an UDP address resolution. If 'dest_addr_' is NULL assume the
|
||||||
// request a bind address. If 'dest_addr_' is NULL assume the
|
|
||||||
// resolution is supposed to fail.
|
// resolution is supposed to fail.
|
||||||
static void test_resolve (const char *name_, const char *dest_addr_,
|
static void test_resolve (bool bind_, const char *name_, const char *dest_addr_,
|
||||||
uint16_t expected_port_ = 0,
|
uint16_t expected_port_,
|
||||||
const char *bind_addr_ = NULL,
|
const char *bind_addr_,
|
||||||
bool multicast_ = false)
|
bool multicast_)
|
||||||
{
|
{
|
||||||
zmq::udp_address_t addr;
|
zmq::udp_address_t addr;
|
||||||
bool bound = bind_addr_ != NULL;
|
|
||||||
|
|
||||||
int rc = addr.resolve (name_, bound);
|
int rc = addr.resolve (name_, bind_);
|
||||||
|
|
||||||
if (dest_addr_ == NULL) {
|
if (dest_addr_ == NULL) {
|
||||||
TEST_ASSERT_EQUAL (-1, rc);
|
TEST_ASSERT_EQUAL (-1, rc);
|
||||||
@ -77,55 +75,73 @@ static void test_resolve (const char *name_, const char *dest_addr_,
|
|||||||
TEST_ASSERT_EQUAL (htons (expected_port_), bind->sin_port);
|
TEST_ASSERT_EQUAL (htons (expected_port_), bind->sin_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_resolve_bind (const char *name_, const char *dest_addr_,
|
||||||
|
uint16_t expected_port_ = 0,
|
||||||
|
const char *bind_addr_ = NULL,
|
||||||
|
bool multicast_ = false)
|
||||||
|
{
|
||||||
|
test_resolve (true, name_, dest_addr_, expected_port_, bind_addr_,
|
||||||
|
multicast_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_connect (const char *name_, const char *dest_addr_,
|
||||||
|
uint16_t expected_port_ = 0,
|
||||||
|
const char *bind_addr_ = NULL,
|
||||||
|
bool multicast_ = false)
|
||||||
|
{
|
||||||
|
test_resolve (false, name_, dest_addr_, expected_port_, bind_addr_,
|
||||||
|
multicast_);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_simple ()
|
static void test_resolve_ipv4_simple ()
|
||||||
{
|
{
|
||||||
test_resolve ("127.0.0.1:5555", "127.0.0.1", 5555);
|
test_resolve_connect ("127.0.0.1:5555", "127.0.0.1", 5555);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_bind ()
|
static void test_resolve_ipv4_bind ()
|
||||||
{
|
{
|
||||||
test_resolve ("127.0.0.1:5555", "127.0.0.1", 5555, "127.0.0.1");
|
test_resolve_bind ("127.0.0.1:5555", "127.0.0.1", 5555, "127.0.0.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_bind_any ()
|
static void test_resolve_ipv4_bind_any ()
|
||||||
{
|
{
|
||||||
test_resolve ("*:*", "0.0.0.0", 0, "0.0.0.0");
|
test_resolve_bind ("*:*", "0.0.0.0", 0, "0.0.0.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_bind_anyport ()
|
static void test_resolve_ipv4_bind_anyport ()
|
||||||
{
|
{
|
||||||
test_resolve ("127.0.0.1:*", "127.0.0.1", 0, "127.0.0.1");
|
test_resolve_bind ("127.0.0.1:*", "127.0.0.1", 0, "127.0.0.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_bind_any_port ()
|
static void test_resolve_ipv4_bind_any_port ()
|
||||||
{
|
{
|
||||||
test_resolve ("*:5555", "0.0.0.0", 5555, "0.0.0.0");
|
test_resolve_bind ("*:5555", "0.0.0.0", 5555, "0.0.0.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_connect_any ()
|
static void test_resolve_ipv4_connect_any ()
|
||||||
{
|
{
|
||||||
// Cannot use wildcard for connection
|
// Cannot use wildcard for connection
|
||||||
test_resolve ("*:5555", NULL);
|
test_resolve_connect ("*:5555", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_connect_anyport ()
|
static void test_resolve_ipv4_connect_anyport ()
|
||||||
{
|
{
|
||||||
test_resolve ("127.0.0.1:*", NULL);
|
test_resolve_connect ("127.0.0.1:*", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_connect_port0 ()
|
static void test_resolve_ipv4_connect_port0 ()
|
||||||
{
|
{
|
||||||
test_resolve ("127.0.0.1:0", "127.0.0.1", 0);
|
test_resolve_connect ("127.0.0.1:0", "127.0.0.1", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_bind_mcast ()
|
static void test_resolve_ipv4_bind_mcast ()
|
||||||
{
|
{
|
||||||
test_resolve ("239.0.0.1:1234", "239.0.0.1", 1234, "0.0.0.0", true);
|
test_resolve_bind ("239.0.0.1:1234", "239.0.0.1", 1234, "0.0.0.0", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv4_connect_mcast ()
|
static void test_resolve_ipv4_connect_mcast ()
|
||||||
{
|
{
|
||||||
test_resolve ("239.0.0.1:2222", "239.0.0.1", 2222, NULL, true);
|
test_resolve_connect ("239.0.0.1:2222", "239.0.0.1", 2222, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_resolve_ipv6_simple ()
|
static void test_resolve_ipv6_simple ()
|
||||||
@ -135,7 +151,41 @@ static void test_resolve_ipv6_simple ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IPv6 not yet supported
|
// IPv6 not yet supported
|
||||||
test_resolve ("::1", NULL);
|
test_resolve_connect ("::1", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_bind ()
|
||||||
|
{
|
||||||
|
test_resolve_bind ("127.0.0.1;230.2.8.12:5555", "230.2.8.12", 5555,
|
||||||
|
"127.0.0.1", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_bind_any ()
|
||||||
|
{
|
||||||
|
test_resolve_bind ("*;230.2.8.12:5555", "230.2.8.12", 5555,
|
||||||
|
"0.0.0.0", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_connect ()
|
||||||
|
{
|
||||||
|
test_resolve_connect ("8.9.10.11;230.2.8.12:5555", "230.2.8.12", 5555,
|
||||||
|
"8.9.10.11", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_connect_any ()
|
||||||
|
{
|
||||||
|
test_resolve_connect ("*;230.2.8.12:5555", "230.2.8.12", 5555,
|
||||||
|
"0.0.0.0", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_bind_bad ()
|
||||||
|
{
|
||||||
|
test_resolve_bind ("127.0.0.1;1.2.3.4:5555", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_resolve_ipv4_mcast_src_connect_bad ()
|
||||||
|
{
|
||||||
|
test_resolve_connect ("127.0.0.1;1.2.3.4:5555", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
@ -156,6 +206,12 @@ int main (void)
|
|||||||
RUN_TEST (test_resolve_ipv4_bind_mcast);
|
RUN_TEST (test_resolve_ipv4_bind_mcast);
|
||||||
RUN_TEST (test_resolve_ipv4_connect_mcast);
|
RUN_TEST (test_resolve_ipv4_connect_mcast);
|
||||||
RUN_TEST (test_resolve_ipv6_simple);
|
RUN_TEST (test_resolve_ipv6_simple);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_bind);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_bind_any);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_connect);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_connect_any);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_bind_bad);
|
||||||
|
RUN_TEST (test_resolve_ipv4_mcast_src_connect_bad);
|
||||||
|
|
||||||
zmq::shutdown_network ();
|
zmq::shutdown_network ();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user