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); }
static int zyre_node_recv_beacon (zyre_node_t *self) { // Get IP address and beacon of peer char *ipaddress = zstr_recv (zbeacon_socket (self->beacon)); zframe_t *frame = zframe_recv (zbeacon_socket (self->beacon)); // Ignore anything that isn't a valid beacon bool is_valid = true; beacon_t beacon; if (zframe_size (frame) == sizeof (beacon_t)) { memcpy (&beacon, zframe_data (frame), zframe_size (frame)); if (beacon.version != BEACON_VERSION) is_valid = false; } else is_valid = false; // Check that the peer, identified by its UUID, exists if (is_valid) { zuuid_t *uuid = zuuid_new (); zuuid_set (uuid, beacon.uuid); if (beacon.port) { char endpoint [30]; sprintf (endpoint, "tcp://%s:%d", ipaddress, ntohs (beacon.port)); zyre_peer_t *peer = zyre_node_require_peer (self, uuid, endpoint); zyre_peer_refresh (peer); } 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); zframe_destroy (&frame); return 0; }
static void zyre_node_recv_gossip (zyre_node_t *self) { // Get IP address and beacon of peer char *command = NULL, *uuidstr, *endpoint; zstr_recvx (self->gossip, &command, &uuidstr, &endpoint, NULL); if (command == NULL) return; // Interrupted // Any replies except DELIVER would signify an internal error; these // messages come from zgossip, not an external source assert (streq (command, "DELIVER")); // Require peer, if it's not us if (strneq (endpoint, self->endpoint)) { zuuid_t *uuid = zuuid_new (); zuuid_set_str (uuid, uuidstr); zyre_node_require_peer (self, uuid, endpoint); zuuid_destroy (&uuid); } zstr_free (&command); zstr_free (&uuidstr); zstr_free (&endpoint); }
static int zyre_node_recv_peer (zyre_node_t *self) { // Router socket tells us the identity of this peer zre_msg_t *msg = zre_msg_recv (self->inbox); if (msg == NULL) return 0; // Interrupted // First frame is sender identity, holding binary UUID zuuid_t *uuid = zuuid_new (); zuuid_set (uuid, zframe_data (zre_msg_address (msg))); // On HELLO we may create the peer if it's unknown // On other commands the peer must already exist zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid)); if (zre_msg_id (msg) == ZRE_MSG_HELLO) { peer = zyre_node_require_peer (self, uuid, zre_msg_ipaddress (msg), zre_msg_mailbox (msg)); assert (peer); zyre_peer_set_ready (peer, true); } // Ignore command if peer isn't ready if (peer == NULL || !zyre_peer_ready (peer)) { zre_msg_destroy (&msg); zuuid_destroy (&uuid); return 0; } if (!zyre_peer_check_message (peer, msg)) { zclock_log ("W: [%s] lost messages from %s", zuuid_str (self->uuid), zuuid_str (uuid)); assert (false); } // Now process each command if (zre_msg_id (msg) == ZRE_MSG_HELLO) { // Tell the caller about the peer zstr_sendm (self->pipe, "ENTER"); zstr_sendm (self->pipe, zuuid_str (uuid)); zframe_t *headers = zhash_pack (zre_msg_headers (msg)); zframe_send (&headers, self->pipe, 0); // Join peer to listed groups char *name = zre_msg_groups_first (msg); while (name) { zyre_node_join_peer_group (self, peer, name); name = zre_msg_groups_next (msg); } // Hello command holds latest status of peer zyre_peer_set_status (peer, zre_msg_status (msg)); // Store peer headers for future reference zyre_peer_set_headers (peer, zre_msg_headers (msg)); // If peer is a ZRE/LOG collector, connect to it char *collector = zre_msg_headers_string (msg, "X-ZRELOG", NULL); if (collector) zyre_log_connect (self->log, collector); } else if (zre_msg_id (msg) == ZRE_MSG_WHISPER) { // Pass up to caller API as WHISPER event zstr_sendm (self->pipe, "WHISPER"); zstr_sendm (self->pipe, zuuid_str (uuid)); zmsg_t *content = zmsg_dup (zre_msg_content (msg)); zmsg_send (&content, self->pipe); } else if (zre_msg_id (msg) == ZRE_MSG_SHOUT) { // Pass up to caller as SHOUT event zstr_sendm (self->pipe, "SHOUT"); zstr_sendm (self->pipe, zuuid_str (uuid)); zstr_sendm (self->pipe, zre_msg_group (msg)); zmsg_t *content = zmsg_dup (zre_msg_content (msg)); zmsg_send (&content, self->pipe); } else if (zre_msg_id (msg) == ZRE_MSG_PING) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_PING_OK); zyre_peer_send (peer, &msg); } else if (zre_msg_id (msg) == ZRE_MSG_JOIN) { zyre_node_join_peer_group (self, peer, zre_msg_group (msg)); assert (zre_msg_status (msg) == zyre_peer_status (peer)); } else if (zre_msg_id (msg) == ZRE_MSG_LEAVE) { zyre_node_leave_peer_group (self, peer, zre_msg_group (msg)); assert (zre_msg_status (msg) == zyre_peer_status (peer)); } zuuid_destroy (&uuid); zre_msg_destroy (&msg); // Activity from peer resets peer timers zyre_peer_refresh (peer); return 0; }
static void zyre_node_recv_peer (zyre_node_t *self) { // Router socket tells us the identity of this peer zre_msg_t *msg = zre_msg_recv (self->inbox); if (!msg) return; // Interrupted // First frame is sender identity byte *peerid_data = zframe_data (zre_msg_routing_id (msg)); size_t peerid_size = zframe_size (zre_msg_routing_id (msg)); // Identity must be [1] followed by 16-byte UUID if (peerid_size != ZUUID_LEN + 1) { zre_msg_destroy (&msg); return; } zuuid_t *uuid = zuuid_new (); zuuid_set (uuid, peerid_data + 1); // On HELLO we may create the peer if it's unknown // On other commands the peer must already exist zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid)); if (zre_msg_id (msg) == ZRE_MSG_HELLO) { if (peer) { // Remove fake peers if (zyre_peer_ready (peer)) { zyre_node_remove_peer (self, peer); assert (!(zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid))); } else if (streq (zyre_peer_endpoint (peer), self->endpoint)) { // We ignore HELLO, if peer has same endpoint as current node zre_msg_destroy (&msg); zuuid_destroy (&uuid); return; } } peer = zyre_node_require_peer (self, uuid, zre_msg_endpoint (msg)); assert (peer); zyre_peer_set_ready (peer, true); } // Ignore command if peer isn't ready if (peer == NULL || !zyre_peer_ready (peer)) { zre_msg_destroy (&msg); zuuid_destroy (&uuid); return; } if (zyre_peer_messages_lost (peer, msg)) { zsys_warning ("(%s) messages lost from %s", self->name, zyre_peer_name (peer)); zyre_node_remove_peer (self, peer); zre_msg_destroy (&msg); zuuid_destroy (&uuid); return; } // Now process each command if (zre_msg_id (msg) == ZRE_MSG_HELLO) { // Store properties from HELLO command into peer zyre_peer_set_name (peer, zre_msg_name (msg)); zyre_peer_set_headers (peer, zre_msg_headers (msg)); // Tell the caller about the peer zstr_sendm (self->outbox, "ENTER"); zstr_sendm (self->outbox, zyre_peer_identity (peer)); zstr_sendm (self->outbox, zyre_peer_name (peer)); zframe_t *headers = zhash_pack (zyre_peer_headers (peer)); zframe_send (&headers, self->outbox, ZFRAME_MORE); zstr_send (self->outbox, zre_msg_endpoint (msg)); if (self->verbose) zsys_info ("(%s) ENTER name=%s endpoint=%s", self->name, zyre_peer_name (peer), zyre_peer_endpoint (peer)); // Join peer to listed groups const char *name = zre_msg_groups_first (msg); while (name) { zyre_node_join_peer_group (self, peer, name); name = zre_msg_groups_next (msg); } // Now take peer's status from HELLO, after joining groups zyre_peer_set_status (peer, zre_msg_status (msg)); } else if (zre_msg_id (msg) == ZRE_MSG_WHISPER) { // Pass up to caller API as WHISPER event zstr_sendm (self->outbox, "WHISPER"); zstr_sendm (self->outbox, zuuid_str (uuid)); zstr_sendm (self->outbox, zyre_peer_name (peer)); zmsg_t *content = zmsg_dup (zre_msg_content (msg)); zmsg_send (&content, self->outbox); } else if (zre_msg_id (msg) == ZRE_MSG_SHOUT) { // Pass up to caller as SHOUT event zstr_sendm (self->outbox, "SHOUT"); zstr_sendm (self->outbox, zuuid_str (uuid)); zstr_sendm (self->outbox, zyre_peer_name (peer)); zstr_sendm (self->outbox, zre_msg_group (msg)); zmsg_t *content = zmsg_dup (zre_msg_content (msg)); zmsg_send (&content, self->outbox); } else if (zre_msg_id (msg) == ZRE_MSG_PING) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_PING_OK); zyre_peer_send (peer, &msg); } else if (zre_msg_id (msg) == ZRE_MSG_JOIN) { zyre_node_join_peer_group (self, peer, zre_msg_group (msg)); assert (zre_msg_status (msg) == zyre_peer_status (peer)); } else if (zre_msg_id (msg) == ZRE_MSG_LEAVE) { zyre_node_leave_peer_group (self, peer, zre_msg_group (msg)); assert (zre_msg_status (msg) == zyre_peer_status (peer)); } zuuid_destroy (&uuid); zre_msg_destroy (&msg); // Activity from peer resets peer timers zyre_peer_refresh (peer, self->evasive_timeout, self->expired_timeout); }