// .split main task // We have a single task that implements the worker side of the // Paranoid Pirate Protocol (PPP). The interesting parts here are // the heartbeating, which lets the worker detect if the queue has // died, and vice versa: static void ppworker_actor(zsock_t *pipe, void *args) { ubx_block_t *b = (ubx_block_t *) args; struct czmq_ppworker_info *inf = (struct czmq_ppworker_info*) b->private_data; zsock_t *worker = s_worker_socket (); // If liveness hits zero, queue is considered disconnected size_t liveness = HEARTBEAT_LIVENESS; size_t interval = INTERVAL_INIT; // Send out heartbeats at regular intervals uint64_t heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL; srandom ((unsigned) time (NULL)); printf("ppworker: actor started.\n"); // send signal on pipe socket to acknowledge initialisation zsock_signal (pipe, 0); while (true) { zmq_pollitem_t items [] = { { zsock_resolve(worker), 0, ZMQ_POLLIN, 0 } }; int rc = zmq_poll (items, 1, HEARTBEAT_INTERVAL * ZMQ_POLL_MSEC); if (rc == -1) break; // Interrupted if (items [0].revents & ZMQ_POLLIN) { // Get message // - 3-part envelope + content -> request // - 1-part HEARTBEAT -> heartbeat zmsg_t *msg = zmsg_recv (worker); if (!msg) break; // Interrupted if (zmsg_size (msg) == 3) { printf ("I: normal reply\n"); byte *buffer; size_t buffer_size = zmsg_encode (msg, &buffer); ubx_type_t* type = ubx_type_get(b->ni, "unsigned char"); ubx_data_t umsg; umsg.data = (void *)buffer; umsg.len = buffer_size; umsg.type = type; __port_write(inf->ports.zmq_in, &umsg); zmsg_send (&msg, worker); liveness = HEARTBEAT_LIVENESS; sleep (1); // Do some heavy work if (zsys_interrupted) break; } else // .split handle heartbeats // When we get a heartbeat message from the queue, it means the // queue was (recently) alive, so we must reset our liveness // indicator: if (zmsg_size (msg) == 1) { zframe_t *frame = zmsg_first (msg); if (memcmp (zframe_data (frame), PPP_HEARTBEAT, 1) == 0) liveness = HEARTBEAT_LIVENESS; else { printf ("E: invalid message\n"); zmsg_dump (msg); } zmsg_destroy (&msg); } else { printf ("E: invalid message\n"); zmsg_dump (msg); } interval = INTERVAL_INIT; } else // .split detecting a dead queue // If the queue hasn't sent us heartbeats in a while, destroy the // socket and reconnect. This is the simplest most brutal way of // discarding any messages we might have sent in the meantime: if (--liveness == 0) { printf ("W: heartbeat failure, can't reach queue\n"); printf ("W: reconnecting in %zd msec...\n", interval); zclock_sleep (interval); if (interval < INTERVAL_MAX) interval *= 2; zsock_destroy(&worker); worker = s_worker_socket (); liveness = HEARTBEAT_LIVENESS; } // Send heartbeat to queue if it's time if (zclock_time () > heartbeat_at) { heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL; printf ("I: worker heartbeat\n"); zframe_t *frame = zframe_new (PPP_HEARTBEAT, 1); zframe_send (&frame, worker, 0); } } }
zmsg_t * zgossip_msg_encode (zgossip_msg_t **self_p) { assert (self_p); assert (*self_p); zgossip_msg_t *self = *self_p; zmsg_t *msg = zmsg_new (); size_t frame_size = 2 + 1; // Signature and message ID switch (self->id) { case ZGOSSIP_MSG_HELLO: // version is a 1-byte integer frame_size += 1; break; case ZGOSSIP_MSG_PUBLISH: // version is a 1-byte integer frame_size += 1; // key is a string with 1-byte length frame_size++; // Size is one octet if (self->key) frame_size += strlen (self->key); // value is a string with 4-byte length frame_size += 4; if (self->value) frame_size += strlen (self->value); // ttl is a 4-byte integer frame_size += 4; break; case ZGOSSIP_MSG_PING: // version is a 1-byte integer frame_size += 1; break; case ZGOSSIP_MSG_PONG: // version is a 1-byte integer frame_size += 1; break; case ZGOSSIP_MSG_INVALID: // version is a 1-byte integer frame_size += 1; break; default: zsys_error ("bad message type '%d', not sent\n", self->id); // No recovery, this is a fatal application error assert (false); } // Now serialize message into the frame zframe_t *frame = zframe_new (NULL, frame_size); self->needle = zframe_data (frame); PUT_NUMBER2 (0xAAA0 | 0); PUT_NUMBER1 (self->id); switch (self->id) { case ZGOSSIP_MSG_HELLO: PUT_NUMBER1 (1); break; case ZGOSSIP_MSG_PUBLISH: PUT_NUMBER1 (1); if (self->key) { PUT_STRING (self->key); } else PUT_NUMBER1 (0); // Empty string if (self->value) { PUT_LONGSTR (self->value); } else PUT_NUMBER4 (0); // Empty string PUT_NUMBER4 (self->ttl); break; case ZGOSSIP_MSG_PING: PUT_NUMBER1 (1); break; case ZGOSSIP_MSG_PONG: PUT_NUMBER1 (1); break; case ZGOSSIP_MSG_INVALID: PUT_NUMBER1 (1); break; } // Now send the data frame if (zmsg_append (msg, &frame)) { zmsg_destroy (&msg); zgossip_msg_destroy (self_p); return NULL; } // Destroy zgossip_msg object zgossip_msg_destroy (self_p); return msg; }
/// // Return address of frame data byte *QmlZframe::data () { return zframe_data (self); };
void zwsdecoder_process_buffer(zwsdecoder_t *self, zframe_t* data) { int i = 0; byte* buffer = zframe_data(data); int buffer_length = zframe_size(data); int bytes_to_read; while (i < buffer_length) { switch (self->state) { case error: return; case begin_payload: self->payload_index = 0; self->payload = zmalloc(sizeof(byte) * (self->payload_length + 4)); // +4 extra bytes in case we have to inflate it // continue to payload case payload: bytes_to_read = self->payload_length - self->payload_index; if (bytes_to_read > (buffer_length - i)) { bytes_to_read = buffer_length - i; } memcpy(self->payload + self->payload_index, buffer + i, bytes_to_read); if (self->is_masked) { for (int j = self->payload_index; j < self->payload_index + bytes_to_read; j++) { self->payload[j] = self->payload[j] ^ self->mask[(j) % 4]; } } self->payload_index += bytes_to_read; i += bytes_to_read; if (self->payload_index < self->payload_length) { self->state = payload; } else { // temp(this, new MessageEventArgs(m_opcode, m_payload, m_more)); self->state = new_message; invoke_new_message(self); } break; default: zwsdecoder_process_byte(self, buffer[i]); i++; break; } } }
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, ZFRAME_MORE); zstr_send (self->pipe, zre_msg_ipaddress (msg)); // 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; }
int main (void) { zctx_t *ctx = zctx_new (); void *frontend = zsocket_new (ctx, ZMQ_ROUTER); void *backend = zsocket_new (ctx, ZMQ_ROUTER); zsocket_bind (frontend, "tcp://*:5555"); // For clients zsocket_bind (backend, "tcp://*:5556"); // For workers // List of available workers zlist_t *workers = zlist_new (); // Send out heartbeats at regular intervals uint64_t heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL; while (true) { zmq_pollitem_t items [] = { { backend, 0, ZMQ_POLLIN, 0 }, { frontend, 0, ZMQ_POLLIN, 0 } }; // Poll frontend only if we have available workers int rc = zmq_poll (items, zlist_size (workers)? 2: 1, HEARTBEAT_INTERVAL * ZMQ_POLL_MSEC); if (rc == -1) break; // Interrupted // Handle worker activity on backend if (items [0].revents & ZMQ_POLLIN) { // Use worker identity for load-balancing zmsg_t *msg = zmsg_recv (backend); if (!msg) break; // Interrupted // Any sign of life from worker means it's ready zframe_t *identity = zmsg_unwrap (msg); worker_t *worker = s_worker_new (identity); s_worker_ready (worker, workers); // Validate control message, or return reply to client if (zmsg_size (msg) == 1) { zframe_t *frame = zmsg_first (msg); if (memcmp (zframe_data (frame), PPP_READY, 1) && memcmp (zframe_data (frame), PPP_HEARTBEAT, 1)) { printf ("E: invalid message from worker"); zmsg_dump (msg); } zmsg_destroy (&msg); } else zmsg_send (&msg, frontend); } if (items [1].revents & ZMQ_POLLIN) { // Now get next client request, route to next worker zmsg_t *msg = zmsg_recv (frontend); if (!msg) break; // Interrupted zmsg_push (msg, s_workers_next (workers)); zmsg_send (&msg, backend); } // .split handle heartbeating // We handle heartbeating after any socket activity. First we send // heartbeats to any idle workers if it's time. Then we purge any // dead workers: if (zclock_time () >= heartbeat_at) { worker_t *worker = (worker_t *) zlist_first (workers); while (worker) { zframe_send (&worker->identity, backend, ZFRAME_REUSE + ZFRAME_MORE); zframe_t *frame = zframe_new (PPP_HEARTBEAT, 1); zframe_send (&frame, backend, 0); worker = (worker_t *) zlist_next (workers); } heartbeat_at = zclock_time () + HEARTBEAT_INTERVAL; } s_workers_purge (workers); } // When we're done, clean up properly while (zlist_size (workers)) { worker_t *worker = (worker_t *) zlist_pop (workers); s_worker_destroy (&worker); } zlist_destroy (&workers); zctx_destroy (&ctx); return 0; }
zre_msg_t * zre_msg_decode (zmsg_t **msg_p, int socket_type) { assert (msg_p); zmsg_t *msg = *msg_p; if (msg == NULL) return NULL; zre_msg_t *self = zre_msg_new (0); // If message came from a router socket, first frame is routing_id if (socket_type == ZMQ_ROUTER) { self->routing_id = zmsg_pop (msg); // If message was not valid, forget about it if (!self->routing_id || !zmsg_next (msg)) { zre_msg_destroy (&self); return (NULL); // Malformed or empty } } // Read and parse command in frame zframe_t *frame = zmsg_pop (msg); if (!frame) goto empty; // Malformed or empty // Get and check protocol signature self->needle = zframe_data (frame); self->ceiling = self->needle + zframe_size (frame); uint16_t signature; GET_NUMBER2 (signature); if (signature != (0xAAA0 | 1)) goto empty; // Invalid signature // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZRE_MSG_HELLO: GET_NUMBER2 (self->sequence); GET_STRING (self->ipaddress); GET_NUMBER2 (self->mailbox); { size_t list_size; GET_NUMBER4 (list_size); self->groups = zlist_new (); zlist_autofree (self->groups); while (list_size--) { char *string; GET_LONGSTR (string); zlist_append (self->groups, string); free (string); } } GET_NUMBER1 (self->status); { size_t hash_size; GET_NUMBER4 (hash_size); self->headers = zhash_new (); zhash_autofree (self->headers); while (hash_size--) { char *key, *value; GET_STRING (key); GET_LONGSTR (value); zhash_insert (self->headers, key, value); free (key); free (value); } } break; case ZRE_MSG_WHISPER: GET_NUMBER2 (self->sequence); // Get zero or more remaining frames, leaving current // frame untouched self->content = zmsg_new (); while (zmsg_size (msg)) zmsg_add (self->content, zmsg_pop (msg)); break; case ZRE_MSG_SHOUT: GET_NUMBER2 (self->sequence); GET_STRING (self->group); // Get zero or more remaining frames, leaving current // frame untouched self->content = zmsg_new (); while (zmsg_size (msg)) zmsg_add (self->content, zmsg_pop (msg)); break; case ZRE_MSG_JOIN: GET_NUMBER2 (self->sequence); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_LEAVE: GET_NUMBER2 (self->sequence); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_PING: GET_NUMBER2 (self->sequence); break; case ZRE_MSG_PING_OK: GET_NUMBER2 (self->sequence); break; default: goto malformed; } // Successful return zframe_destroy (&frame); zmsg_destroy (msg_p); return self; // Error returns malformed: printf ("E: malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zmsg_destroy (msg_p); zre_msg_destroy (&self); return (NULL); }
static void s_broker_worker_msg (broker_t *self, zframe_t *sender, zmsg_t *msg) { assert (zmsg_size (msg) >= 1); // At least, command zframe_t *command = zmsg_pop (msg); char *identity = zframe_strhex (sender); int worker_ready = (zhash_lookup (self->workers, identity) != NULL); free (identity); worker_t *worker = s_worker_require (self, sender); if (zframe_streq (command, MDPW_READY)) { if (worker_ready) // Not first command in session s_worker_delete (worker, 1); else if (zframe_size (sender) >= 4 // Reserved service name && memcmp (zframe_data (sender), "mmi.", 4) == 0) s_worker_delete (worker, 1); else { // Attach worker to service and mark as idle zframe_t *service_frame = zmsg_pop (msg); worker->service = s_service_require (self, service_frame); zlist_append (self->waiting, worker); zlist_append (worker->service->waiting, worker); worker->service->workers++; worker->expiry = zclock_time () + HEARTBEAT_EXPIRY; s_service_dispatch (worker->service); zframe_destroy (&service_frame); zclock_log ("worker created"); } } else if (zframe_streq (command, MDPW_REPORT)) { if (worker_ready) { // Remove & save client return envelope and insert the // protocol header and service name, then rewrap envelope. zframe_t *client = zmsg_unwrap (msg); zmsg_pushstr (msg, worker->service->name); zmsg_pushstr (msg, MDPC_REPORT); zmsg_pushstr (msg, MDPC_CLIENT); zmsg_wrap (msg, client); zmsg_send (&msg, self->socket); } else s_worker_delete (worker, 1); } else if (zframe_streq (command, MDPW_HEARTBEAT)) { if (worker_ready) { if (zlist_size (self->waiting) > 1) { // Move worker to the end of the waiting queue, // so s_broker_purge will only check old worker(s) zlist_remove (self->waiting, worker); zlist_append (self->waiting, worker); } worker->expiry = zclock_time () + HEARTBEAT_EXPIRY; } else s_worker_delete (worker, 1); } else if (zframe_streq (command, MDPW_DISCONNECT)) s_worker_delete (worker, 0); else { zclock_log ("E: invalid input message"); zmsg_dump (msg); } zframe_destroy (&command); zmsg_destroy (&msg); }
static void s_broker_client_msg (broker_t *self, zframe_t *sender, zmsg_t *msg) { assert (zmsg_size (msg) >= 2); // Service name + body zframe_t *service_frame = zmsg_pop (msg); service_t *service = s_service_require (self, service_frame); // If we got a MMI service request, process that internally if (zframe_size (service_frame) >= 4 && memcmp (zframe_data (service_frame), "mmi.", 4) == 0) { char *return_code; if (zframe_streq (service_frame, "mmi.service")) { char *name = zframe_strdup (zmsg_last (msg)); service_t *service = (service_t *) zhash_lookup (self->services, name); return_code = service && service->workers? "200": "404"; free (name); } else // The filter service that can be used to manipulate // the command filter table. if (zframe_streq (service_frame, "mmi.filter") && zmsg_size (msg) == 3) { zframe_t *operation = zmsg_pop (msg); zframe_t *service_frame = zmsg_pop (msg); zframe_t *command_frame = zmsg_pop (msg); char *command_str = zframe_strdup (command_frame); if (zframe_streq (operation, "enable")) { service_t *service = s_service_require (self, service_frame); s_service_enable_command (service, command_str); return_code = "200"; } else if (zframe_streq (operation, "disable")) { service_t *service = s_service_require (self, service_frame); s_service_disable_command (service, command_str); return_code = "200"; } else return_code = "400"; zframe_destroy (&operation); zframe_destroy (&service_frame); zframe_destroy (&command_frame); free (command_str); // Add an empty frame; it will be replaced by the return code. zmsg_pushstr (msg, ""); } else return_code = "501"; zframe_reset (zmsg_last (msg), return_code, strlen (return_code)); // Insert the protocol header and service name, then rewrap envelope. zmsg_push (msg, zframe_dup (service_frame)); zmsg_pushstr (msg, MDPC_REPORT); zmsg_pushstr (msg, MDPC_CLIENT); zmsg_wrap (msg, zframe_dup (sender)); zmsg_send (&msg, self->socket); } else { int enabled = 1; if (zmsg_size (msg) >= 1) { zframe_t *cmd_frame = zmsg_first (msg); char *cmd = zframe_strdup (cmd_frame); enabled = s_service_is_command_enabled (service, cmd); free (cmd); } // Forward the message to the worker. if (enabled) { zmsg_wrap (msg, zframe_dup (sender)); zlist_append (service->requests, msg); s_service_dispatch (service); } // Send a NAK message back to the client. else { zmsg_push (msg, zframe_dup (service_frame)); zmsg_pushstr (msg, MDPC_NAK); zmsg_pushstr (msg, MDPC_CLIENT); zmsg_wrap (msg, zframe_dup (sender)); zmsg_send (&msg, self->socket); } } zframe_destroy (&service_frame); }
void trigger(void *cvoid, zctx_t * context, void * control) { triggerconfig_t * c = (triggerconfig_t*) cvoid; //set up msgpack stuff zclock_log("watch_port started!"); msgpack_zone mempool; msgpack_zone_init(&mempool, 2048); // TODO char * user_id = "17"; // TODO get broker in somehow char * broker = "tcp://au.ninjablocks.com:5773"; mdcli_t * client = mdcli_new(broker, 1); //VERBOSE triggermemory_t trigger_memory; msgpack_object * addins_obj = parse_msgpack(&mempool, c->addins); if(!parse_addins(addins_obj, &trigger_memory)) { //bad message zclock_log("bad trigger definition"); msgpack_object_print(stdout, *addins_obj); send_sync("bad trigger", control); return; } zclock_log("Creating trigger: target %s, rule_id %s, name %s", c->target_worker, c->rule_id, c->trigger_name); dump_trigger(&trigger_memory); triggerfunction trigger_func; if(!(trigger_func = find_trigger(c->channel, c->trigger_name))) { zclock_log("no trigger found for channel %s, trigger %s", c->channel, c->trigger_name); send_sync("no such trigger", control); return; } void * line = zsocket_new(context, ZMQ_SUB); // what line are we on? // this comes in the addins. char * linesocket = to_linesocket(trigger_memory.line_id); zclock_log("trigger is connecting to listen on %s", linesocket); zsocket_connect(line, linesocket); zsockopt_set_unsubscribe(line, ""); zsockopt_set_subscribe(line, "VALUE"); recv_sync("ping", control); send_sync("pong", control); zmq_pollitem_t items [] = { { line, 0, ZMQ_POLLIN, 0 }, { control, 0, ZMQ_POLLIN, 0 } }; while(1) { // listen on control and line zmq_poll (items, 2, -1); if (items[1].revents & ZMQ_POLLIN) { zclock_log("rule %s received message on control pipe", c->rule_id); // control message // really only expecting DESTROY zmsg_t * msg = zmsg_recv(control); char * str = zmsg_popstr(msg); zmsg_destroy(&msg); if (strcmp("Destroy", str) == 0) { zclock_log("rule %s will quit on request", c->rule_id); free(str); send_sync("ok", control); zclock_log("rule %s quitting on request", c->rule_id); break; } else { zclock_log("unexpected command %s for rule %s", str, c->rule_id); free(str); send_sync("ok", control); } } if (items[0].revents & ZMQ_POLLIN) { // serial update zmsg_t * msg = zmsg_recv(line); zframe_t * cmd = zmsg_pop(msg); if(zframe_streq(cmd, "CHANNEL_CHANGE")) { // TODO // must have been dormant to have gotten this char * new_channel = zmsg_popstr(msg); if(strcmp(c->channel, new_channel) == 0) { // oh, happy day! We're relevant again. // reactivate and start looking at reset levels. zclock_log("line %d: changed channel from %s to %s: trigger coming back to life", trigger_memory.line_id, c->channel, new_channel); zsockopt_set_subscribe(line, "VALUE"); zsockopt_set_unsubscribe(line, "CHANNEL_CHANGE"); } free(new_channel); } else if (zframe_streq(cmd, "VALUE")) { zframe_t * vframe = zmsg_pop(msg); int value; memcpy(&value, zframe_data(vframe), sizeof(int)); char * update_channel = zmsg_popstr(msg); if(strcmp(c->channel, update_channel) != 0) { // channel changed, go dormant // this is legit according to my tests at // https://gist.github.com/2042350 zclock_log("line %d: changed channel from %s to %s: trigger going dormant", trigger_memory.line_id, c->channel, update_channel); zsockopt_set_subscribe(line, "CHANNEL_CHANGE"); zsockopt_set_unsubscribe(line, "VALUE"); } else if(trigger_func(&trigger_memory, value)) { send_trigger(client, c->target_worker, c->rule_id, value, user_id); } free(update_channel); } else { // shouldn't ever happen. zclock_log("shouldn't have received command %s\n", zframe_strdup(cmd)); } zmsg_destroy(&msg); zframe_destroy(&cmd); } } msgpack_zone_destroy(&mempool); }
int _thsafe_zmq_client_open_release (smio_t *self, llio_endpoint_t *endpoint, uint32_t opcode) { assert (self); int ret = -1; zmsg_t *send_msg = zmsg_new (); ASSERT_ALLOC(send_msg, err_msg_alloc); DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Calling thsafe_release\n"); /* Message is: * frame 0: RELEASE opcode * frame 1: endpopint struct (FIXME?) */ int zerr = zmsg_addmem (send_msg, &opcode, sizeof (opcode)); ASSERT_TEST(zerr == 0, "Could not add OPEN opcode in message", err_add_opcode); zerr = zmsg_addmem (send_msg, endpoint, sizeof (*endpoint)); ASSERT_TEST(zerr == 0, "Could not add endpoint in message", err_add_endpoint); DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Sending message:\n"); #ifdef LOCAL_MSG_DBG zmsg_print (send_msg); #endif zerr = zmsg_send (&send_msg, self->pipe); ASSERT_TEST(zerr == 0, "Could not send message", err_send_msg); /* Message is: * frame 0: reply code * frame 1: return code */ /* Returns NULL if confirmation was not OK or in case of error. * Returns the original message if the confirmation was OK */ zmsg_t *recv_msg = _thsafe_zmq_client_recv_confirmation (self); ASSERT_TEST(recv_msg != NULL, "Could not receive confirmation code", err_null_raw_data); /* If we are here the message got a OK reply code. * Just return the return code */ zframe_t *reply_frame = zmsg_pop (recv_msg); zframe_destroy (&reply_frame); /* Don't do anything with the reply code */ zframe_t *ret_code_frame = zmsg_pop (recv_msg); if (ret_code_frame == NULL) { DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Interrupted or malformed message\n"); /* Interrupted or malformed message */ goto err_recv_data; } /* Check if the frame has the number of bytes requested. * For now, we consider a success only when the number of * bytes requested is the same as the actually read*/ if (zframe_size (ret_code_frame) != THSAFE_REPLY_SIZE) { DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Frame size is wrong\n"); goto err_recv_data_size; } ret = *(THSAFE_REPLY_TYPE *) zframe_data (ret_code_frame); DBE_DEBUG (DBG_MSG | DBG_LVL_TRACE, "[smio_thsafe_client:zmq] Received return code: %08X\n", ret); err_recv_data_size: zframe_destroy (&ret_code_frame); err_recv_data: err_null_raw_data: zmsg_destroy (&recv_msg); err_send_msg: err_add_endpoint: err_add_opcode: zmsg_destroy (&send_msg); err_msg_alloc: return ret; }
int main (void) { zctx_t *context = zctx_new (); void *frontend = zsocket_new (context, ZMQ_SUB); zsocket_bind (frontend, "ipc://frontend"); void *backend = zsocket_new (context, ZMQ_XPUB); zsocket_bind (backend, "ipc://backend"); // .split main poll loop // We route topic updates from frontend to backend, and // we handle subscriptions by sending whatever we cached, // if anything: while (true) { printf("Polling...\r\n"); zmq_pollitem_t items [] = { { frontend, 0, ZMQ_POLLIN, 0 }, { backend, 0, ZMQ_POLLIN, 0 } }; if (zmq_poll (items, 2, -1) <= 0) break; // Interrupted(-1) or no event signaled (0) printf("Something read...\r\n"); // Any new topic data we cache and then forward if (items [0].revents & ZMQ_POLLIN) { printf("Received... "); char *topic = zstr_recv (frontend); char *current = zstr_recv (frontend); if (!topic) break; printf("%s : %s \r\n", topic, current); zstr_sendm (backend, topic); zstr_send (backend, current); free (topic); } // .split handle subscriptions // When we get a new subscription, we pull data from the cache: if (items [1].revents & ZMQ_POLLIN) { printf("Received new subscription...\r\n"); zframe_t *frame = zframe_recv (backend); if (!frame) break; // Event is one byte 0=unsub or 1=sub, followed by topic byte *event = zframe_data (frame); char *topic = zmalloc (zframe_size (frame)); memcpy (topic, event + 1, zframe_size (frame) - 1); printf ("Topic is %s\n", topic); if (event [0] == 0) { printf ("Unsubscribing topic %s\r\n", topic); zsocket_set_unsubscribe (frontend, topic); } if (event [0] == 1) { printf ("Subscribing topic %s\r\n", topic); zsocket_set_subscribe (frontend, topic); } free(topic); zframe_destroy (&frame); } } zctx_destroy (&context); return 0; }
// This function is used by endpoint to receive message from zloop. int maltcp_ctx_recv_message(void *self, mal_endpoint_t *mal_endpoint, mal_message_t **message) { maltcp_ctx_t *maltcp_ctx = (maltcp_ctx_t *) self; maltcp_endpoint_data_t *endpoint_data = (maltcp_endpoint_data_t *) mal_endpoint_get_endpoint_data(mal_endpoint); int rc = 0; clog_debug(maltcp_logger, "maltcp_ctx_recv_message()\n"); zmsg_t *zmsg = zmsg_recv(endpoint_data->socket); if (zmsg) { size_t frames_count = zmsg_size(zmsg); clog_debug(maltcp_logger, "maltcp_ctx_recv_message: received zmsg (%d frames)\n", frames_count); // The first frame contains the peer URI. zframe_t *from = zmsg_pop(zmsg); char *peer_uri = NULL; if (from != NULL) { int len = zframe_size(from); peer_uri = (char *) malloc(len +1); strncpy(peer_uri, (char *)zframe_data(from), len); peer_uri[len] = '\0'; zframe_destroy(&from); } clog_debug(maltcp_logger, "maltcp_ctx_recv_message: peer_uri = %s\n", peer_uri); // The MAL message is in the second frame. // Now the frame is owned by us. zframe_t *frame = zmsg_pop(zmsg); size_t mal_msg_bytes_length = zframe_size(frame); clog_debug(maltcp_logger, "maltcp_ctx_recv_message: mal_msg_bytes_length=%d\n", mal_msg_bytes_length); // Does not copy the frame bytes in another array. byte *mal_msg_bytes = zframe_data(frame); *message = mal_message_new_void(); // MALTCP always uses the 'malbinary' encoding format for the messages header encoding (another // format may be used at the application layer for the message body). // Note: We could use virtual allocation and initialization functions from encoder // rather than malbinary interface. malbinary_cursor_t cursor; malbinary_cursor_init(&cursor, (char *) mal_msg_bytes, mal_msg_bytes_length, 0); mal_uinteger_t variable_length; // 'maltcp' encoding format of the MAL header if (maltcp_decode_message(maltcp_ctx->maltcp_header, *message, maltcp_ctx->decoder, &cursor, &variable_length) != 0) { clog_error(maltcp_logger, "maltcp_ctx_recv_message, cannot decode message\n"); return -1; } // Note: Currently the message length is always equal to the frame size. assert(mal_msg_bytes_length == (variable_length + FIXED_HEADER_LENGTH)); // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message. // currently the body is always copied in a newly allocated memory. // Destroy must free the tcp frame // mal_message_set_body_owner(*message, frame); // If the From URI field is not completely filled, we have to complete it with // the information from TCP/IP protocol. mal_uri_t *uri_from = mal_message_get_uri_from(*message); if (uri_from == NULL) { mal_message_set_uri_from(*message, peer_uri); mal_message_set_free_uri_from(*message, (1==1)); } else if (strncmp(uri_from, MALTCP_URI, sizeof MALTCP_URI -1) != 0) { if (uri_from[0] == '/') uri_from += 1; mal_uri_t *uri = (mal_uri_t *) malloc(strlen(peer_uri) + strlen(uri_from) +2); strcpy(uri, peer_uri); // Ensures presence of path separator (not added in maltcp_ctx_socket_receive). strcat(uri, "/"); strcat(uri, uri_from); mal_message_set_uri_from(*message, uri); mal_message_set_free_uri_from(*message, (1==1)); free(peer_uri); } else { // The complete URI is registered in the message header, use it. free(peer_uri); } // If the To URI field is not completely filled, we have to complete it. // TODO (AF): The To URI should never be completely filled!! mal_uri_t *uri_to = mal_message_get_uri_to(*message); if ((uri_to == NULL) || (strncmp(uri_to, MALTCP_URI, sizeof MALTCP_URI -1) != 0)) { mal_message_set_uri_to(*message, mal_endpoint_get_uri(endpoint_data->mal_endpoint)); mal_message_set_free_uri_to(*message, (1!=1)); } clog_debug(maltcp_logger, "maltcp_ctx_recv_message: "); if (clog_is_loggable(maltcp_logger, CLOG_DEBUG_LEVEL)) mal_message_print(*message); clog_debug(maltcp_logger, "\n"); // Verify if the message could be delivered and destroy it otherwise. if (endpoint_data->mal_endpoint) { bool message_delivered = false; mal_uri_t *endpoint_uri = mal_endpoint_get_uri(endpoint_data->mal_endpoint); if (strcmp(maltcp_get_service_from_uri(endpoint_uri), maltcp_get_service_from_uri(uri_to)) == 0) message_delivered = true; clog_debug(maltcp_logger, "maltcp_ctx_recv_message: message_delivered=%d\n", message_delivered); if (!message_delivered) { clog_debug(maltcp_logger, "maltcp_ctx_recv_message: destroy MAL message\n", uri_to); mal_message_destroy(message, maltcp_ctx->mal_ctx); } } // TODO (AF) : Normally the frame should be kept to avoid copying the body of the message. // currently the body is always copied in a newly allocated memory. zframe_destroy(&frame); } else { clog_debug(maltcp_logger, "maltcp_ctx_recv_message(): NULL\n"); } return rc; }
/// // Return address of frame data byte * QZframe::data () { byte * rv = zframe_data (self); return rv; }
static void s_socket_event (agent_t *self) { zframe_t *frame; zmq_event_t event; char *description = "Unknown"; char address [1025]; // Copy event data into event struct frame = zframe_recv (self->socket); // Extract id of the event as bitfield memcpy (&(event.event), zframe_data (frame), sizeof (event.event)); // Extract value which is either error code, fd, or reconnect interval memcpy (&(event.value), zframe_data (frame) + sizeof (event.event), sizeof (event.value)); zframe_destroy (&frame); // Copy address part frame = zframe_recv (self->socket); memcpy (address, zframe_data (frame), zframe_size (frame)); address [zframe_size (frame)] = 0; // Terminate address string zframe_destroy (&frame); switch (event.event) { case ZMQ_EVENT_ACCEPTED: description = "Accepted"; break; case ZMQ_EVENT_ACCEPT_FAILED: description = "Accept failed"; break; case ZMQ_EVENT_BIND_FAILED: description = "Bind failed"; break; case ZMQ_EVENT_CLOSED: description = "Closed"; break; case ZMQ_EVENT_CLOSE_FAILED: description = "Close failed"; break; case ZMQ_EVENT_DISCONNECTED: description = "Disconnected"; break; case ZMQ_EVENT_CONNECTED: description = "Connected"; break; case ZMQ_EVENT_CONNECT_DELAYED: description = "Connect delayed"; break; case ZMQ_EVENT_CONNECT_RETRIED: description = "Connect retried"; break; case ZMQ_EVENT_LISTENING: description = "Listening"; break; case ZMQ_EVENT_MONITOR_STOPPED: description = "Monitor stopped"; break; default: if (self->verbose) printf ("Unknown socket monitor event: %d", event.event); break; } if (self->verbose) printf ("I: zmonitor: %s - %s\n", description, address); zmsg_t *msg = zmsg_new(); zmsg_addstrf (msg, "%d", (int) event.event); zmsg_addstrf (msg, "%d", (int) event.value); zmsg_addstrf (msg, "%s", address); zmsg_addstrf (msg, "%s", description); zmsg_send (&msg, self->pipe); }
int main(int argc, char* argv[]) { zctx_t* ctx; void* cloudfe; void* cloudbe; int i; void* localfe; void* localbe; int capacity = 0; zlist_t* workers; if (argc < 2) { fprintf(stderr, "syntax: peering me {you} ...\n"); return 1; } self = argv[1]; fprintf(stdout, "I: preparing broker at %s ...\n", self); srand((unsigned int)time(NULL)); ctx = zctx_new(); cloudfe = zsocket_new(ctx, ZMQ_ROUTER); zsockopt_set_identity(cloudfe, self); zsocket_bind(cloudfe, "ipc://%s-cloud.ipc", self); cloudbe = zsocket_new(ctx, ZMQ_ROUTER); zsockopt_set_identity(cloudbe, self); for (i = 2; i < argc; ++i) { char* peer = argv[i]; fprintf(stdout, "I: connecting to cloud frontend at '%s'\n", peer); zsocket_connect(cloudbe, "ipc://%s-cloud.ipc", peer); } localfe = zsocket_new(ctx, ZMQ_ROUTER); zsocket_bind(localfe, "ipc://%s-localfe.ipc", self); localbe = zsocket_new(ctx, ZMQ_ROUTER); zsocket_bind(localbe, "ipc://%s-localbe.ipc", self); fprintf(stdout, "Press Enter when all brokers are started: "); getchar(); for (i = 0; i < NUM_WORKERS; ++i) zthread_new(worker_routine, NULL); for (i = 0; i < NUM_CLIENTS; ++i) zthread_new(client_routine, NULL); workers = zlist_new(); while (1) { zmsg_t* msg; zmq_pollitem_t backends[] = { {localbe, 0, ZMQ_POLLIN, 0}, {cloudbe, 0, ZMQ_POLLIN, 0}, }; int r = zmq_poll(backends, 2, capacity ? 1000 * ZMQ_POLL_MSEC : -1); if (-1 == r) break; msg = NULL; if (backends[0].revents & ZMQ_POLLIN) { zframe_t* identity; zframe_t* frame; msg = zmsg_recv(localbe); if (!msg) break; identity = zmsg_unwrap(msg); zlist_append(workers, identity); ++capacity; frame = zmsg_first(msg); if (0 == memcmp(zframe_data(frame), WORKER_READY, 1)) zmsg_destroy(&msg); } else if (backends[1].revents & ZMQ_POLLIN) { zframe_t* identity; msg = zmsg_recv(cloudbe); if (!msg) break; identity = zmsg_unwrap(msg); zframe_destroy(&identity); } for (i = 2; msg && i < argc; ++i) { char* data = (char*)zframe_data(zmsg_first(msg)); size_t size = zframe_size(zmsg_first(msg)); if (size == strlen(argv[i]) && 0 == memcmp(data, argv[i], size)) zmsg_send(&msg, cloudfe); } if (msg) zmsg_send(&msg, localfe); while (capacity) { int reroutable = 0; zmq_pollitem_t frontends[] = { {localfe, 0, ZMQ_POLLIN, 0}, {cloudfe, 0, ZMQ_POLLIN, 0}, }; r = zmq_poll(frontends, 2, 0); assert(r >= 0); if (frontends[1].revents & ZMQ_POLLIN) { msg = zmsg_recv(cloudfe); reroutable = 0; } else if (frontends[0].revents & ZMQ_POLLIN) { msg = zmsg_recv(localfe); reroutable = 1; } else break; if (0 != reroutable && argc > 2 && 0 == rand() % 5) { int random_peer = rand() % (argc - 2) + 2; zmsg_pushmem(msg, argv[random_peer], strlen(argv[random_peer])); zmsg_send(&msg, cloudbe); } else { zframe_t* frame = (zframe_t*)zlist_pop(workers); zmsg_wrap(msg, frame); zmsg_send(&msg, localbe); --capacity; } } } while (zlist_size(workers)) { zframe_t* frame = (zframe_t*)zlist_pop(workers); zframe_destroy(&frame); } zlist_destroy(&workers); zctx_destroy(&ctx); return 0; }
int main (void) { zctx_t *ctx = zctx_new (); void *frontend = zsocket_new (ctx, ZMQ_ROUTER); void *backend = zsocket_new (ctx, ZMQ_ROUTER); zsocket_bind (frontend, "ipc://frontend.ipc"); zsocket_bind (backend, "ipc://backend.ipc"); int client_nbr; for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++) zthread_new (client_task, NULL); int worker_nbr; for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++) zthread_new (worker_task, NULL); // Queue of available workers zlist_t *workers = zlist_new (); // Here is the main loop for the load-balancer. It works the same way // as the previous example, but is a lot shorter because CZMQ gives // us an API that does more with fewer calls: while (true) { zmq_pollitem_t items [] = { { backend, 0, ZMQ_POLLIN, 0 }, { frontend, 0, ZMQ_POLLIN, 0 } }; // Poll frontend only if we have available workers int rc = zmq_poll (items, zlist_size (workers)? 2: 1, -1); if (rc == -1) break; // Interrupted // Handle worker activity on backend if (items [0].revents & ZMQ_POLLIN) { // Use worker identity for load-balancing zmsg_t *msg = zmsg_recv (backend); if (!msg) break; // Interrupted zframe_t *identity = zmsg_unwrap (msg); zlist_append (workers, identity); // Forward message to client if it's not a READY zframe_t *frame = zmsg_first (msg); if (memcmp (zframe_data (frame), WORKER_READY, 1) == 0) zmsg_destroy (&msg); else zmsg_send (&msg, frontend); } if (items [1].revents & ZMQ_POLLIN) { // Get client request, route to first available worker zmsg_t *msg = zmsg_recv (frontend); if (msg) { zmsg_wrap (msg, (zframe_t *) zlist_pop (workers)); zmsg_send (&msg, backend); } } } // When we're done, clean up properly while (zlist_size (workers)) { zframe_t *frame = (zframe_t *) zlist_pop (workers); zframe_destroy (&frame); } zlist_destroy (&workers); zctx_destroy (&ctx); return 0; }
zre_log_msg_t * zre_log_msg_recv (void *input) { assert (input); zre_log_msg_t *self = zre_log_msg_new (0); zframe_t *frame = NULL; size_t string_size; size_t list_size; size_t hash_size; // Read valid message frame from socket; we loop over any // garbage data we might receive from badly-connected peers while (true) { // If we're reading from a ROUTER socket, get address if (zsocket_type (input) == ZMQ_ROUTER) { zframe_destroy (&self->address); self->address = zframe_recv (input); if (!self->address) goto empty; // Interrupted if (!zsocket_rcvmore (input)) goto malformed; } // Read and parse command in frame frame = zframe_recv (input); if (!frame) goto empty; // Interrupted // Get and check protocol signature self->needle = zframe_data (frame); self->ceiling = self->needle + zframe_size (frame); uint16_t signature; GET_NUMBER2 (signature); if (signature == (0xAAA0 | 2)) break; // Valid signature // Protocol assertion, drop message while (zsocket_rcvmore (input)) { zframe_destroy (&frame); frame = zframe_recv (input); } zframe_destroy (&frame); } // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZRE_LOG_MSG_LOG: GET_NUMBER1 (self->level); GET_NUMBER1 (self->event); GET_NUMBER2 (self->node); GET_NUMBER2 (self->peer); GET_NUMBER8 (self->time); free (self->data); GET_STRING (self->data); break; default: goto malformed; } // Successful return zframe_destroy (&frame); return self; // Error returns malformed: printf ("E: malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zre_log_msg_destroy (&self); return (NULL); }
int main (void) { zctx_t *context = zctx_new (); void *frontend = zsocket_new (context, ZMQ_SUB); zsocket_bind (frontend, "tcp://*:5557"); void *backend = zsocket_new (context, ZMQ_XPUB); zsocket_bind (backend, "tcp://*:5558"); // Subscribe to every single topic from publisher zsocket_set_subscribe (frontend, ""); // Store last instance of each topic in a cache zhash_t *cache = zhash_new (); // .split main poll loop // We route topic updates from frontend to backend, and // we handle subscriptions by sending whatever we cached, // if anything: while (true) { zmq_pollitem_t items [] = { { frontend, 0, ZMQ_POLLIN, 0 }, { backend, 0, ZMQ_POLLIN, 0 } }; if (zmq_poll (items, 2, 1000 * ZMQ_POLL_MSEC) == -1) break; // Interrupted // Any new topic data we cache and then forward if (items [0].revents & ZMQ_POLLIN) { char *topic = zstr_recv (frontend); char *current = zstr_recv (frontend); if (!topic) break; char *previous = zhash_lookup (cache, topic); if (previous) { zhash_delete (cache, topic); free (previous); } zhash_insert (cache, topic, current); zstr_sendm (backend, topic); zstr_send (backend, current); free (topic); } // .split handle subscriptions // When we get a new subscription we pull data from the cache: if (items [1].revents & ZMQ_POLLIN) { zframe_t *frame = zframe_recv (backend); if (!frame) break; // Event is one byte 0=unsub or 1=sub, followed by topic byte *event = zframe_data (frame); if (event [0] == 1) { char *topic = zmalloc (zframe_size (frame)); memcpy (topic, event + 1, zframe_size (frame) - 1); printf ("Sending cached topic %s\n", topic); char *previous = zhash_lookup (cache, topic); if (previous) { zstr_sendm (backend, topic); zstr_send (backend, previous); } free (topic); } zframe_destroy (&frame); } } zctx_destroy (&context); zhash_destroy (&cache); return 0; }
int zre_log_msg_send (zre_log_msg_t **self_p, void *output) { assert (output); assert (self_p); assert (*self_p); // Calculate size of serialized data zre_log_msg_t *self = *self_p; size_t frame_size = 2 + 1; // Signature and message ID switch (self->id) { case ZRE_LOG_MSG_LOG: // level is a 1-byte integer frame_size += 1; // event is a 1-byte integer frame_size += 1; // node is a 2-byte integer frame_size += 2; // peer is a 2-byte integer frame_size += 2; // time is a 8-byte integer frame_size += 8; // data is a string with 1-byte length frame_size++; // Size is one octet if (self->data) frame_size += strlen (self->data); break; default: printf ("E: bad message type '%d', not sent\n", self->id); // No recovery, this is a fatal application error assert (false); } // Now serialize message into the frame zframe_t *frame = zframe_new (NULL, frame_size); self->needle = zframe_data (frame); size_t string_size; int frame_flags = 0; PUT_NUMBER2 (0xAAA0 | 2); PUT_NUMBER1 (self->id); switch (self->id) { case ZRE_LOG_MSG_LOG: PUT_NUMBER1 (self->level); PUT_NUMBER1 (self->event); PUT_NUMBER2 (self->node); PUT_NUMBER2 (self->peer); PUT_NUMBER8 (self->time); if (self->data) { PUT_STRING (self->data); } else PUT_NUMBER1 (0); // Empty string break; } // If we're sending to a ROUTER, we send the address first if (zsocket_type (output) == ZMQ_ROUTER) { assert (self->address); if (zframe_send (&self->address, output, ZFRAME_MORE)) { zframe_destroy (&frame); zre_log_msg_destroy (self_p); return -1; } } // Now send the data frame if (zframe_send (&frame, output, frame_flags)) { zframe_destroy (&frame); zre_log_msg_destroy (self_p); return -1; } // Destroy zre_log_msg object zre_log_msg_destroy (self_p); return 0; }
zmsg_t * zre_msg_encode (zre_msg_t *self, int socket_type) { assert (self); zmsg_t *msg = zmsg_new (); // If we're sending to a ROUTER, send the routing_id first if (socket_type == ZMQ_ROUTER) zmsg_prepend (msg, &self->routing_id); size_t frame_size = 2 + 1; // Signature and message ID switch (self->id) { case ZRE_MSG_HELLO: // sequence is a 2-byte integer frame_size += 2; // ipaddress is a string with 1-byte length frame_size++; // Size is one octet if (self->ipaddress) frame_size += strlen (self->ipaddress); // mailbox is a 2-byte integer frame_size += 2; // groups is an array of strings frame_size += 4; // Size is 4 octets if (self->groups) { // Add up size of list contents char *groups = (char *) zlist_first (self->groups); while (groups) { frame_size += 4 + strlen (groups); groups = (char *) zlist_next (self->groups); } } // status is a 1-byte integer frame_size += 1; // headers is an array of key=value strings frame_size += 4; // Size is 4 octets if (self->headers) { self->headers_bytes = 0; // Add up size of dictionary contents zhash_foreach (self->headers, s_headers_count, self); } frame_size += self->headers_bytes; break; case ZRE_MSG_WHISPER: // sequence is a 2-byte integer frame_size += 2; break; case ZRE_MSG_SHOUT: // sequence is a 2-byte integer frame_size += 2; // group is a string with 1-byte length frame_size++; // Size is one octet if (self->group) frame_size += strlen (self->group); break; case ZRE_MSG_JOIN: // sequence is a 2-byte integer frame_size += 2; // group is a string with 1-byte length frame_size++; // Size is one octet if (self->group) frame_size += strlen (self->group); // status is a 1-byte integer frame_size += 1; break; case ZRE_MSG_LEAVE: // sequence is a 2-byte integer frame_size += 2; // group is a string with 1-byte length frame_size++; // Size is one octet if (self->group) frame_size += strlen (self->group); // status is a 1-byte integer frame_size += 1; break; case ZRE_MSG_PING: // sequence is a 2-byte integer frame_size += 2; break; case ZRE_MSG_PING_OK: // sequence is a 2-byte integer frame_size += 2; break; default: printf ("E: bad message type '%d', not sent\n", self->id); // No recovery, this is a fatal application error assert (false); } // Now serialize message into the frame zframe_t *frame = zframe_new (NULL, frame_size); self->needle = zframe_data (frame); PUT_NUMBER2 (0xAAA0 | 1); PUT_NUMBER1 (self->id); switch (self->id) { case ZRE_MSG_HELLO: PUT_NUMBER2 (self->sequence); if (self->ipaddress) { PUT_STRING (self->ipaddress); } else PUT_NUMBER1 (0); // Empty string PUT_NUMBER2 (self->mailbox); if (self->groups) { PUT_NUMBER4 (zlist_size (self->groups)); char *groups = (char *) zlist_first (self->groups); while (groups) { PUT_LONGSTR (groups); groups = (char *) zlist_next (self->groups); } } else PUT_NUMBER4 (0); // Empty string array PUT_NUMBER1 (self->status); if (self->headers) { PUT_NUMBER4 (zhash_size (self->headers)); zhash_foreach (self->headers, s_headers_write, self); } else PUT_NUMBER4 (0); // Empty dictionary break; case ZRE_MSG_WHISPER: PUT_NUMBER2 (self->sequence); break; case ZRE_MSG_SHOUT: PUT_NUMBER2 (self->sequence); if (self->group) { PUT_STRING (self->group); } else PUT_NUMBER1 (0); // Empty string break; case ZRE_MSG_JOIN: PUT_NUMBER2 (self->sequence); if (self->group) { PUT_STRING (self->group); } else PUT_NUMBER1 (0); // Empty string PUT_NUMBER1 (self->status); break; case ZRE_MSG_LEAVE: PUT_NUMBER2 (self->sequence); if (self->group) { PUT_STRING (self->group); } else PUT_NUMBER1 (0); // Empty string PUT_NUMBER1 (self->status); break; case ZRE_MSG_PING: PUT_NUMBER2 (self->sequence); break; case ZRE_MSG_PING_OK: PUT_NUMBER2 (self->sequence); break; } // Now send the data frame if (zmsg_append (msg, &frame)) { zmsg_destroy (&msg); zre_msg_destroy (&self); return NULL; } // Now send the content field if set if (self->id == ZRE_MSG_WHISPER) { zframe_t *content_part = zmsg_pop (self->content); while (content_part) { zmsg_append (msg, &content_part); content_part = zmsg_pop (self->content); } } // Now send the content field if set if (self->id == ZRE_MSG_SHOUT) { zframe_t *content_part = zmsg_pop (self->content); while (content_part) { zmsg_append (msg, &content_part); content_part = zmsg_pop (self->content); } } // Destroy zre_msg object zre_msg_destroy (&self); return msg; }
void web_request(void *sweb, req_store_t * req_store, void *spss, void *sgraph) { zmsg_t *msg = zmsg_recv(sweb); zframe_t *address = zmsg_unwrap(msg); json_t *req_json; json_error_t error; printf("\nbroker:sweb received: %s\n", (const char *)zframe_data(zmsg_first(msg))); const char *data; size_t data_size = zframe_size(zmsg_first(msg)); data = zframe_data(zmsg_first(msg)); req_json = json_loadb(data, data_size, 0, &error); zmsg_destroy(&msg); int32_t requestId = request_store_add(req_store, address, req_json); json_t *clientRequest = json_object_get(req_json, "clientRequest"); json_t *request = json_object_get(clientRequest, "request"); const char *type = json_string_value(json_object_get(request, "type")); if (strcmp(type, "searchRequest") == 0) web_request_searchRequest(requestId, request, spss); else if (strcmp(type, "newNode") == 0) web_request_newNode(requestId, request, sgraph); else if (strcmp(type, "newPosition") == 0) web_request_newPosition(requestId, request, spss); else if (strcmp(type, "newLink") == 0) web_request_newLink(requestId, request, sgraph); else if (strcmp(type, "delLink") == 0) web_request_delLink(requestId, request, sgraph); else if (strcmp(type, "delNode") == 0) web_request_delNode(requestId, request, sgraph); else if (strcmp(type, "newNodeData") == 0) web_request_newNodeData(requestId, request, sgraph); else if (strcmp(type, "newLinkData") == 0) web_request_newLinkData(requestId, request, sgraph); else { //TODO process request //malformed request printf("\ni received a malformed request : %s", type); //delete request zframe_destroy(&address); request_store_delete(req_store, requestId); } }
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); }
void graph_response(void *sgraph, req_store_t * req_store, void *sweb, void *spss) { zmsg_t *msg = zmsg_recv(sgraph); zframe_t *null = zmsg_unwrap(msg); zframe_destroy(&null); json_error_t error; printf("\nbroker:sgraph received: %s\n", (const char *)zframe_data(zmsg_first(msg))); const char *data; size_t data_size = zframe_size(zmsg_first(msg)); data = zframe_data(zmsg_first(msg)); json_t *graph_resp_json = json_loadb(data, data_size, 0, &error); zmsg_destroy(&msg); //identify the request int32_t requestId = json_integer_value(json_object_get(graph_resp_json, "requestId")); req_t *req = request_store_req(req_store, requestId); json_t *response = json_object_get(graph_resp_json, "response"); const char *resp_type = json_string_value(json_object_get(response, "type")); json_t *request = json_object_get(json_object_get(req->request, "clientRequest"), "request"); const char *req_type = json_string_value(json_object_get(request, "type")); if ((strcmp(resp_type, "retrieveResponse") == 0) && (strcmp(req_type, "searchRequest") == 0)) graph_response_retrieveResponse(req, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "newNodeResponse") == 0) && (strcmp(req_type, "newNode") == 0)) graph_response_newNodeResponse(request, response, requestId, spss, req_store); else if ((strcmp(resp_type, "newLinkResponse") == 0) && (strcmp(req_type, "newLink") == 0)) graph_response_newLinkResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "delLinkResponse") == 0) && (strcmp(req_type, "delLink") == 0)) graph_response_delLinkResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "delNode") == 0) && (strcmp(req_type, "delNode") == 0)) graph_response_delNodeResponse(req, request, response, requestId, spss, req_store); else if ((strcmp(resp_type, "newNodeData") == 0) && (strcmp(req_type, "newNodeData") == 0)) graph_response_newNodeDataResponse(req, request, response, requestId, sweb, req_store); else if ((strcmp(resp_type, "newLinkData") == 0) && (strcmp(req_type, "newLinkData") == 0)) graph_response_newLinkDataResponse(req, request, response, requestId, sweb, req_store); json_decref(graph_resp_json); }
zgossip_msg_t * zgossip_msg_decode (zmsg_t **msg_p) { assert (msg_p); zmsg_t *msg = *msg_p; if (msg == NULL) return NULL; zgossip_msg_t *self = zgossip_msg_new (0); // Read and parse command in frame zframe_t *frame = zmsg_pop (msg); if (!frame) goto empty; // Malformed or empty // Get and check protocol signature self->needle = zframe_data (frame); self->ceiling = self->needle + zframe_size (frame); uint16_t signature; GET_NUMBER2 (signature); if (signature != (0xAAA0 | 0)) goto empty; // Invalid signature // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZGOSSIP_MSG_HELLO: GET_NUMBER1 (self->version); if (self->version != 1) goto malformed; break; case ZGOSSIP_MSG_PUBLISH: GET_NUMBER1 (self->version); if (self->version != 1) goto malformed; GET_STRING (self->key); GET_LONGSTR (self->value); GET_NUMBER4 (self->ttl); break; case ZGOSSIP_MSG_PING: GET_NUMBER1 (self->version); if (self->version != 1) goto malformed; break; case ZGOSSIP_MSG_PONG: GET_NUMBER1 (self->version); if (self->version != 1) goto malformed; break; case ZGOSSIP_MSG_INVALID: GET_NUMBER1 (self->version); if (self->version != 1) goto malformed; break; default: goto malformed; } // Successful return zframe_destroy (&frame); zmsg_destroy (msg_p); return self; // Error returns malformed: zsys_error ("malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zmsg_destroy (msg_p); zgossip_msg_destroy (&self); return (NULL); }
static void interface_task (void *args, zctx_t *ctx, void *pipe ) { lsd_handle_t *self = (lsd_handle_t*) args; assert(self); char *peer = NULL; char *group = NULL; zframe_t* msg_frame = NULL; zmq_pollitem_t pollitems [] = { { pipe, 0, ZMQ_POLLIN, 0 }, { zre_node_handle (self->interface), 0, ZMQ_POLLIN, 0 } }; while (!zctx_interrupted) { if (zmq_poll (pollitems, 2, randof (1000) * ZMQ_POLL_MSEC) == -1) { debugLog ("I: Interrupted by user action.\n"); break; // Interrupted } if (pollitems [0].revents & ZMQ_POLLIN) { debugLog ("I: Interrupted by parent.\n"); break; // Any command fom parent means EXIT } // Process an event from interface if (pollitems [1].revents & ZMQ_POLLIN) { zmsg_t *incoming = zre_node_recv (self->interface); if (!incoming) { debugLog ("I: Interrupted before end of read.\n"); break; // Interrupted } char *event = zmsg_popstr (incoming); debugLog("I EVENT == %s", event); if (streq (event, "ENTER")) { peer = zmsg_popstr (incoming); debugLog ("I: ENTER '%s'", peer); if(self->callback) { (*self->callback)(self, LSD_EVENT_ENTER, peer, NULL, NULL, 0, self->class_ptr); } } else if (streq (event, "EXIT")) { peer = zmsg_popstr (incoming); debugLog ("I: EXIT '%s'", peer); if(self->callback) { (*self->callback)(self, LSD_EVENT_EXIT, peer, NULL, NULL, 0, self->class_ptr); } } else if (streq (event, "WHISPER")) { peer = zmsg_popstr (incoming); msg_frame = zmsg_pop (incoming); debugLog ("I: WHISPER '%s' msglen %d", peer, (int)zframe_size(msg_frame)); if(self->callback) { (*self->callback)(self, LSD_EVENT_WHISPER, peer, NULL, (const uint8_t*)zframe_data(msg_frame), zframe_size(msg_frame), self->class_ptr); } } else if (streq (event, "SHOUT")) { peer = zmsg_popstr (incoming); group = zmsg_popstr (incoming); msg_frame = zmsg_pop (incoming); debugLog ("I: SHOUT from '%s' group '%s' msglen %d", peer, group, (int)zframe_size(msg_frame)); if(self->callback) { (*self->callback)(self, LSD_EVENT_SHOUT, peer, group, zframe_data(msg_frame), zframe_size(msg_frame), self->class_ptr); } } else if (streq (event, "DELIVER")) { char *filename = zmsg_popstr (incoming); char *fullname = zmsg_popstr (incoming); debugLog ("I: DELIVER file %s", fullname); if(self->callback) { (*self->callback)(self, LSD_EVENT_DELIVER, NULL, NULL, (const uint8_t*)fullname, strlen(fullname), self->class_ptr); } free (fullname); free (filename); }else if (streq (event, "JOIN")) { peer = zmsg_popstr (incoming); group = zmsg_popstr (incoming); debugLog ("I: JOIN '%s - %s'", peer, group); if(self->callback) { (*self->callback)(self, LSD_EVENT_JOIN, peer, group, NULL, 0, self->class_ptr); } } else if (streq (event, "LEAVE")) { peer = zmsg_popstr (incoming); group = zmsg_popstr (incoming); debugLog ("I: LEAVE '%s - %s'", peer, group); if(self->callback) { (*self->callback)(self, LSD_EVENT_LEAVE, peer, group, NULL, 0, self->class_ptr); } } if(peer) { free(peer); peer = NULL; } if(group) { free(group); group = NULL; } if(msg_frame) { zframe_destroy(&msg_frame); msg_frame = NULL; } free (event); zmsg_destroy (&incoming); } } }
void curve_client_test (bool verbose) { printf (" * curve_client: "); // @selftest // Create temporary directory for test files zsys_dir_create (TESTDIR); // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); zcert_save (server_cert, TESTDIR "/server.cert"); // We'll run the server as a background task, and the // client in this foreground thread. zthread_new (server_task, &verbose); zcert_t *client_cert = zcert_new (); zcert_save_public (client_cert, TESTDIR "/client.cert"); curve_client_t *client = curve_client_new (&client_cert); curve_client_set_metadata (client, "Client", "CURVEZMQ/curve_client"); curve_client_set_metadata (client, "Identity", "E475DA11"); curve_client_set_verbose (client, verbose); curve_client_connect (client, "tcp://127.0.0.1:9005", (byte *)zcert_public_key (server_cert)); curve_client_sendstr (client, "Hello, World"); char *reply = curve_client_recvstr (client); assert (streq (reply, "Hello, World")); free (reply); // Try a multipart message zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "Hello, World"); zmsg_addstr (msg, "Second frame"); curve_client_send (client, &msg); msg = curve_client_recv (client); assert (zmsg_size (msg) == 2); zmsg_destroy (&msg); // Now send messages of increasing size, check they work int count; int size = 0; for (count = 0; count < 18; count++) { if (verbose) printf ("Testing message of size=%d...\n", size); zframe_t *data = zframe_new (NULL, size); int byte_nbr; // Set data to sequence 0...255 repeated for (byte_nbr = 0; byte_nbr < size; byte_nbr++) zframe_data (data)[byte_nbr] = (byte) byte_nbr; msg = zmsg_new (); zmsg_prepend (msg, &data); curve_client_send (client, &msg); msg = curve_client_recv (client); data = zmsg_pop (msg); assert (data); assert (zframe_size (data) == size); for (byte_nbr = 0; byte_nbr < size; byte_nbr++) { assert (zframe_data (data)[byte_nbr] == (byte) byte_nbr); } zframe_destroy (&data); zmsg_destroy (&msg); size = size * 2 + 1; } // Signal end of test curve_client_sendstr (client, "END"); reply = curve_client_recvstr (client); free (reply); zcert_destroy (&server_cert); zcert_destroy (&client_cert); curve_client_destroy (&client); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end // Ensure server thread has exited before we do zclock_sleep (100); printf ("OK\n"); }
void zbeacon_test (bool verbose) { printf (" * zbeacon: "); if (verbose) printf ("\n"); // @selftest // Test 1 - two beacons, one speaking, one listening // Create speaker beacon to broadcast our service zactor_t *speaker = zactor_new (zbeacon, NULL); assert (speaker); if (verbose) zstr_sendx (speaker, "VERBOSE", NULL); zsock_send (speaker, "si", "CONFIGURE", 9999); char *hostname = zstr_recv (speaker); if (!*hostname) { printf ("OK (skipping test, no UDP broadcasting)\n"); zactor_destroy (&speaker); free (hostname); return; } free (hostname); // Create listener beacon on port 9999 to lookup service zactor_t *listener = zactor_new (zbeacon, NULL); assert (listener); if (verbose) zstr_sendx (listener, "VERBOSE", NULL); zsock_send (listener, "si", "CONFIGURE", 9999); hostname = zstr_recv (listener); assert (*hostname); free (hostname); // We will broadcast the magic value 0xCAFE byte announcement [2] = { 0xCA, 0xFE }; zsock_send (speaker, "sbi", "PUBLISH", announcement, 2, 100); // We will listen to anything (empty subscription) zsock_send (listener, "sb", "SUBSCRIBE", "", 0); // Wait for at most 1/2 second if there's no broadcasting zsock_set_rcvtimeo (listener, 500); char *ipaddress = zstr_recv (listener); if (ipaddress) { zframe_t *content = zframe_recv (listener); assert (zframe_size (content) == 2); assert (zframe_data (content) [0] == 0xCA); assert (zframe_data (content) [1] == 0xFE); zframe_destroy (&content); zstr_free (&ipaddress); zstr_sendx (speaker, "SILENCE", NULL); } zactor_destroy (&listener); zactor_destroy (&speaker); // Test subscription filter using a 3-node setup zactor_t *node1 = zactor_new (zbeacon, NULL); assert (node1); zsock_send (node1, "si", "CONFIGURE", 5670); hostname = zstr_recv (node1); assert (*hostname); free (hostname); zactor_t *node2 = zactor_new (zbeacon, NULL); assert (node2); zsock_send (node2, "si", "CONFIGURE", 5670); hostname = zstr_recv (node2); assert (*hostname); free (hostname); zactor_t *node3 = zactor_new (zbeacon, NULL); assert (node3); zsock_send (node3, "si", "CONFIGURE", 5670); hostname = zstr_recv (node3); assert (*hostname); free (hostname); zsock_send (node1, "sbi", "PUBLISH", "NODE/1", 6, 250); zsock_send (node2, "sbi", "PUBLISH", "NODE/2", 6, 250); zsock_send (node3, "sbi", "PUBLISH", "RANDOM", 6, 250); zsock_send (node1, "sb", "SUBSCRIBE", "NODE", 4); // Poll on three API sockets at once zpoller_t *poller = zpoller_new (node1, node2, node3, NULL); assert (poller); int64_t stop_at = zclock_mono () + 1000; while (zclock_mono () < stop_at) { long timeout = (long) (stop_at - zclock_mono ()); if (timeout < 0) timeout = 0; void *which = zpoller_wait (poller, timeout * ZMQ_POLL_MSEC); if (which) { assert (which == node1); char *ipaddress, *received; zstr_recvx (node1, &ipaddress, &received, NULL); assert (streq (received, "NODE/2")); zstr_free (&ipaddress); zstr_free (&received); } } zpoller_destroy (&poller); // Stop listening zstr_sendx (node1, "UNSUBSCRIBE", NULL); // Stop all node broadcasts zstr_sendx (node1, "SILENCE", NULL); zstr_sendx (node2, "SILENCE", NULL); zstr_sendx (node3, "SILENCE", NULL); // Destroy the test nodes zactor_destroy (&node1); zactor_destroy (&node2); zactor_destroy (&node3); // @end printf ("OK\n"); }
static void s_self_handle_sink (self_t *self) { #if defined (ZMQ_EVENT_ALL) #if (ZMQ_VERSION_MAJOR == 4) // First frame is event number and value zframe_t *frame = zframe_recv (self->sink); int event = *(uint16_t *) (zframe_data (frame)); int value = *(uint32_t *) (zframe_data (frame) + 2); // Address is in second message frame char *address = zstr_recv (self->sink); zframe_destroy (&frame); #elif (ZMQ_VERSION_MAJOR == 3 && ZMQ_VERSION_MINOR == 2) // zmq_event_t is passed as-is in the frame zframe_t *frame = zframe_recv (self->sink); zmq_event_t *eptr = (zmq_event_t *) zframe_data (frame); int event = eptr->event; int value = eptr->data.listening.fd; char *address = strdup (eptr->data.listening.addr); zframe_destroy (&frame); #else // We can't plausibly be here with other versions of libzmq assert (false); #endif // Now map event to text equivalent char *name; switch (event) { case ZMQ_EVENT_ACCEPTED: name = "ACCEPTED"; break; case ZMQ_EVENT_ACCEPT_FAILED: name = "ACCEPT_FAILED"; break; case ZMQ_EVENT_BIND_FAILED: name = "BIND_FAILED"; break; case ZMQ_EVENT_CLOSED: name = "CLOSED"; break; case ZMQ_EVENT_CLOSE_FAILED: name = "CLOSE_FAILED"; break; case ZMQ_EVENT_DISCONNECTED: name = "DISCONNECTED"; break; case ZMQ_EVENT_CONNECTED: name = "CONNECTED"; break; case ZMQ_EVENT_CONNECT_DELAYED: name = "CONNECT_DELAYED"; break; case ZMQ_EVENT_CONNECT_RETRIED: name = "CONNECT_RETRIED"; break; case ZMQ_EVENT_LISTENING: name = "LISTENING"; break; #if (ZMQ_VERSION_MAJOR == 4) case ZMQ_EVENT_MONITOR_STOPPED: name = "MONITOR_STOPPED"; break; #endif default: zsys_error ("illegal socket monitor event: %d", event); name = "UNKNOWN"; break; } if (self->verbose) zsys_info ("zmonitor: %s - %s", name, address); zstr_sendfm (self->pipe, "%s", name); zstr_sendfm (self->pipe, "%d", value); zstr_send (self->pipe, address); free (address); #endif }
void zre_msg_dump (zre_msg_t *self) { assert (self); switch (self->id) { case ZRE_MSG_HELLO: puts ("HELLO:"); printf (" sequence=%ld\n", (long) self->sequence); if (self->ipaddress) printf (" ipaddress='%s'\n", self->ipaddress); else printf (" ipaddress=\n"); printf (" mailbox=%ld\n", (long) self->mailbox); printf (" groups={"); if (self->groups) { char *groups = (char *) zlist_first (self->groups); while (groups) { printf (" '%s'", groups); groups = (char *) zlist_next (self->groups); } } printf (" }\n"); printf (" status=%ld\n", (long) self->status); printf (" headers={\n"); if (self->headers) zhash_foreach (self->headers, s_headers_dump, self); printf (" }\n"); break; case ZRE_MSG_WHISPER: puts ("WHISPER:"); printf (" sequence=%ld\n", (long) self->sequence); printf (" content={\n"); if (self->content) { size_t size = zframe_size (self->content); byte *data = zframe_data (self->content); printf (" size=%td\n", zframe_size (self->content)); if (size > 32) size = 32; int content_index; for (content_index = 0; content_index < size; content_index++) { if (content_index && (content_index % 4 == 0)) printf ("-"); printf ("%02X", data [content_index]); } } printf (" }\n"); break; case ZRE_MSG_SHOUT: puts ("SHOUT:"); printf (" sequence=%ld\n", (long) self->sequence); if (self->group) printf (" group='%s'\n", self->group); else printf (" group=\n"); printf (" content={\n"); if (self->content) { size_t size = zframe_size (self->content); byte *data = zframe_data (self->content); printf (" size=%td\n", zframe_size (self->content)); if (size > 32) size = 32; int content_index; for (content_index = 0; content_index < size; content_index++) { if (content_index && (content_index % 4 == 0)) printf ("-"); printf ("%02X", data [content_index]); } } printf (" }\n"); break; case ZRE_MSG_JOIN: puts ("JOIN:"); printf (" sequence=%ld\n", (long) self->sequence); if (self->group) printf (" group='%s'\n", self->group); else printf (" group=\n"); printf (" status=%ld\n", (long) self->status); break; case ZRE_MSG_LEAVE: puts ("LEAVE:"); printf (" sequence=%ld\n", (long) self->sequence); if (self->group) printf (" group='%s'\n", self->group); else printf (" group=\n"); printf (" status=%ld\n", (long) self->status); break; case ZRE_MSG_PING: puts ("PING:"); printf (" sequence=%ld\n", (long) self->sequence); break; case ZRE_MSG_PING_OK: puts ("PING_OK:"); printf (" sequence=%ld\n", (long) self->sequence); break; } }