static void s_self_switch (self_t *self, zsock_t *input, zsock_t *output) { // We use the low-level libzmq API for best performance void *zmq_input = zsock_resolve (input); void *zmq_output = zsock_resolve (output); void *zmq_capture = self->capture? zsock_resolve (self->capture): NULL; zmq_msg_t msg; zmq_msg_init (&msg); if (zmq_recvmsg (zmq_input, &msg, 0) == -1) return; // Nothing to do, probably interrupted while (true) { int send_flags = zsocket_rcvmore (zmq_input)? ZMQ_SNDMORE: 0; if (zmq_capture) { zmq_msg_t dup; zmq_msg_init (&dup); zmq_msg_copy (&dup, &msg); if (zmq_sendmsg (zmq_capture, &dup, send_flags) == -1) zmq_msg_close (&dup); } if (zmq_sendmsg (zmq_output, &msg, send_flags) == -1) { zmq_msg_close (&msg); break; } if (zmq_recvmsg (zmq_input, &msg, ZMQ_DONTWAIT) == -1) break; // Presumably EAGAIN } }
int main (void) { zctx_t *ctx = zctx_new (); void *server = zsocket_new (ctx, ZMQ_XPUB); zsocket_bind (server, "tcp://*:6001"); void *client = zsocket_new (ctx, ZMQ_XSUB); zsocket_connect (client, "tcp://localhost:6001"); byte subscribe [] = { 1 }; zmq_send (client, &subscribe, sizeof (subscribe), 0); zmq_send (client, "MOREMOREMORE", 12, ZMQ_SNDMORE); zmq_send (client, "LAST", 4, 0); // First message is subscription, 1 byte zframe_t *frame = zframe_recv (server); assert (zframe_size (frame) == 1); assert (zsocket_rcvmore (server) == 0); zframe_destroy (&frame); // Second message is 12 bytes with MORE frame = zframe_recv (server); assert (zframe_size (frame) == 12); assert (zsocket_rcvmore (server) == 1); zframe_destroy (&frame); // Third message is 4 bytes with no more frame = zframe_recv (server); assert (zframe_size (frame) == 4); assert (zsocket_rcvmore (server) == 0); zframe_destroy (&frame); zctx_destroy (&ctx); return 0; }
zmsg_t * zmsg_recv (void *source) { assert (source); zmsg_t *self = zmsg_new (); if (!self) return NULL; void *handle = zsock_resolve (source); while (true) { zframe_t *frame = zframe_recv (handle); if (!frame) { zmsg_destroy (&self); break; // Interrupted or terminated } if (zmsg_append (self, &frame)) { zmsg_destroy (&self); break; } if (!zsocket_rcvmore (handle)) break; // Last message frame } return self; }
static void s_proxy_task (void *args, zctx_t *ctx, void *command_pipe) { // Confirm to API that we've started up zsocket_signal (command_pipe); zproxy_t *self = (zproxy_t *) args; // Capture socket, if not NULL, receives all data void *capture = NULL; // Create poller to work on all three sockets zpoller_t *poller = zpoller_new (self->frontend, self->backend, command_pipe, NULL); bool stopped = false; while (!stopped) { // Wait for activity on any polled socket, and read incoming message void *which = zpoller_wait (poller, -1); zmq_msg_t msg; zmq_msg_init (&msg); int send_flags; // Flags for outgoing message if (which && zmq_recvmsg (which, &msg, 0) != -1) { send_flags = zsocket_rcvmore (which)? ZMQ_SNDMORE: 0; if (which == self->frontend || which == self->backend) { void *output = which == self->frontend? self->backend: self->frontend; // Loop on all waiting messages, since polling adds a // non-trivial cost per message, especially on OS/X while (true) { if (capture) { zmq_msg_t dup; zmq_msg_init (&dup); zmq_msg_copy (&dup, &msg); if (zmq_sendmsg (capture, &dup, send_flags) == -1) zmq_msg_close (&dup); } if (zmq_sendmsg (output, &msg, send_flags) == -1) { zmq_msg_close (&msg); break; } if (zmq_recvmsg (which, &msg, ZMQ_DONTWAIT) == -1) break; // Presumably EAGAIN send_flags = zsocket_rcvmore (which)? ZMQ_SNDMORE: 0; } } else if (which == command_pipe) { char command [10] = { 0 }; assert (zmq_msg_size (&msg) < 10); memcpy (command, zmq_msg_data (&msg), zmq_msg_size (&msg)); // Execute API command if (streq (command, "PAUSE")) { zpoller_destroy (&poller); poller = zpoller_new (command_pipe, NULL); } else if (streq (command, "RESUME")) { zpoller_destroy (&poller); poller = zpoller_new (self->frontend, self->backend, command_pipe, NULL); } else if (streq (command, "CAPTURE")) { // Capture flow is always PUSH-to-PULL capture = zsocket_new (self->ctx, ZMQ_PUSH); char *endpoint = zstr_recv (command_pipe); if (capture) { int rc = zsocket_connect (capture, "%s", endpoint); assert (rc == 0); } zstr_free (&endpoint); } else if (streq (command, "STOP")) stopped = true; else assert (0); // Cannot happen, so die // Signal to caller that we processed the command zsocket_signal (command_pipe); } else assert (0); // Cannot happen, so die } else break; // Interrupted } zpoller_destroy (&poller); }
static int read_zmq_message_and_forward(zloop_t *loop, zsock_t *sock, void *callback_data) { int i = 0; zmq_msg_t message_parts[4]; publisher_state_t *state = (publisher_state_t*)callback_data; void *socket = zsock_resolve(sock); // read the message parts, possibly including the message meta info while (!zsys_interrupted) { // printf("[D] receiving part %d\n", i+1); if (i>3) { zmq_msg_t dummy_msg; zmq_msg_init(&dummy_msg); zmq_recvmsg(socket, &dummy_msg, 0); zmq_msg_close(&dummy_msg); } else { zmq_msg_init(&message_parts[i]); zmq_recvmsg(socket, &message_parts[i], 0); } if (!zsocket_rcvmore(socket)) break; i++; } if (i<2) { if (!zsys_interrupted) { fprintf(stderr, "[E] received only %d message parts\n", i); } goto cleanup; } else if (i>3) { fprintf(stderr, "[E] received more than 4 message parts\n"); goto cleanup; } zmq_msg_t *body = &message_parts[2]; msg_meta_t meta = META_INFO_EMPTY; if (i==3) zmq_msg_extract_meta_info(&message_parts[3], &meta); // const char *prefix = socket == state->compressor_output ? "EXTERNAL MESSAGE" : "INTERNAL MESSAGE"; // my_zmq_msg_fprint(&message_parts[0], 3, prefix, stdout); // dump_meta_info(prefix, &meta); if (meta.created_ms) msg_meta.created_ms = meta.created_ms; else msg_meta.created_ms = global_time; size_t msg_bytes = zmq_msg_size(body); if (socket == state->compressor_output) { decompressed_messages_count++; decompressed_messages_bytes += msg_bytes; if (msg_bytes > decompressed_messages_max_bytes) decompressed_messages_max_bytes = msg_bytes; } else { received_messages_count++; received_messages_bytes += msg_bytes; if (msg_bytes > received_messages_max_bytes) received_messages_max_bytes = msg_bytes; } msg_meta.compression_method = meta.compression_method; if (meta.compression_method) { // decompress publish_on_zmq_transport(&message_parts[0], state->compressor_input, &msg_meta, 0); } else { // forward to comsumer msg_meta.sequence_number++; if (debug) { my_zmq_msg_fprint(&message_parts[0], 3, "[D]", stdout); dump_meta_info("[D]", &msg_meta); } char *pub_spec = NULL; bool is_heartbeat = zmq_msg_size(&message_parts[0]) == 9 && strncmp("heartbeat", zmq_msg_data(&message_parts[0]), 9) == 0; if (is_heartbeat) { if (debug) printf("[D] received heartbeat message from device %u\n", msg_meta.device_number); pub_spec = strndup(zmq_msg_data(&message_parts[1]), zmq_msg_size(&message_parts[1])); } device_tracker_calculate_gap(tracker, &msg_meta, pub_spec); if (!is_heartbeat) publish_on_zmq_transport(&message_parts[0], state->publisher, &msg_meta, ZMQ_DONTWAIT); } cleanup: for (;i>=0;i--) { zmq_msg_close(&message_parts[i]); } return 0; }
int zsockopt_test (bool verbose) { printf (" * zsockopt: "); // @selftest zctx_t *ctx = zctx_new (); assert (ctx); void *zocket; #if (ZMQ_VERSION_MAJOR == 2) # if defined (ZMQ_HWM) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_hwm (zocket, 1); assert (zsocket_hwm (zocket) == 1); zsocket_hwm (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SWAP) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_swap (zocket, 1); assert (zsocket_swap (zocket) == 1); zsocket_swap (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_AFFINITY) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_affinity (zocket, 1); assert (zsocket_affinity (zocket) == 1); zsocket_affinity (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_IDENTITY) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_identity (zocket, "test"); char *identity = zsocket_identity (zocket); assert (identity); free (identity); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RATE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rate (zocket, 1); assert (zsocket_rate (zocket) == 1); zsocket_rate (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECOVERY_IVL) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_recovery_ivl (zocket, 1); assert (zsocket_recovery_ivl (zocket) == 1); zsocket_recovery_ivl (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECOVERY_IVL_MSEC) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_recovery_ivl_msec (zocket, 1); assert (zsocket_recovery_ivl_msec (zocket) == 1); zsocket_recovery_ivl_msec (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_MCAST_LOOP) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_mcast_loop (zocket, 1); assert (zsocket_mcast_loop (zocket) == 1); zsocket_mcast_loop (zocket); zsocket_destroy (ctx, zocket); # endif # if (ZMQ_VERSION_MINOR == 2) # if defined (ZMQ_RCVTIMEO) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rcvtimeo (zocket, 1); assert (zsocket_rcvtimeo (zocket) == 1); zsocket_rcvtimeo (zocket); zsocket_destroy (ctx, zocket); # endif # endif # if (ZMQ_VERSION_MINOR == 2) # if defined (ZMQ_SNDTIMEO) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_sndtimeo (zocket, 1); assert (zsocket_sndtimeo (zocket) == 1); zsocket_sndtimeo (zocket); zsocket_destroy (ctx, zocket); # endif # endif # if defined (ZMQ_SNDBUF) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_sndbuf (zocket, 1); assert (zsocket_sndbuf (zocket) == 1); zsocket_sndbuf (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVBUF) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rcvbuf (zocket, 1); assert (zsocket_rcvbuf (zocket) == 1); zsocket_rcvbuf (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_LINGER) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_linger (zocket, 1); assert (zsocket_linger (zocket) == 1); zsocket_linger (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECONNECT_IVL) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_reconnect_ivl (zocket, 1); assert (zsocket_reconnect_ivl (zocket) == 1); zsocket_reconnect_ivl (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECONNECT_IVL_MAX) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_reconnect_ivl_max (zocket, 1); assert (zsocket_reconnect_ivl_max (zocket) == 1); zsocket_reconnect_ivl_max (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_BACKLOG) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_backlog (zocket, 1); assert (zsocket_backlog (zocket) == 1); zsocket_backlog (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SUBSCRIBE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_subscribe (zocket, "test"); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_UNSUBSCRIBE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_unsubscribe (zocket, "test"); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_TYPE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_type (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVMORE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_rcvmore (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_FD) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_fd (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_EVENTS) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_events (zocket); zsocket_destroy (ctx, zocket); # endif #endif #if (ZMQ_VERSION_MAJOR == 3) # if defined (ZMQ_TYPE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_type (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SNDHWM) zocket = zsocket_new (ctx, ZMQ_PUB); assert (zocket); zsocket_set_sndhwm (zocket, 1); assert (zsocket_sndhwm (zocket) == 1); zsocket_sndhwm (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVHWM) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rcvhwm (zocket, 1); assert (zsocket_rcvhwm (zocket) == 1); zsocket_rcvhwm (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_AFFINITY) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_affinity (zocket, 1); assert (zsocket_affinity (zocket) == 1); zsocket_affinity (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SUBSCRIBE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_subscribe (zocket, "test"); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_UNSUBSCRIBE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_unsubscribe (zocket, "test"); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_IDENTITY) zocket = zsocket_new (ctx, ZMQ_DEALER); assert (zocket); zsocket_set_identity (zocket, "test"); char *identity = zsocket_identity (zocket); assert (identity); free (identity); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RATE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rate (zocket, 1); assert (zsocket_rate (zocket) == 1); zsocket_rate (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECOVERY_IVL) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_recovery_ivl (zocket, 1); assert (zsocket_recovery_ivl (zocket) == 1); zsocket_recovery_ivl (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SNDBUF) zocket = zsocket_new (ctx, ZMQ_PUB); assert (zocket); zsocket_set_sndbuf (zocket, 1); assert (zsocket_sndbuf (zocket) == 1); zsocket_sndbuf (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVBUF) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rcvbuf (zocket, 1); assert (zsocket_rcvbuf (zocket) == 1); zsocket_rcvbuf (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_LINGER) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_linger (zocket, 1); assert (zsocket_linger (zocket) == 1); zsocket_linger (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECONNECT_IVL) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_reconnect_ivl (zocket, 1); assert (zsocket_reconnect_ivl (zocket) == 1); zsocket_reconnect_ivl (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RECONNECT_IVL_MAX) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_reconnect_ivl_max (zocket, 1); assert (zsocket_reconnect_ivl_max (zocket) == 1); zsocket_reconnect_ivl_max (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_BACKLOG) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_backlog (zocket, 1); assert (zsocket_backlog (zocket) == 1); zsocket_backlog (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_MAXMSGSIZE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_maxmsgsize (zocket, 1); assert (zsocket_maxmsgsize (zocket) == 1); zsocket_maxmsgsize (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_MULTICAST_HOPS) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_multicast_hops (zocket, 1); assert (zsocket_multicast_hops (zocket) == 1); zsocket_multicast_hops (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVTIMEO) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_rcvtimeo (zocket, 1); assert (zsocket_rcvtimeo (zocket) == 1); zsocket_rcvtimeo (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_SNDTIMEO) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_sndtimeo (zocket, 1); assert (zsocket_sndtimeo (zocket) == 1); zsocket_sndtimeo (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_IPV4ONLY) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_set_ipv4only (zocket, 1); assert (zsocket_ipv4only (zocket) == 1); zsocket_ipv4only (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_DELAY_ATTACH_ON_CONNECT) zocket = zsocket_new (ctx, ZMQ_PUB); assert (zocket); zsocket_set_delay_attach_on_connect (zocket, 1); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_ROUTER_MANDATORY) zocket = zsocket_new (ctx, ZMQ_ROUTER); assert (zocket); zsocket_set_router_mandatory (zocket, 1); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_ROUTER_RAW) zocket = zsocket_new (ctx, ZMQ_ROUTER); assert (zocket); zsocket_set_router_raw (zocket, 1); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_XPUB_VERBOSE) zocket = zsocket_new (ctx, ZMQ_XPUB); assert (zocket); zsocket_set_xpub_verbose (zocket, 1); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_RCVMORE) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_rcvmore (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_FD) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_fd (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_EVENTS) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); zsocket_events (zocket); zsocket_destroy (ctx, zocket); # endif # if defined (ZMQ_LAST_ENDPOINT) zocket = zsocket_new (ctx, ZMQ_SUB); assert (zocket); char *last_endpoint = zsocket_last_endpoint (zocket); assert (last_endpoint); free (last_endpoint); zsocket_destroy (ctx, zocket); # endif zocket = zsocket_new (ctx, ZMQ_SUB); zsocket_set_hwm (zocket, 1); #endif zctx_destroy (&ctx); // @end printf ("OK\n"); 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); }
zre_msg_t * zre_msg_recv (void *input) { assert (input); zre_msg_t *self = zre_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 | 1)) 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_MSG_HELLO: GET_NUMBER2 (self->sequence); free (self->ipaddress); GET_STRING (self->ipaddress); GET_NUMBER2 (self->mailbox); GET_NUMBER1 (list_size); self->groups = zlist_new (); zlist_autofree (self->groups); while (list_size--) { char *string; GET_STRING (string); zlist_append (self->groups, string); free (string); } GET_NUMBER1 (self->status); GET_NUMBER1 (hash_size); self->headers = zhash_new (); zhash_autofree (self->headers); while (hash_size--) { char *string; GET_STRING (string); char *value = strchr (string, '='); if (value) *value++ = 0; zhash_insert (self->headers, string, value); free (string); } break; case ZRE_MSG_WHISPER: GET_NUMBER2 (self->sequence); // Get next frame, leave current untouched if (!zsocket_rcvmore (input)) goto malformed; self->content = zframe_recv (input); break; case ZRE_MSG_SHOUT: GET_NUMBER2 (self->sequence); free (self->group); GET_STRING (self->group); // Get next frame, leave current untouched if (!zsocket_rcvmore (input)) goto malformed; self->content = zframe_recv (input); break; case ZRE_MSG_JOIN: GET_NUMBER2 (self->sequence); free (self->group); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_LEAVE: GET_NUMBER2 (self->sequence); free (self->group); 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); return self; // Error returns malformed: printf ("E: malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zre_msg_destroy (&self); return (NULL); }