Commit 2dc85794 authored by Lionel Flandrin's avatar Lionel Flandrin

Problem: the UDP address code uses an ad hoc custom parser

Solution: replace it with the ip_resolver code shared with the TCP
address code

It simplifies the UDP parsing code and makes it behave more like the
TCP counterpart, in particular it's not possible to connect to hosts
by name and bind by NIC names.

It also adds support for "*" port resolving to 0 (useful to let the OS
allocate the port number).
parent 0b36b842
......@@ -44,6 +44,8 @@
#include <ctype.h>
#endif
#include "ip_resolver.hpp"
zmq::udp_address_t::udp_address_t () : is_multicast (false)
{
memset (&bind_address, 0, sizeof bind_address);
......@@ -56,38 +58,29 @@ zmq::udp_address_t::~udp_address_t ()
int zmq::udp_address_t::resolve (const char *name_, bool bind_)
{
// Find the ':' at end that separates address from the port number.
const char *delimiter = strrchr (name_, ':');
if (!delimiter) {
errno = EINVAL;
return -1;
}
ip_resolver_options_t resolver_opts;
// Separate the address/port.
std::string addr_str (name_, delimiter - name_);
std::string port_str (delimiter + 1);
resolver_opts.bindable (bind_)
.allow_dns (!bind_)
.allow_nic_name (bind_)
.expect_port (true)
.ipv6 (false);
// Parse the port number (0 is not a valid port).
uint16_t port = (uint16_t) atoi (port_str.c_str ());
if (port == 0) {
errno = EINVAL;
ip_resolver_t resolver (resolver_opts);
ip_addr_t addr;
int rc = resolver.resolve (&addr, name_);
if (rc != 0) {
return -1;
}
dest_address.sin_family = AF_INET;
dest_address.sin_port = htons (port);
// Only when the udp should bind we allow * as the address
if (addr_str == "*" && bind_)
dest_address.sin_addr.s_addr = htonl (INADDR_ANY);
else
dest_address.sin_addr.s_addr = inet_addr (addr_str.c_str ());
if (dest_address.sin_addr.s_addr == INADDR_NONE) {
errno = EINVAL;
if (addr.generic.sa_family != AF_INET) {
// Shouldn't happen
return -1;
}
dest_address = addr.ipv4;
// we will check only first byte of IP
// and if it from 224 to 239, then it can
// represent multicast IP.
......@@ -110,7 +103,7 @@ int zmq::udp_address_t::resolve (const char *name_, bool bind_)
bind_address = dest_address;
else {
bind_address.sin_family = AF_INET;
bind_address.sin_port = htons (port);
bind_address.sin_port = dest_address.sin_port;
bind_address.sin_addr.s_addr = htonl (INADDR_ANY);
}
......
......@@ -89,14 +89,12 @@ static void test_resolve_ipv4_bind ()
static void test_resolve_ipv4_bind_any ()
{
// Wildcard port not supported
test_resolve ("*:*", NULL, 0, "0.0.0.0");
test_resolve ("*:*", "0.0.0.0", 0, "0.0.0.0");
}
static void test_resolve_ipv4_bind_anyport ()
{
// Wildcard port not supported
test_resolve ("127.0.0.1:*", NULL, 0, "127.0.0.1");
test_resolve ("127.0.0.1:*", "127.0.0.1", 0, "127.0.0.1");
}
static void test_resolve_ipv4_bind_any_port ()
......@@ -115,6 +113,11 @@ static void test_resolve_ipv4_connect_anyport ()
test_resolve ("127.0.0.1:*", NULL);
}
static void test_resolve_ipv4_connect_port0 ()
{
test_resolve ("127.0.0.1:0", "127.0.0.1", 0);
}
static void test_resolve_ipv4_bind_mcast ()
{
test_resolve ("239.0.0.1:1234", "239.0.0.1", 1234, "0.0.0.0", true);
......@@ -149,6 +152,7 @@ int main (void)
RUN_TEST (test_resolve_ipv4_bind_any_port);
RUN_TEST (test_resolve_ipv4_connect_any);
RUN_TEST (test_resolve_ipv4_connect_anyport);
RUN_TEST (test_resolve_ipv4_connect_port0);
RUN_TEST (test_resolve_ipv4_bind_mcast);
RUN_TEST (test_resolve_ipv4_connect_mcast);
RUN_TEST (test_resolve_ipv6_simple);
......
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