Support addressing TIPC Port Identity

ZeroMQ currently supports location independent addressing using TIPC
Port Names with tipc://{type,instance}. This commits adds support for
connecting and binding using TIPC Port Identity addresses. To connect
using Port Identities the expected format is tipc://<Z.C.N:Ref>, e.g.
"tipc://<1.2.3:123123>". To bind using TIPC Port Identities the expected
format is "tipc://<*>".
This commit is contained in:
Pontus Sköldström 2018-02-19 17:34:40 +01:00
parent 4c7c9b87bf
commit 78aa9b1983
4 changed files with 93 additions and 10 deletions

View File

@ -41,6 +41,7 @@
zmq::tipc_address_t::tipc_address_t ()
{
memset (&address, 0, sizeof address);
_random = false;
}
zmq::tipc_address_t::tipc_address_t (const sockaddr *sa, socklen_t sa_len)
@ -50,22 +51,42 @@ zmq::tipc_address_t::tipc_address_t (const sockaddr *sa, socklen_t sa_len)
memset (&address, 0, sizeof address);
if (sa->sa_family == AF_TIPC)
memcpy (&address, sa, sa_len);
_random = false;
}
zmq::tipc_address_t::~tipc_address_t ()
{
}
void zmq::tipc_address_t::set_random ()
{
_random = true;
}
bool zmq::tipc_address_t::is_random () const
{
return _random;
}
bool zmq::tipc_address_t::is_service () const
{
if (address.addrtype == TIPC_ADDR_ID)
return false;
return true;
}
int zmq::tipc_address_t::resolve (const char *name)
{
unsigned int type = 0;
unsigned int lower = 0;
unsigned int upper = 0;
unsigned int ref = 0;
unsigned int z = 1, c = 0, n = 0;
char eof;
const char *domain;
const int res = sscanf (name, "{%u,%u,%u}", &type, &lower, &upper);
int res = sscanf (name, "{%u,%u,%u}", &type, &lower, &upper);
if (res == 0)
goto portid;
/* Fetch optional domain suffix. */
if ((domain = strchr (name, '@'))) {
if (sscanf (domain, "@%u.%u.%u%c", &z, &c, &n, &eof) != 3)
@ -93,6 +114,25 @@ nameseq:
address.addr.nameseq.upper = upper;
address.scope = TIPC_ZONE_SCOPE;
return 0;
portid:
res = sscanf (name, "<%u.%u.%u:%u>", &z, &c, &n, &ref);
if (res == 4) {
address.family = AF_TIPC;
address.addrtype = TIPC_ADDR_ID;
address.addr.id.node = tipc_addr (z, c, n);
address.addr.id.ref = ref;
address.scope = 0;
return 0;
} else if (strncmp (name, "<*>", 3) == 0) {
set_random ();
address.family = AF_TIPC;
address.addrtype = TIPC_ADDR_ID;
address.addr.id.node = 0;
address.addr.id.ref = 0;
address.scope = 0;
return 0;
} else
return EINVAL;
}
int zmq::tipc_address_t::to_string (std::string &addr_)
@ -102,11 +142,28 @@ int zmq::tipc_address_t::to_string (std::string &addr_)
return -1;
}
std::stringstream s;
s << "tipc://"
<< "{" << address.addr.nameseq.type;
s << ", " << address.addr.nameseq.lower;
s << ", " << address.addr.nameseq.upper << "}";
addr_ = s.str ();
if (address.addrtype == TIPC_ADDR_NAMESEQ
|| address.addrtype == TIPC_ADDR_NAME) {
s << "tipc://"
<< "{" << address.addr.nameseq.type;
s << ", " << address.addr.nameseq.lower;
s << ", " << address.addr.nameseq.upper << "}";
addr_ = s.str ();
} else if (address.addrtype == TIPC_ADDR_ID) {
s << "tipc://"
<< "<" << tipc_zone (address.addr.id.node);
s << "." << tipc_cluster (address.addr.id.node);
s << "." << tipc_node (address.addr.id.node);
s << ":" << address.addr.id.ref << ">";
addr_ = s.str ();
} else if (is_random ()) {
s << "tipc://"
<< "<" << tipc_zone (address.addr.id.node);
s << "." << tipc_cluster (address.addr.id.node);
s << "." << tipc_node (address.addr.id.node);
s << ":" << address.addr.id.ref << ">";
addr_ = s.str ();
}
return 0;
}

View File

@ -54,10 +54,16 @@ class tipc_address_t
// The opposite to resolve()
int to_string (std::string &addr_);
// Handling different TIPC address types
bool is_service () const;
bool is_random () const;
void set_random ();
const sockaddr *addr () const;
socklen_t addrlen () const;
private:
bool _random;
struct sockaddr_tipc address;
tipc_address_t (const tipc_address_t &);

View File

@ -204,6 +204,11 @@ int zmq::tipc_connecter_t::open ()
{
zmq_assert (s == retired_fd);
// Cannot connect to random tipc addresses
if (addr->resolved.tipc_addr->is_random ()) {
errno = EINVAL;
return -1;
}
// Create the socket.
s = open_socket (AF_TIPC, SOCK_STREAM, 0);
if (s == -1)

View File

@ -137,12 +137,27 @@ int zmq::tipc_listener_t::set_address (const char *addr_)
if (s == -1)
return -1;
// If address was randomly assigned, update address object to reflect the actual address
if (address.is_random ()) {
struct sockaddr_storage ss;
socklen_t sl = sizeof (ss);
int rc = getsockname (s, (sockaddr *) &ss, &sl);
if (rc != 0) {
return rc;
}
tipc_address_t addr ((struct sockaddr *) &ss, sl);
}
address.to_string (endpoint);
// Bind the socket to tipc name.
rc = bind (s, address.addr (), address.addrlen ());
if (rc != 0)
goto error;
// Bind the socket to tipc name
if (address.is_service ()) {
rc = bind (s, address.addr (), address.addrlen ());
if (rc != 0)
goto error;
}
// Listen for incoming connections.
rc = listen (s, options.backlog);