static void zyre_node_recv_beacon (zyre_node_t *self) { // Get IP address and beacon of peer char *ipaddress = zstr_recv (self->beacon); zframe_t *frame = zframe_recv (self->beacon); if (ipaddress == NULL) return; // Interrupted // Ignore anything that isn't a valid beacon beacon_t beacon; memset (&beacon, 0, sizeof (beacon_t)); if (zframe_size (frame) == sizeof (beacon_t)) memcpy (&beacon, zframe_data (frame), zframe_size (frame)); zframe_destroy (&frame); if (beacon.version != BEACON_VERSION) return; // Garbage beacon, ignore it zuuid_t *uuid = zuuid_new (); zuuid_set (uuid, beacon.uuid); if (beacon.port) { char endpoint [100]; const char *iface = zsys_interface (); if (zsys_ipv6 () && iface && !streq (iface, "") && !streq (iface, "*")) sprintf (endpoint, "tcp://%s%%%s:%d", ipaddress, iface, ntohs (beacon.port)); else sprintf (endpoint, "tcp://%s:%d", ipaddress, ntohs (beacon.port)); zyre_peer_t *peer = zyre_node_require_peer (self, uuid, endpoint); zyre_peer_refresh (peer, self->evasive_timeout, self->expired_timeout); } else { // Zero port means peer is going away; remove it if // we had any knowledge of it already zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup ( self->peers, zuuid_str (uuid)); if (peer) zyre_node_remove_peer (self, peer); } zuuid_destroy (&uuid); zstr_free (&ipaddress); }
JNIEXPORT jint JNICALL Java_org_zeromq_czmq_Zsys__1_1ipv6 (JNIEnv *env, jclass c) { jint ipv6_ = (jint) zsys_ipv6 (); return ipv6_; }
int zyre_peer_connect (zyre_peer_t *self, zuuid_t *from, const char *endpoint, uint64_t expired_timeout) { assert (self); assert (!self->connected); // Create new outgoing socket (drop any messages in transit) self->mailbox = zsock_new (ZMQ_DEALER); if (!self->mailbox) return -1; // Null when we're shutting down // Set our own identity on the socket so that receiving node // knows who each message came from. Note that we cannot use // the UUID directly as the identity since it may contain a // zero byte at the start, which libzmq does not like for // historical and arguably bogus reasons that it nonetheless // enforces. byte routing_id [ZUUID_LEN + 1] = { 1 }; memcpy (routing_id + 1, zuuid_data (from), ZUUID_LEN); int rc = zmq_setsockopt (zsock_resolve (self->mailbox), ZMQ_IDENTITY, routing_id, ZUUID_LEN + 1); assert (rc == 0); // Set a high-water mark that allows for reasonable activity zsock_set_sndhwm (self->mailbox, expired_timeout * 100); // Send messages immediately or return EAGAIN zsock_set_sndtimeo (self->mailbox, 0); // If the peer is a link-local IPv6 address but the interface is not set, // use ZSYS_INTERFACE_ADDRESS if provided zrex_t *rex = zrex_new (NULL); char endpoint_iface [NI_MAXHOST] = {0}; if (zsys_ipv6 () && zsys_interface () && strlen(zsys_interface ()) && !streq (zsys_interface (), "*") && zrex_eq (rex, endpoint, "^tcp://(fe80[^%]+)(:\\d+)$")) { const char *hostname, *port; zrex_fetch (rex, &hostname, &port, NULL); strcat (endpoint_iface, "tcp://"); strcat (endpoint_iface, hostname); strcat (endpoint_iface, "%"); strcat (endpoint_iface, zsys_interface ()); strcat (endpoint_iface, port); } else strcat (endpoint_iface, endpoint); zrex_destroy (&rex); // Connect through to peer node rc = zsock_connect (self->mailbox, "%s", endpoint_iface); if (rc != 0) { zsys_debug ("(%s) cannot connect to endpoint=%s", self->origin, endpoint_iface); zsock_destroy (&self->mailbox); return -1; } if (self->verbose) zsys_info ("(%s) connect to peer: endpoint=%s", self->origin, endpoint_iface); self->endpoint = strdup (endpoint_iface); self->connected = true; self->ready = false; return 0; }
/// // Return use of IPv6 for zsock instances. int QmlZsysAttached::ipv6 () { return zsys_ipv6 (); };
void zyre_node_actor (zsock_t *pipe, void *args) { // Create node instance to pass around zyre_node_t *self = zyre_node_new (pipe, args); if (!self) // Interrupted return; // Signal actor successfully initialized zsock_signal (self->pipe, 0); // Loop until the agent is terminated one way or another int64_t reap_at = zclock_mono () + REAP_INTERVAL; while (!self->terminated) { // Start beacon as soon as we can if (self->beacon && self->port <= 0) { // Our hostname is provided by zbeacon zsock_send(self->beacon, "si", "CONFIGURE", self->beacon_port); char *hostname = zstr_recv(self->beacon); // Is UDP broadcast interface available? if (!streq(hostname, "")) { if (zsys_ipv6()) self->port = zsock_bind(self->inbox, "tcp://%s%%%s:*", zsys_ipv6_address(), zsys_interface()); else self->port = zsock_bind(self->inbox, "tcp://%s:*", hostname); if (self->port > 0) { assert(!self->endpoint); // If caller set this, we'd be using gossip if (streq(zsys_interface(), "*")) { char *hostname = zsys_hostname(); self->endpoint = zsys_sprintf("tcp://%s:%d", hostname, self->port); zstr_free(&hostname); } else { self->endpoint = strdup(zsock_endpoint(self->inbox)); } // Set broadcast/listen beacon beacon_t beacon; beacon.protocol[0] = 'Z'; beacon.protocol[1] = 'R'; beacon.protocol[2] = 'E'; beacon.version = BEACON_VERSION; beacon.port = htons(self->port); zuuid_export(self->uuid, beacon.uuid); zsock_send(self->beacon, "sbi", "PUBLISH", (byte *)&beacon, sizeof(beacon_t), self->interval); zsock_send(self->beacon, "sb", "SUBSCRIBE", (byte *) "ZRE", 3); zpoller_add(self->poller, self->beacon); // Start polling on inbox zpoller_add(self->poller, self->inbox); } } zstr_free(&hostname); } int timeout = (int) (reap_at - zclock_mono ()); if (timeout > REAP_INTERVAL) timeout = REAP_INTERVAL; else if (timeout < 0) timeout = 0; zsock_t *which = (zsock_t *) zpoller_wait (self->poller, timeout); if (which == self->pipe) zyre_node_recv_api (self); else if (which == self->inbox) zyre_node_recv_peer (self); else if (self->beacon && (void *) which == self->beacon) zyre_node_recv_beacon (self); else if (self->gossip && (zactor_t *) which == self->gossip) zyre_node_recv_gossip (self); else if (zpoller_terminated (self->poller)) break; // Interrupted, check before expired else if (zpoller_expired (self->poller)) { if (zclock_mono () >= reap_at) { void *item; reap_at = zclock_mono () + REAP_INTERVAL; // Ping all peers and reap any expired ones for (item = zhash_first (self->peers); item != NULL; item = zhash_next (self->peers)) zyre_node_ping_peer (zhash_cursor (self->peers), item, self); } } } zyre_node_destroy (&self); }
/// // Return use of IPv6 for zsock instances. int QZsys::ipv6 () { int rv = zsys_ipv6 (); return rv; }