static zyre_peer_t * zyre_node_require_peer (zyre_node_t *self, zuuid_t *uuid, char *address, uint16_t port) { zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, zuuid_str (uuid)); if (!peer) { // Purge any previous peer on same endpoint char endpoint [100]; snprintf (endpoint, 100, "tcp://%s:%hu", address, port); zhash_foreach (self->peers, zyre_node_purge_peer, endpoint); peer = zyre_peer_new (self->ctx, self->peers, uuid); zyre_peer_connect (peer, self->uuid, endpoint); // Handshake discovery by sending HELLO as first message zre_msg_t *msg = zre_msg_new (ZRE_MSG_HELLO); zre_msg_set_ipaddress (msg, self->host); zre_msg_set_mailbox (msg, self->port); zre_msg_set_groups (msg, zhash_keys (self->own_groups)); zre_msg_set_status (msg, self->status); zre_msg_set_headers (msg, zhash_dup (self->headers)); zyre_peer_send (peer, &msg); // Send new peer event to logger, if any zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_ENTER, zyre_peer_endpoint (peer), endpoint); } return peer; }
void zyre_log_test (bool verbose) { printf (" * zyre_log: "); // @selftest zctx_t *ctx = zctx_new (); // Get all incoming log messages void *collector = zsocket_new (ctx, ZMQ_SUB); zsocket_bind (collector, "tcp://127.0.0.1:5555"); zsocket_set_subscribe (collector, ""); // Create a log instance to send log messages zyre_log_t *log = zyre_log_new (ctx, "this is me"); zyre_log_connect (log, "tcp://127.0.0.1:5555"); // Workaround for issue 270; give time for connect to // happen and subscriptions to go to pub socket; 200 // msec should be enough for under valgrind on a slow PC zpoller_t *poller = zpoller_new (collector, NULL); zpoller_wait (poller, 200); // Send some messages zyre_log_info (log, ZRE_LOG_MSG_EVENT_JOIN, NULL, "this is you"); zyre_log_info (log, ZRE_LOG_MSG_EVENT_EXIT, "Pizza time", "this is you"); zyre_log_warning (log, "this is you", "Time flies like an %s", "arrow"); zyre_log_error (log, "this is you", "Fruit flies like a %s", "banana"); int count = 0; while (count < 4) { zre_log_msg_t *msg = zre_log_msg_recv (collector); assert (msg); if (verbose) zre_log_msg_dump (msg); zre_log_msg_destroy (&msg); count++; } zpoller_destroy (&poller); zyre_log_destroy (&log); zctx_destroy (&ctx); // @end printf ("OK\n"); }
static void zyre_node_remove_peer (zyre_node_t *self, zyre_peer_t *peer) { // Tell the calling application the peer has gone zstr_sendm (self->pipe, "EXIT"); zstr_send (self->pipe, zyre_peer_identity (peer)); // Send a log event zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_EXIT, zyre_peer_endpoint (peer), zyre_peer_endpoint (peer)); // Remove peer from any groups we've got it in zhash_foreach (self->peer_groups, zyre_node_delete_peer, peer); // To destroy peer, we remove from peers hash table zhash_delete (self->peers, zyre_peer_identity (peer)); }
static int zyre_node_recv_api (zyre_node_t *self) { // Get the whole message off the pipe in one go zmsg_t *request = zmsg_recv (self->pipe); char *command = zmsg_popstr (request); if (!command) return -1; // Interrupted if (streq (command, "SET")) { char *name = zmsg_popstr (request); char *value = zmsg_popstr (request); zhash_update (self->headers, name, value); zstr_free (&name); zstr_free (&value); } else if (streq (command, "START")) { zyre_node_start (self); zstr_send (self->pipe, "OK"); } else if (streq (command, "STOP")) { zyre_node_stop (self); zstr_send (self->pipe, "OK"); } else if (streq (command, "WHISPER")) { // Get peer to send message to char *identity = zmsg_popstr (request); zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, identity); // Send frame on out to peer's mailbox, drop message // if peer doesn't exist (may have been destroyed) if (peer) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_WHISPER); zre_msg_set_content (msg, request); zyre_peer_send (peer, &msg); request = NULL; } zstr_free (&identity); } else if (streq (command, "SHOUT")) { // Get group to send message to char *name = zmsg_popstr (request); zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->peer_groups, name); if (group) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_SHOUT); zre_msg_set_group (msg, name); zre_msg_set_content (msg, request); zyre_group_send (group, &msg); request = NULL; } zstr_free (&name); } else if (streq (command, "JOIN")) { char *name = zmsg_popstr (request); zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name); if (!group) { // Only send if we're not already in group group = zyre_group_new (name, self->own_groups); zre_msg_t *msg = zre_msg_new (ZRE_MSG_JOIN); zre_msg_set_group (msg, name); // Update status before sending command zre_msg_set_status (msg, ++(self->status)); zhash_foreach (self->peers, zyre_node_send_peer, msg); zre_msg_destroy (&msg); zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_JOIN, NULL, name); } zstr_free (&name); } else if (streq (command, "LEAVE")) { char *name = zmsg_popstr (request); zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name); if (group) { // Only send if we are actually in group zre_msg_t *msg = zre_msg_new (ZRE_MSG_LEAVE); zre_msg_set_group (msg, name); // Update status before sending command zre_msg_set_status (msg, ++(self->status)); zhash_foreach (self->peers, zyre_node_send_peer, msg); zre_msg_destroy (&msg); zhash_delete (self->own_groups, name); zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_LEAVE, NULL, name); } zstr_free (&name); } else if (streq (command, "TERMINATE")) { self->terminated = true; zstr_send (self->pipe, "OK"); } zstr_free (&command); zmsg_destroy (&request); return 0; }
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_routing_id (msg))); if (self->verbose) zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_RECV, zuuid_str (self->uuid), zuuid_str (uuid)); // 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 { char endpoint_node [30]; sprintf(endpoint_node, "tcp://%s:%d", self->host, self->port); // We ignore HELLO, because peer has same host:port as current node if (streq(endpoint_node, zyre_peer_endpoint(peer))) { zre_msg_destroy (&msg); zuuid_destroy (&uuid); return 0; } } } 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, ZFRAME_MORE); zstr_send (self->pipe, zre_msg_ipaddress (msg)); // 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); } // 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 const 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; }