void zstr_test (bool verbose) { printf (" * zstr: "); // @selftest // Create two PAIR sockets and connect over inproc zsock_t *output = zsock_new_pair ("@inproc://zstr.test"); assert (output); zsock_t *input = zsock_new_pair (">inproc://zstr.test"); assert (input); // Send ten strings, five strings with MORE flag and then END int string_nbr; for (string_nbr = 0; string_nbr < 10; string_nbr++) zstr_sendf (output, "this is string %d", string_nbr); zstr_sendx (output, "This", "is", "almost", "the", "very", "END", NULL); // Read and count until we receive END string_nbr = 0; for (string_nbr = 0;; string_nbr++) { char *string = zstr_recv (input); if (streq (string, "END")) { zstr_free (&string); break; } zstr_free (&string); } assert (string_nbr == 15); zsock_destroy (&input); zsock_destroy (&output); // @end printf ("OK\n"); }
void *client_task (void *args) { zctx_t *ctx = zctx_new (); void *subscriber = zsocket_new (ctx, ZMQ_SUB); void *pusher = zsocket_new (ctx, ZMQ_PUSH); zsocket_connect (subscriber, "tcp://localhost:5563"); zsocket_connect (pusher, "tcp://localhost:5564"); int i; for (i = 0; i < 1000000; i++) { zsocket_set_subscribe (subscriber, "A"); zmq_pollitem_t polla [] = { { pusher, 0, ZMQ_POLLOUT, 0 } }; if (zmq_poll (polla, 1, 100) == 1) zstr_send (pusher, "B"); zmq_pollitem_t pollb [] = { { subscriber, 0, ZMQ_POLLIN, 0 } }; if (zmq_poll (pollb, 1, 100) == 1) free (zstr_recv (subscriber)); zsocket_set_unsubscribe (subscriber, "A"); } return NULL; }
static void zyre_node_recv_beacon (zyre_node_t *self) { // Get IP address and beacon of peer char *ipaddress = zstr_recv (self->beacon); zframe_t *frame = zframe_recv (self->beacon); if (ipaddress == NULL) return; // Interrupted // Ignore anything that isn't a valid beacon beacon_t beacon = { { 0 } }; if (zframe_size (frame) == sizeof (beacon_t)) memcpy (&beacon, zframe_data (frame), zframe_size (frame)); zframe_destroy (&frame); if (beacon.version != BEACON_VERSION) return; // Garbage beacon, ignore it zuuid_t *uuid = zuuid_new (); zuuid_set (uuid, beacon.uuid); if (beacon.port) { char endpoint [30]; sprintf (endpoint, "tcp://%s:%d", ipaddress, ntohs (beacon.port)); zyre_peer_t *peer = zyre_node_require_peer (self, uuid, endpoint); zyre_peer_refresh (peer); } else { // Zero port means peer is going away; remove it if // we had any knowledge of it already zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup ( self->peers, zuuid_str (uuid)); if (peer) zyre_node_remove_peer (self, peer); } zuuid_destroy (&uuid); zstr_free (&ipaddress); }
static int timer_main_serial_loop(zloop_t *loop, int timer_id, void *arg) { ticket_printer_t *self = (ticket_printer_t *) arg; if (self->serial_printer == NULL) { s_restart_boca_serial(self, self->boca_serial_port); return 0; } if (!s_heartbeat_boca_serial(self)) { enum BOCA_STATUS status = boca_serial_status(self->serial_printer); if (self->verbose && status != BOCA_UNKNOWN) { zsys_debug("ticket printer: got serial printer status %s.", boca_status_display(status)); } s_handle_boca_status(self, &status, false); } switch (self->state) { case STATE_PRINTING: s_print_tix(self, true); break; case STATE_IDLE: s_print_tix(self, true); break; case STATE_ERROR: zstr_send(self->ticket_store_req, "TICKETUNPRINTED"); char *code = zstr_recv(self->ticket_store_req); if (code != NULL && streq(code, "OK")) { self->tix_counter = 0; } if (code != NULL) zstr_free(&code); free(self->last_token); self->last_token = strdup(""); s_restart_boca_serial(self, self->boca_serial_port); break; case STATE_PAUSE: break; } return 0; }
int zsocket_test (Bool verbose) { printf (" * zsocket: "); // @selftest zctx_t *ctx = zctx_new (); // Create a detached thread, let it run char *interf = "*"; char *domain = "localhost"; int service = 5560; void *writer = zsocket_new (ctx, ZMQ_PUSH); void *reader = zsocket_new (ctx, ZMQ_PULL); assert (streq (zsocket_type_str (writer), "PUSH")); assert (streq (zsocket_type_str (reader), "PULL")); int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service); assert (rc == service); zsocket_connect (reader, "tcp://%s:%d", domain, service); zstr_send (writer, "HELLO"); char *message = zstr_recv (reader); assert (message); assert (streq (message, "HELLO")); free (message); int port = zsocket_bind (writer, "tcp://%s:*", interf); assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO); zsocket_destroy (ctx, writer); zctx_destroy (&ctx); // @end printf ("OK\n"); return 0; }
static void s_agent_task (void *args, zctx_t *ctx, void *pipe) { char *endpoint = zstr_recv (pipe); assert (endpoint); agent_t *self = s_agent_new (ctx, pipe, endpoint); zpoller_t *poller = zpoller_new (self->pipe, self->socket, NULL); while (!self->terminated) { // Poll on API pipe and on monitor socket void *result = zpoller_wait (poller, -1); if (result == NULL) break; // Interrupted else if (result == self->pipe) s_api_command (self); else if (result == self->socket) s_socket_event (self); } zpoller_destroy (&poller); s_agent_destroy (&self); }
void zproxy_v2_test (bool verbose) { printf (" * zproxy (deprecated): "); if (verbose) printf ("\n"); // @selftest zctx_t *ctx = zctx_new (); assert (ctx); void *frontend = zsocket_new (ctx, ZMQ_PULL); assert (frontend); int rc = zsocket_bind (frontend, "inproc://frontend"); assert (rc == 0); void *backend = zsocket_new (ctx, ZMQ_PUSH); assert (backend); rc = zsocket_bind (backend, "inproc://backend"); assert (rc == 0); zproxy_t *proxy = zproxy_new (ctx, frontend, backend); assert (proxy); // Connect application sockets to proxy void *faucet = zsocket_new (ctx, ZMQ_PUSH); assert (faucet); rc = zsocket_connect (faucet, "inproc://frontend"); assert (rc == 0); void *sink = zsocket_new (ctx, ZMQ_PULL); assert (sink); rc = zsocket_connect (sink, "inproc://backend"); assert (rc == 0); // Send some messages and check they arrived zstr_send (faucet, "Hello"); char *string = zstr_recv (sink); assert (streq (string, "Hello")); zstr_free (&string); // Check pause/resume functionality zproxy_pause (proxy); zstr_send (faucet, "World"); zproxy_resume (proxy); string = zstr_recv (sink); assert (streq (string, "World")); zstr_free (&string); // Create capture socket, must be a PULL socket void *capture = zsocket_new (ctx, ZMQ_PULL); assert (capture); rc = zsocket_bind (capture, "inproc://capture"); assert (rc == 0); // Switch on capturing, check that it works zproxy_capture (proxy, "inproc://capture"); zstr_send (faucet, "Hello"); string = zstr_recv (sink); assert (streq (string, "Hello")); zstr_free (&string); string = zstr_recv (capture); assert (streq (string, "Hello")); zstr_free (&string); zproxy_destroy (&proxy); zctx_destroy (&ctx); // @end printf ("OK\n"); }
char * curve_client_recvstr (curve_client_t *self) { assert (self); return zstr_recv (self->data); }
void zyre_node_actor (zsock_t *pipe, void *args) { // Create node instance to pass around zyre_node_t *self = zyre_node_new (pipe, args); if (!self) // Interrupted return; // Signal actor successfully initialized zsock_signal (self->pipe, 0); // Loop until the agent is terminated one way or another int64_t reap_at = zclock_mono () + REAP_INTERVAL; while (!self->terminated) { // Start beacon as soon as we can if (self->beacon && self->port <= 0) { // Our hostname is provided by zbeacon zsock_send(self->beacon, "si", "CONFIGURE", self->beacon_port); char *hostname = zstr_recv(self->beacon); // Is UDP broadcast interface available? if (!streq(hostname, "")) { if (zsys_ipv6()) self->port = zsock_bind(self->inbox, "tcp://%s%%%s:*", zsys_ipv6_address(), zsys_interface()); else self->port = zsock_bind(self->inbox, "tcp://%s:*", hostname); if (self->port > 0) { assert(!self->endpoint); // If caller set this, we'd be using gossip if (streq(zsys_interface(), "*")) { char *hostname = zsys_hostname(); self->endpoint = zsys_sprintf("tcp://%s:%d", hostname, self->port); zstr_free(&hostname); } else { self->endpoint = strdup(zsock_endpoint(self->inbox)); } // Set broadcast/listen beacon beacon_t beacon; beacon.protocol[0] = 'Z'; beacon.protocol[1] = 'R'; beacon.protocol[2] = 'E'; beacon.version = BEACON_VERSION; beacon.port = htons(self->port); zuuid_export(self->uuid, beacon.uuid); zsock_send(self->beacon, "sbi", "PUBLISH", (byte *)&beacon, sizeof(beacon_t), self->interval); zsock_send(self->beacon, "sb", "SUBSCRIBE", (byte *) "ZRE", 3); zpoller_add(self->poller, self->beacon); // Start polling on inbox zpoller_add(self->poller, self->inbox); } } zstr_free(&hostname); } int timeout = (int) (reap_at - zclock_mono ()); if (timeout > REAP_INTERVAL) timeout = REAP_INTERVAL; else if (timeout < 0) timeout = 0; zsock_t *which = (zsock_t *) zpoller_wait (self->poller, timeout); if (which == self->pipe) zyre_node_recv_api (self); else if (which == self->inbox) zyre_node_recv_peer (self); else if (self->beacon && (void *) which == self->beacon) zyre_node_recv_beacon (self); else if (self->gossip && (zactor_t *) which == self->gossip) zyre_node_recv_gossip (self); else if (zpoller_terminated (self->poller)) break; // Interrupted, check before expired else if (zpoller_expired (self->poller)) { if (zclock_mono () >= reap_at) { void *item; reap_at = zclock_mono () + REAP_INTERVAL; // Ping all peers and reap any expired ones for (item = zhash_first (self->peers); item != NULL; item = zhash_next (self->peers)) zyre_node_ping_peer (zhash_cursor (self->peers), item, self); } } } zyre_node_destroy (&self); }
int zsocket_test (bool verbose) { printf (" * zsocket: "); // @selftest zctx_t *ctx = zctx_new (); assert (ctx); // Create a detached thread, let it run char *interf = "*"; char *domain = "localhost"; int service = 5560; void *writer = zsocket_new (ctx, ZMQ_PUSH); assert (writer); void *reader = zsocket_new (ctx, ZMQ_PULL); assert (reader); assert (streq (zsocket_type_str (writer), "PUSH")); assert (streq (zsocket_type_str (reader), "PULL")); int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service); assert (rc == service); rc = zsocket_connect (reader, "tcp://%s:%d", domain, service); assert (rc == 0); zstr_send (writer, "HELLO"); char *message = zstr_recv (reader); assert (message); assert (streq (message, "HELLO")); free (message); // Test binding to ports int port = zsocket_bind (writer, "tcp://%s:*", interf); assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO); assert (zsocket_poll (writer, 100) == false); rc = zsocket_connect (reader, "txp://%s:%d", domain, service); assert (rc == -1); // Test sending frames to socket rc = zsocket_sendmem (writer,"ABC", 3, ZFRAME_MORE); assert (rc == 0); rc = zsocket_sendmem (writer, "DEFG", 4, 0); assert (rc == 0); zframe_t *frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "ABC")); assert (zframe_more (frame)); zframe_destroy (&frame); frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "DEFG")); assert (!zframe_more (frame)); zframe_destroy (&frame); // Test zframe_sendmem_zero_copy rc = zsocket_sendmem_zero_copy (writer, strdup ("ABC"), 3, s_test_free_str_cb, NULL, ZFRAME_MORE); assert (rc == 0); rc = zsocket_sendmem_zero_copy (writer, strdup ("DEFG"), 4, s_test_free_str_cb, NULL, 0); assert (rc == 0); frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "ABC")); assert (zframe_more (frame)); zframe_destroy (&frame); frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "DEFG")); assert (!zframe_more (frame)); zframe_destroy (&frame); zsocket_destroy (ctx, writer); zctx_destroy (&ctx); // @end printf ("OK\n"); return 0; }
void zsocket_test (bool verbose) { printf (" * zsocket (deprecated): "); // @selftest zctx_t *ctx = zctx_new (); assert (ctx); // Create a detached thread, let it run char *interf = "127.0.0.1"; char *domain = "localhost"; int service = 5560; void *writer = zsocket_new (ctx, ZMQ_PUSH); assert (writer); void *reader = zsocket_new (ctx, ZMQ_PULL); assert (reader); assert (streq (zsocket_type_str (writer), "PUSH")); assert (streq (zsocket_type_str (reader), "PULL")); int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service); assert (rc == service); #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (3, 2, 0)) // Check unbind rc = zsocket_unbind (writer, "tcp://%s:%d", interf, service); assert (rc == 0); // In some cases and especially when running under Valgrind, doing // a bind immediately after an unbind causes an EADDRINUSE error. // Even a short sleep allows the OS to release the port for reuse. zclock_sleep (100); // Bind again rc = zsocket_bind (writer, "tcp://%s:%d", interf, service); assert (rc == service); #endif rc = zsocket_connect (reader, "tcp://%s:%d", domain, service); assert (rc == 0); zstr_send (writer, "HELLO"); char *message = zstr_recv (reader); assert (message); assert (streq (message, "HELLO")); free (message); // Test binding to ports int port = zsocket_bind (writer, "tcp://%s:*", interf); assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO); assert (zsocket_poll (writer, 100) == false); // Test error state when connecting to an invalid socket type // ('txp://' instead of 'tcp://', typo intentional) rc = zsocket_connect (reader, "txp://%s:%d", domain, service); assert (rc == -1); // Test sending frames to socket rc = zsocket_sendmem (writer, "ABC", 3, ZFRAME_MORE); assert (rc == 0); rc = zsocket_sendmem (writer, "DEFG", 4, 0); assert (rc == 0); zframe_t *frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "ABC")); assert (zframe_more (frame)); zframe_destroy (&frame); frame = zframe_recv (reader); assert (frame); assert (zframe_streq (frame, "DEFG")); assert (!zframe_more (frame)); zframe_destroy (&frame); rc = zsocket_signal (writer); assert (rc == 0); rc = zsocket_wait (reader); assert (rc == 0); zsocket_destroy (ctx, reader); zsocket_destroy (ctx, writer); zctx_destroy (&ctx); // @end printf ("OK\n"); }
int main(int argc, char *argv[]) { printf("Organizer started.\n"); zsock_t *executer_sock = zsock_new_req("tcp://127.0.0.1:98789"); while (1) { char cmd[50] = {0}; printf("What do you want? "); scanf("%s", &cmd); if (streq(cmd, "teleport")) { char target[50] = {0}, name[50] = {0}; printf("Which? Where? "); scanf("%s %s", &name, &target); /*printf("Name: %s\tTarget: %s\n", name, target);*/ OEMsg oem = OEMSG__INIT; Teleport tpm = TELEPORT__INIT; void *buf; unsigned len; tpm.vm_name = name; tpm.target_ip = target; oem.teleport = &tpm; oem.type = OEMSG__TYPE__TELEPORT; len = oemsg__get_packed_size(&oem); buf = malloc(len); oemsg__pack(&oem, buf); /*printf(buf);*/ zframe_t *frame = zframe_new(buf, len); zframe_send(&frame, executer_sock, 0); /*zstr_send(executer_sock, buf);*/ memset(buf, 0, len * (sizeof buf[0])); free(buf); char *smsg; smsg = zstr_recv(executer_sock); free(smsg); } else if (streq(cmd, "start")) { char name[50] = {0}; printf("Which? "); scanf("%s", &name); OEMsg oem = OEMSG__INIT; Start sm = START__INIT; void *buf; unsigned len; sm.vm_name = name; oem.start = &sm; oem.type = OEMSG__TYPE__START; len = oemsg__get_packed_size(&oem); buf = malloc(len); oemsg__pack(&oem, buf); /*printf(buf);*/ zframe_t *frame = zframe_new(buf, len); zframe_send(&frame, executer_sock, 0); /*zstr_send(executer_sock, buf);*/ memset(buf, 0, len * (sizeof buf[0])); free(buf); char *smsg; smsg = zstr_recv(executer_sock); free(smsg); } else if (streq(cmd, "exit")) { break; } else { break; } } zsock_destroy(&executer_sock); return 0; }
void zpoller_test (bool verbose) { printf (" * zpoller: "); // @selftest // Create a few sockets zsock_t *vent = zsock_new (ZMQ_PUSH); assert (vent); int port_nbr = zsock_bind (vent, "tcp://127.0.0.1:*"); assert (port_nbr != -1); zsock_t *sink = zsock_new (ZMQ_PULL); assert (sink); int rc = zsock_connect (sink, "tcp://127.0.0.1:%d", port_nbr); assert (rc != -1); zsock_t *bowl = zsock_new (ZMQ_PULL); assert (bowl); zsock_t *dish = zsock_new (ZMQ_PULL); assert (dish); // Set up poller zpoller_t *poller = zpoller_new (bowl, dish, NULL); assert (poller); // Add a reader to the existing poller rc = zpoller_add (poller, sink); assert (rc == 0); zstr_send (vent, "Hello, World"); // We expect a message only on the sink zsock_t *which = (zsock_t *) zpoller_wait (poller, -1); assert (which == sink); assert (zpoller_expired (poller) == false); assert (zpoller_terminated (poller) == false); char *message = zstr_recv (which); assert (streq (message, "Hello, World")); zstr_free (&message); // Stop polling reader rc = zpoller_remove (poller, sink); assert (rc == 0); // Removing a non-existent reader shall fail rc = zpoller_remove (poller, sink); assert (rc == -1); assert (errno == EINVAL); // Check we can poll an FD rc = zsock_connect (bowl, "tcp://127.0.0.1:%d", port_nbr); assert (rc != -1); SOCKET fd = zsock_fd (bowl); rc = zpoller_add (poller, (void *) &fd); assert (rc != -1); zstr_send (vent, "Hello again, world"); assert (zpoller_wait (poller, 500) == &fd); // Check zpoller_set_nonstop () zsys_interrupted = 1; zpoller_wait (poller, 0); assert (zpoller_terminated (poller)); zpoller_set_nonstop (poller, true); zpoller_wait (poller, 0); assert (!zpoller_terminated (poller)); zsys_interrupted = 0; zpoller_destroy (&poller); zsock_destroy (&vent); zsock_destroy (&sink); zsock_destroy (&bowl); zsock_destroy (&dish); #ifdef ZMQ_SERVER // Check thread safe sockets zpoller_destroy (&poller); zsock_t *client = zsock_new (ZMQ_CLIENT); assert (client); zsock_t *server = zsock_new (ZMQ_SERVER); assert (server); poller = zpoller_new (client, server, NULL); assert (poller); port_nbr = zsock_bind (server, "tcp://127.0.0.1:*"); assert (port_nbr != -1); rc = zsock_connect (client, "tcp://127.0.0.1:%d", port_nbr); assert (rc != -1); zstr_send (client, "Hello, World"); // We expect a message only on the server which = (zsock_t *) zpoller_wait (poller, -1); assert (which == server); assert (zpoller_expired (poller) == false); assert (zpoller_terminated (poller) == false); message = zstr_recv (which); assert (streq (message, "Hello, World")); zstr_free (&message); zpoller_destroy (&poller); zsock_destroy (&client); zsock_destroy (&server); #endif #if defined (__WINDOWS__) zsys_shutdown(); #endif // @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); assert (address); 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 }
static int zyre_node_start (zyre_node_t *self) { if (self->beacon_port) { // Start beacon discovery // ------------------------------------------------------------------ assert (!self->beacon); self->beacon = zactor_new (zbeacon, NULL); if (!self->beacon) return 1; // Not possible to start beacon if (self->verbose) zsock_send (self->beacon, "s", "VERBOSE"); // Our hostname is provided by zbeacon zsock_send (self->beacon, "si", "CONFIGURE", self->beacon_port); char *hostname = zstr_recv (self->beacon); if (streq (hostname, "")) return -1; // No UDP broadcast interface available self->port = zsock_bind (self->inbox, "tcp://%s:*", hostname); zstr_free (&hostname); assert (self->port > 0); // Die on bad interface or port exhaustion assert (!self->endpoint); // If caller set this, we'd be using gossip self->endpoint = strdup (zsock_endpoint (self->inbox)); // Set broadcast/listen beacon beacon_t beacon; beacon.protocol [0] = 'Z'; beacon.protocol [1] = 'R'; beacon.protocol [2] = 'E'; beacon.version = BEACON_VERSION; beacon.port = htons (self->port); zuuid_export (self->uuid, beacon.uuid); zsock_send (self->beacon, "sbi", "PUBLISH", (byte *) &beacon, sizeof (beacon_t), self->interval); zsock_send (self->beacon, "sb", "SUBSCRIBE", (byte *) "ZRE", 3); zpoller_add (self->poller, self->beacon); } else { // Start gossip discovery // ------------------------------------------------------------------ // If application didn't set an endpoint explicitly, grab ephemeral // port on all available network interfaces. if (!self->endpoint) { const char *iface = zsys_interface (); if (streq (iface, "")) iface = "*"; self->port = zsock_bind (self->inbox, "tcp://%s:*", iface); assert (self->port > 0); // Die on bad interface or port exhaustion char *hostname = zsys_hostname (); self->endpoint = zsys_sprintf ("tcp://%s:%d", hostname, self->port); zstr_free (&hostname); } assert (self->gossip); zstr_sendx (self->gossip, "PUBLISH", zuuid_str (self->uuid), self->endpoint, NULL); // Start polling on zgossip zpoller_add (self->poller, self->gossip); } // Start polling on inbox zpoller_add (self->poller, self->inbox); return 0; }
void zyre_test (bool verbose) { printf (" * zyre: "); if (verbose) printf ("\n"); // @selftest // We'll use inproc gossip discovery so that this works without networking uint64_t version = zyre_version (); assert ((version / 10000) % 100 == ZYRE_VERSION_MAJOR); assert ((version / 100) % 100 == ZYRE_VERSION_MINOR); assert (version % 100 == ZYRE_VERSION_PATCH); // Create two nodes zyre_t *node1 = zyre_new ("node1"); assert (node1); assert (streq (zyre_name (node1), "node1")); zyre_set_header (node1, "X-HELLO", "World"); if (verbose) zyre_set_verbose (node1); // Set inproc endpoint for this node int rc = zyre_set_endpoint (node1, "inproc://zyre-node1"); assert (rc == 0); // Set up gossip network for this node zyre_gossip_bind (node1, "inproc://gossip-hub"); rc = zyre_start (node1); assert (rc == 0); zyre_t *node2 = zyre_new ("node2"); assert (node2); assert (streq (zyre_name (node2), "node2")); if (verbose) zyre_set_verbose (node2); // Set inproc endpoint for this node // First, try to use existing name, it'll fail rc = zyre_set_endpoint (node2, "inproc://zyre-node1"); assert (rc == -1); // Now use available name and confirm that it succeeds rc = zyre_set_endpoint (node2, "inproc://zyre-node2"); assert (rc == 0); // Set up gossip network for this node zyre_gossip_connect (node2, "inproc://gossip-hub"); rc = zyre_start (node2); assert (rc == 0); assert (strneq (zyre_uuid (node1), zyre_uuid (node2))); zyre_join (node1, "GLOBAL"); zyre_join (node2, "GLOBAL"); // Give time for them to interconnect zclock_sleep (250); if (verbose) zyre_dump (node1); zlist_t *peers = zyre_peers (node1); assert (peers); assert (zlist_size (peers) == 1); zlist_destroy (&peers); zyre_join (node1, "node1 group of one"); zyre_join (node2, "node2 group of one"); // Give them time to join their groups zclock_sleep (250); zlist_t *own_groups = zyre_own_groups (node1); assert (own_groups); assert (zlist_size (own_groups) == 2); zlist_destroy (&own_groups); zlist_t *peer_groups = zyre_peer_groups (node1); assert (peer_groups); assert (zlist_size (peer_groups) == 2); zlist_destroy (&peer_groups); char *value = zyre_peer_header_value (node2, zyre_uuid (node1), "X-HELLO"); assert (streq (value, "World")); zstr_free (&value); // One node shouts to GLOBAL zyre_shouts (node1, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT zmsg_t *msg = zyre_recv (node2); assert (msg); char *command = zmsg_popstr (msg); assert (streq (command, "ENTER")); zstr_free (&command); assert (zmsg_size (msg) == 4); char *peerid = zmsg_popstr (msg); char *name = zmsg_popstr (msg); assert (streq (name, "node1")); zstr_free (&name); zframe_t *headers_packed = zmsg_pop (msg); char *address = zmsg_popstr (msg); char *endpoint = zyre_peer_address (node2, peerid); assert (streq (address, endpoint)); zstr_free (&peerid); zstr_free (&endpoint); zstr_free (&address); assert (headers_packed); zhash_t *headers = zhash_unpack (headers_packed); assert (headers); zframe_destroy (&headers_packed); assert (streq ((char *) zhash_lookup (headers, "X-HELLO"), "World")); zhash_destroy (&headers); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); assert (zmsg_size (msg) == 3); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); assert (zmsg_size (msg) == 3); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "SHOUT")); zstr_free (&command); zmsg_destroy (&msg); zyre_stop (node2); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "STOP")); zstr_free (&command); zmsg_destroy (&msg); zyre_stop (node1); zyre_destroy (&node1); zyre_destroy (&node2); printf ("OK\n"); #ifdef ZYRE_BUILD_DRAFT_API if (zsys_has_curve()){ printf (" * zyre-curve: "); if (verbose) printf ("\n"); if (verbose) zsys_debug("----------------TESTING CURVE --------------"); zactor_t *speaker = zactor_new (zbeacon, NULL); assert (speaker); if (verbose) zstr_sendx (speaker, "VERBOSE", NULL); // ensuring we have a broadcast address zsock_send (speaker, "si", "CONFIGURE", 9999); char *hostname = zstr_recv (speaker); if (!*hostname) { printf ("OK (skipping test, no UDP broadcasting)\n"); zactor_destroy (&speaker); freen (hostname); return; } freen (hostname); zactor_destroy (&speaker); // zap setup zactor_t *auth = zactor_new(zauth, NULL); assert (auth); if (verbose) { zstr_sendx(auth, "VERBOSE", NULL); zsock_wait(auth); } zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); zyre_t *node3 = zyre_new ("node3"); zyre_t *node4 = zyre_new ("node4"); assert (node3); assert (node4); zyre_set_verbose (node3); zyre_set_verbose (node4); zyre_set_zap_domain(node3, "TEST"); zyre_set_zap_domain(node4, "TEST"); zsock_set_rcvtimeo(node3->inbox, 10000); zsock_set_rcvtimeo(node4->inbox, 10000); zcert_t *node3_cert = zcert_new (); zcert_t *node4_cert = zcert_new (); assert (node3_cert); assert (node4_cert); zyre_set_zcert(node3, node3_cert); zyre_set_zcert(node4, node4_cert); zyre_set_header(node3, "X-PUBLICKEY", "%s", zcert_public_txt(node3_cert)); zyre_set_header(node4, "X-PUBLICKEY", "%s", zcert_public_txt(node4_cert)); // test beacon if (verbose) zsys_debug ("----------------TESTING BEACON----------------"); rc = zyre_start(node3); assert (rc == 0); rc = zyre_start(node4); assert (rc == 0); zyre_join (node3, "GLOBAL"); zyre_join (node4, "GLOBAL"); zclock_sleep (1500); if (verbose) { zyre_dump (node3); zyre_dump (node4); } zyre_shouts (node3, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "ENTER")); zstr_free (&command); char *peerid = zmsg_popstr (msg); assert (peerid); name = zmsg_popstr (msg); assert (streq (name, "node3")); zmsg_destroy (&msg); msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); zmsg_destroy(&msg); msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "SHOUT")); zstr_free (&command); zmsg_destroy(&msg); zyre_leave(node3, "GLOBAL"); zyre_leave(node4, "GLOBAL"); zstr_free (&name); zstr_free (&peerid); zstr_free (&command); zyre_stop (node3); zyre_stop (node4); // give things a chance to settle... zclock_sleep (250); zyre_destroy(&node3); zyre_destroy(&node4); zcert_destroy(&node3_cert); zcert_destroy(&node4_cert); // test gossip if (verbose) zsys_debug ("----------------TESTING GOSSIP----------------"); zyre_t *node5 = zyre_new ("node5"); zyre_t *node6 = zyre_new ("node6"); assert (node5); assert (node6); if (verbose) { zyre_set_verbose (node5); zyre_set_verbose (node6); } // if it takes more than 10s, something probably went terribly wrong zsock_set_rcvtimeo(node5->inbox, 10000); zsock_set_rcvtimeo(node6->inbox, 10000); zcert_t *node5_cert = zcert_new (); zcert_t *node6_cert = zcert_new (); assert (node5_cert); assert (node6_cert); zyre_set_zcert(node5, node5_cert); zyre_set_zcert(node6, node6_cert); zyre_set_header(node5, "X-PUBLICKEY", "%s", zcert_public_txt(node5_cert)); zyre_set_header(node6, "X-PUBLICKEY", "%s", zcert_public_txt(node6_cert)); const char *gossip_cert = zcert_public_txt (node5_cert); // TODO- need to add zyre_gossip_port functions to get port from gossip bind(?) zyre_gossip_bind(node5, "tcp://127.0.0.1:9001"); zyre_gossip_connect_curve(node6, gossip_cert, "tcp://127.0.0.1:9001"); zyre_start(node5); zsock_wait(node5); zyre_start(node6); zsock_wait(node6); zyre_join (node5, "GLOBAL"); zyre_join (node6, "GLOBAL"); // give things a chance to settle... zclock_sleep (1500); if (verbose) { zyre_dump (node5); zyre_dump (node6); } zyre_shouts (node5, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT msg = zyre_recv (node6); assert (msg); command = zmsg_popstr (msg); zsys_info(command); assert (streq (command, "ENTER")); zstr_free (&command); peerid = zmsg_popstr (msg); assert (peerid); name = zmsg_popstr (msg); zmsg_destroy (&msg); assert (streq (name, "node5")); zstr_free (&name); zyre_leave(node5, "GLOBAL"); zyre_leave(node6, "GLOBAL"); zyre_stop (node5); zyre_stop (node6); // give things a chance to settle... zclock_sleep (250); zstr_free (&peerid); zcert_destroy (&node5_cert); zcert_destroy (&node6_cert); zyre_destroy(&node5); zyre_destroy(&node6); zactor_destroy(&auth); printf ("OK\n"); } #endif }
int main (void) { // Initialize 0MQ context and virtual transport interface zctx_t *ctx = zctx_new (); assert (ctx); // Run request-reply tests { zclock_log ("I: testing request-reply over TCP..."); void *request = zthread_fork (ctx, test_tcp_req, NULL); void *reply = zthread_fork (ctx, test_tcp_rep, NULL); // Send port number to use to each thread zstr_send (request, "32000"); zstr_send (reply, "32000"); sleep (1); zstr_send (request, "END"); free (zstr_recv (request)); zstr_send (reply, "END"); free (zstr_recv (reply)); } // Run request-router tests { zclock_log ("I: testing request-router over TCP..."); void *request = zthread_fork (ctx, test_tcp_req, NULL); void *router = zthread_fork (ctx, test_tcp_router, NULL); // Send port number to use to each thread zstr_send (request, "32001"); zstr_send (router, "32001"); sleep (1); zstr_send (request, "END"); free (zstr_recv (request)); zstr_send (router, "END"); free (zstr_recv (router)); } // Run request-dealer tests { zclock_log ("I: testing request-dealer over TCP..."); void *request = zthread_fork (ctx, test_tcp_req, NULL); void *dealer = zthread_fork (ctx, test_tcp_dealer_srv, NULL); // Send port number to use to each thread zstr_send (request, "32002"); zstr_send (dealer, "32002"); sleep (1); zstr_send (request, "END"); free (zstr_recv (request)); zstr_send (dealer, "END"); free (zstr_recv (dealer)); } // Run dealer-router tests { zclock_log ("I: testing dealer-router over TCP..."); void *dealer = zthread_fork (ctx, test_tcp_dealer_cli, NULL); void *router = zthread_fork (ctx, test_tcp_router, NULL); // Send port number to use to each thread zstr_send (dealer, "32003"); zstr_send (router, "32003"); sleep (1); zstr_send (dealer, "END"); free (zstr_recv (dealer)); zstr_send (router, "END"); free (zstr_recv (router)); } // Run push-pull tests { zclock_log ("I: testing push-pull over TCP..."); void *pull1 = zthread_fork (ctx, test_tcp_pull, NULL); void *pull2 = zthread_fork (ctx, test_tcp_pull, NULL); void *push = zthread_fork (ctx, test_tcp_push, NULL); // Send port number to use to each thread zstr_send (pull1, "32004"); zstr_send (pull2, "32004"); zstr_send (push, "32004"); sleep (1); zstr_send (push, "END"); free (zstr_recv (push)); zstr_send (pull1, "END"); free (zstr_recv (pull1)); zstr_send (pull2, "END"); free (zstr_recv (pull2)); } // Run pub-sub tests { zclock_log ("I: testing pub-sub over TCP..."); void *sub1 = zthread_fork (ctx, test_tcp_sub, NULL); void *sub2 = zthread_fork (ctx, test_tcp_sub, NULL); void *pub = zthread_fork (ctx, test_tcp_pub, NULL); // Send port number to use to each thread zstr_send (sub1, "32005"); zstr_send (sub2, "32005"); zstr_send (pub, "32005"); sleep (1); zstr_send (pub, "END"); free (zstr_recv (pub)); zstr_send (sub1, "END"); free (zstr_recv (sub1)); zstr_send (sub2, "END"); free (zstr_recv (sub2)); } // Run pair tests { zclock_log ("I: testing pair-pair over TCP..."); void *pair1 = zthread_fork (ctx, test_tcp_pair_srv, NULL); void *pair2 = zthread_fork (ctx, test_tcp_pair_cli, NULL); // Send port number to use to each thread zstr_send (pair1, "32006"); zstr_send (pair2, "32006"); sleep (1); zstr_send (pair1, "END"); free (zstr_recv (pair1)); zstr_send (pair2, "END"); free (zstr_recv (pair2)); } zctx_destroy (&ctx); return 0; }
void zsys_test (bool verbose) { printf (" * zsys: "); if (verbose) printf ("\n"); // @selftest zsys_catch_interrupts (); // Check capabilities without using the return value int rc = zsys_has_curve (); if (verbose) { char *hostname = zsys_hostname (); zsys_info ("host name is %s", hostname); free (hostname); zsys_info ("system limit is %zd ZeroMQ sockets", zsys_socket_limit ()); } zsys_set_io_threads (1); zsys_set_max_sockets (0); zsys_set_linger (0); zsys_set_sndhwm (1000); zsys_set_rcvhwm (1000); zsys_set_pipehwm (2500); assert (zsys_pipehwm () == 2500); zsys_set_ipv6 (0); rc = zsys_file_delete ("nosuchfile"); assert (rc == -1); bool rc_bool = zsys_file_exists ("nosuchfile"); assert (rc_bool != true); rc = (int) zsys_file_size ("nosuchfile"); assert (rc == -1); time_t when = zsys_file_modified ("."); assert (when > 0); mode_t mode = zsys_file_mode ("."); assert (S_ISDIR (mode)); assert (mode & S_IRUSR); assert (mode & S_IWUSR); zsys_file_mode_private (); rc = zsys_dir_create ("%s/%s", ".", ".testsys/subdir"); assert (rc == 0); when = zsys_file_modified ("./.testsys/subdir"); assert (when > 0); assert (!zsys_file_stable ("./.testsys/subdir")); rc = zsys_dir_delete ("%s/%s", ".", ".testsys/subdir"); assert (rc == 0); rc = zsys_dir_delete ("%s/%s", ".", ".testsys"); assert (rc == 0); zsys_file_mode_default (); int major, minor, patch; zsys_version (&major, &minor, &patch); assert (major == CZMQ_VERSION_MAJOR); assert (minor == CZMQ_VERSION_MINOR); assert (patch == CZMQ_VERSION_PATCH); char *string = zsys_sprintf ("%s %02x", "Hello", 16); assert (streq (string, "Hello 10")); free (string); char *str64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,."; int num10 = 1234567890; string = zsys_sprintf ("%s%s%s%s%d", str64, str64, str64, str64, num10); assert (strlen (string) == (4 * 64 + 10)); free (string); // Test logging system zsys_set_logident ("czmq_selftest"); zsys_set_logsender ("inproc://logging"); void *logger = zsys_socket (ZMQ_SUB, NULL, 0); assert (logger); rc = zsocket_connect (logger, "inproc://logging"); assert (rc == 0); rc = zmq_setsockopt (logger, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); if (verbose) { zsys_error ("This is an %s message", "error"); zsys_warning ("This is a %s message", "warning"); zsys_notice ("This is a %s message", "notice"); zsys_info ("This is a %s message", "info"); zsys_debug ("This is a %s message", "debug"); zsys_set_logident ("hello, world"); zsys_info ("This is a %s message", "info"); zsys_debug ("This is a %s message", "debug"); // Check that logsender functionality is working char *received = zstr_recv (logger); assert (received); zstr_free (&received); } zsys_close (logger, NULL, 0); // @end printf ("OK\n"); }
static void handler (zsock_t *pipe, void *args) { curl_global_init(CURL_GLOBAL_ALL); CURLM *multi = curl_multi_init (); CURLSH *share = curl_share_init (); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); long verbose = (*(bool *) args) ? 1L : 0L; long timeout = 30; CURLMcode code; SOCKET pipefd = zsock_fd (pipe); struct curl_waitfd waitfd = {pipefd, CURL_WAIT_POLLIN}; // List to hold pending curl handles, in case we are destroy the client // while request are inprogress zlistx_t *pending_handles = zlistx_new (); zlistx_set_destructor (pending_handles, (zlistx_destructor_fn *) curl_destructor); zsock_signal (pipe, 0); bool terminated = false; while (!terminated) { int events = zsock_events (pipe); if ((events & ZMQ_POLLIN) == 0) { code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL); assert (code == CURLM_OK); } events = zsock_events (pipe); if (events & ZMQ_POLLIN) { char* command = zstr_recv (pipe); if (!command) break; // Interrupted // All actors must handle $TERM in this way if (streq (command, "$TERM")) terminated = true; else if (streq (command, "GET")) { char *url; zlistx_t *headers; void *userp; int rc = zsock_recv (pipe, "slp", &url, &headers, &userp); assert (rc == 0); zchunk_t *data = zchunk_new (NULL, 100); assert (data); struct curl_slist *curl_headers = zlistx_to_slist (headers); CURL *curl = curl_easy_init (); zlistx_add_end (pending_handles, curl); http_request *request = (http_request *) zmalloc (sizeof (http_request)); assert (request); request->userp = userp; request->curl = curl; request->data = data; request->headers = curl_headers; curl_easy_setopt (curl, CURLOPT_SHARE, share); curl_easy_setopt (curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose); curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers); curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt (curl, CURLOPT_WRITEDATA, data); curl_easy_setopt (curl, CURLOPT_PRIVATE, request); code = curl_multi_add_handle (multi, curl); assert (code == CURLM_OK); zlistx_destroy (&headers); zstr_free (&url); } else { puts ("E: invalid message to actor"); assert (false); } zstr_free (&command); } int still_running; code = curl_multi_perform (multi, &still_running); assert (code == CURLM_OK); int msgq = 0; struct CURLMsg *msg = curl_multi_info_read(multi, &msgq); while (msg) { if(msg->msg == CURLMSG_DONE) { CURL *curl = msg->easy_handle; http_request *request; curl_easy_getinfo(curl, CURLINFO_PRIVATE, &request); long response_code_long; curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code_long); int response_code = (int)response_code_long; int rc = zsock_send (pipe, "icp", response_code, request->data, request->userp); assert (rc == 0); curl_multi_remove_handle (multi, curl); // Remove curl from the pending handles and delete it void *handle = zlistx_find (pending_handles, curl); assert (handle); rc = zlistx_delete (pending_handles, handle); assert (rc == 0); } msg = curl_multi_info_read(multi, &msgq); } } zlistx_destroy (&pending_handles); curl_share_cleanup (share); curl_multi_cleanup (multi); curl_global_cleanup (); }
int main (int argc, char *argv []) { // Arguments can be either of: // -p primary server, at tcp://localhost:5001 // -b backup server, at tcp://localhost:5002 zctx_t *ctx = zctx_new (); void *statepub = zsocket_new (ctx, ZMQ_PUB); void *statesub = zsocket_new (ctx, ZMQ_SUB); zsockopt_set_subscribe (statesub, ""); void *frontend = zsocket_new (ctx, ZMQ_ROUTER); bstar_t fsm = { 0 }; if (argc == 2 && streq (argv [1], "-p")) { printf ("I: Primary master, waiting for backup (slave)\n"); zsocket_bind (frontend, "tcp://*:5001"); zsocket_bind (statepub, "tcp://*:5003"); zsocket_connect (statesub, "tcp://localhost:5004"); fsm.state = STATE_PRIMARY; } else if (argc == 2 && streq (argv [1], "-b")) { printf ("I: Backup slave, waiting for primary (master)\n"); zsocket_bind (frontend, "tcp://*:5002"); zsocket_bind (statepub, "tcp://*:5004"); zsocket_connect (statesub, "tcp://localhost:5003"); fsm.state = STATE_BACKUP; } else { printf ("Usage: bstarsrv { -p | -b }\n"); zctx_destroy (&ctx); exit (0); } // Set timer for next outgoing state message int64_t send_state_at = zclock_time () + HEARTBEAT; while (!zctx_interrupted) { zmq_pollitem_t items [] = { { frontend, 0, ZMQ_POLLIN, 0 }, { statesub, 0, ZMQ_POLLIN, 0 } }; int time_left = (int) ((send_state_at - zclock_time ())); if (time_left < 0) time_left = 0; int rc = zmq_poll (items, 2, time_left * ZMQ_POLL_MSEC); if (rc == -1) break; // Context has been shut down if (items [0].revents & ZMQ_POLLIN) { // Have a client request zmsg_t *msg = zmsg_recv (frontend); fsm.event = CLIENT_REQUEST; if (s_state_machine (&fsm) == FALSE) // Answer client by echoing request back zmsg_send (&msg, frontend); else zmsg_destroy (&msg); } if (items [1].revents & ZMQ_POLLIN) { // Have state from our peer, execute as event char *message = zstr_recv (statesub); fsm.event = atoi (message); free (message); if (s_state_machine (&fsm)) break; // Error, so exit fsm.peer_expiry = zclock_time () + 2 * HEARTBEAT; } // If we timed-out, send state to peer if (zclock_time () >= send_state_at) { char message [2]; sprintf (message, "%d", fsm.state); zstr_send (statepub, message); send_state_at = zclock_time () + HEARTBEAT; } } if (zctx_interrupted) printf ("W: interrupted\n"); // Shutdown sockets and context zctx_destroy (&ctx); return 0; }
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); }
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; }
int main(void) { zctx_t* ctx = zctx_new(); printf("I: connecting to server...\n"); void* client = zsocket_new(ctx, ZMQ_REQ); assert(client); zsocket_connect(client, SERVER_ENDPOINT); int sequence = 0; int retries_left = REQUEST_RETRIES; while (retries_left && !zctx_interrupted) { // We send a request, then we work to get a reply. char request[10]; sprintf(request, "%d", ++sequence); zstr_send(client, request); int expect_reply = 1; while (expect_reply) { // Poll socket for a reply, with timeout. zmq_pollitem_t items[] = { { client, 0, ZMQ_POLLIN, 0 } }; int rc = zmq_poll(items, 1, REQUEST_TIMEOUT * ZMQ_POLL_MSEC); if (rc == -1) { break; // Interrupted. } if (items[0].revents & ZMQ_POLLIN) { // We got a reply from the server, must match sequence. char* reply = zstr_recv(client); if (!reply) { break; // Interrupted. } if (atoi(reply) == sequence) { printf("I: server replied OK (%s)\n", reply); retries_left = REQUEST_RETRIES; expect_reply = 0; } else { printf("E: malformed reply from server: %s\n", reply); } free(reply); } else if (--retries_left == 0) { printf("E: server seems to be offline, abandoning\n"); break; } else { printf("W: no response from server, retrying...\n"); // Old socket is confused; close it and open a new one. zsocket_destroy(ctx, client); printf("I: reconnecting to server...\n"); client = zsocket_new(ctx, ZMQ_REQ); zsocket_connect(client, SERVER_ENDPOINT); // Send request again, on new socket. zstr_send(client, request); } } } zctx_destroy(&ctx); return 0; }
static rsRetVal addListener(instanceConf_t* iconf){ struct lstn_s* pData; DEFiRet; CHKmalloc(pData=(struct lstn_s*)MALLOC(sizeof(struct lstn_s))); pData->next = NULL; pData->pRuleset = iconf->pBindRuleset; /* Create the zeromq socket */ /* ------------------------ */ pData->sock = zsock_new(iconf->sockType); if (!pData->sock) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: new socket failed for endpoints: %s", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } DBGPRINTF ("imczmq: created socket...\n"); /* Create the beacon actor if configured */ /* ------------------------------------- */ if((iconf->beacon != NULL) && (iconf->beaconPort > 0)) { DBGPRINTF ("imczmq: starting beacon actor...\n"); pData->beaconActor = zactor_new(zbeacon, NULL); if (!pData->beaconActor) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: could not create beacon service"); ABORT_FINALIZE (RS_RET_NO_ERRCODE); } zsock_send(pData->beaconActor, "si", "CONFIGURE", iconf->beaconPort); char *hostname = zstr_recv(pData->beaconActor); if (!*hostname) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: no UDP broadcasting available"); ABORT_FINALIZE (RS_RET_NO_ERRCODE); } zsock_send(pData->beaconActor, "sbi", "PUBLISH", pData->beaconActor, strlen(iconf->beacon)); DBGPRINTF ("omczmq: beacon is lit: hostname: '%s', port: '%d'...\n", hostname, iconf->beaconPort); } DBGPRINTF("imczmq: authtype is: %s\n", iconf->authType); if (iconf->authType != NULL) { /* CURVESERVER */ /* ----------- */ if (!strcmp(iconf->authType, "CURVESERVER")) { zsock_set_zap_domain(pData->sock, "global"); zsock_set_curve_server(pData->sock, 1); pData->serverCert = zcert_load(iconf->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(pData->serverCert, pData->sock); zstr_sendx(authActor, "CURVE", iconf->clientCertPath, NULL); zsock_wait(authActor); DBGPRINTF("imczmq: CURVESERVER: serverCertPath: '%s'\n", iconf->serverCertPath); DBGPRINTF("mczmq: CURVESERVER: clientCertPath: '%s'\n", iconf->clientCertPath); } /* CURVECLIENT */ /* ----------- */ else if (!strcmp(iconf->authType, "CURVECLIENT")) { if (!strcmp(iconf->clientCertPath, "*")) { pData->clientCert = zcert_new(); } else { pData->clientCert = zcert_load(iconf->clientCertPath); } if (!pData->clientCert) { errmsg.LogError(0, NO_ERRCODE, "could not load client cert"); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(pData->clientCert, pData->sock); pData->serverCert = zcert_load(iconf->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } char *server_key = zcert_public_txt(pData->serverCert); zsock_set_curve_serverkey (pData->sock, server_key); DBGPRINTF("imczmq: CURVECLIENT: serverCertPath: '%s'\n", iconf->serverCertPath); DBGPRINTF("imczmq: CURVECLIENT: clientCertPath: '%s'\n", iconf->clientCertPath); DBGPRINTF("imczmq: CURVECLIENT: server_key: '%s'\n", server_key); } else { errmsg.LogError(0, NO_ERRCODE, "unrecognized auth type: '%s'", iconf->authType); ABORT_FINALIZE(RS_RET_ERR); } } /* subscribe to topics */ /* ------------------- */ if (iconf->sockType == ZMQ_SUB) { char topic[256], *list = iconf->topicList; while (list) { char *delimiter = strchr(list, ','); if (!delimiter) { delimiter = list + strlen (list); } if (delimiter - list > 255) { errmsg.LogError(0, NO_ERRCODE, "iconf->topicList must be under 256 characters"); ABORT_FINALIZE(RS_RET_ERR); } memcpy(topic, list, delimiter - list); topic[delimiter - list] = 0; zsock_set_subscribe(pData->sock, topic); if (*delimiter == 0) { break; } list = delimiter + 1; } } switch (iconf->sockType) { case ZMQ_SUB: iconf->serverish = false; break; case ZMQ_PULL: case ZMQ_ROUTER: iconf->serverish = true; break; } int rc = zsock_attach(pData->sock, (const char*)iconf->sockEndpoints, iconf->serverish); if (rc == -1) { errmsg.LogError(0, NO_ERRCODE, "zsock_attach to %s", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_ERR); } /* add this struct to the global */ /* ----------------------------- */ if(lcnfRoot == NULL) { lcnfRoot = pData; } if(lcnfLast == NULL) { lcnfLast = pData; } else { lcnfLast->next = pData; lcnfLast = pData; } finalize_it: RETiRet; }
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"); }
/// // Receive C string from socket. Caller must free returned string using // zstr_free(). Returns NULL if the context is being terminated or the // process was interrupted. const QString QmlZstrAttached::recv (void *source) { return QString (zstr_recv (source)); };
static void node_actor (zsock_t *pipe, void *args) { zyre_t *node = zyre_new (NULL); if (!node) return; // Could not create new node zyre_set_verbose (node); zyre_set_endpoint (node, "inproc://%s", (char *) args); free (args); // Connect to test hub zyre_gossip_connect (node, "inproc://zyre-hub"); zyre_start (node); zsock_signal (pipe, 0); // Signal "ready" to caller int counter = 0; char *to_peer = NULL; // Either of these set, char *to_group = NULL; // and we set a message char *cookie = NULL; zpoller_t *poller = zpoller_new (pipe, zyre_socket (node), NULL); int64_t trigger = zclock_mono () + 1000; while (true) { void *which = zpoller_wait (poller, randof (1000)); if (!which) break; // Interrupted // $TERM from parent means exit; anything else is breach of // contract so we should assert if (which == pipe) { char *command = zstr_recv (pipe); assert (streq (command, "$TERM")); zstr_free (&command); break; // Finished } // Process an event from node if (which == zyre_socket (node)) { zmsg_t *incoming = zyre_recv (node); if (!incoming) break; // Interrupted char *event = zmsg_popstr (incoming); char *peer = zmsg_popstr (incoming); char *name = zmsg_popstr (incoming); if (streq (event, "ENTER")) // Always say hello to new peer to_peer = strdup (peer); else if (streq (event, "EXIT")) // Always try talk to departed peer to_peer = strdup (peer); else if (streq (event, "WHISPER")) { // Send back response 1/2 the time if (randof (2) == 0) { to_peer = strdup (peer); cookie = zmsg_popstr (incoming); } } else if (streq (event, "SHOUT")) { to_peer = strdup (peer); to_group = zmsg_popstr (incoming); cookie = zmsg_popstr (incoming); // Send peer response 1/3rd the time if (randof (3) > 0) { free (to_peer); to_peer = NULL; } // Send group response 1/3rd the time if (randof (3) > 0) { free (to_group); to_group = NULL; } } else if (streq (event, "JOIN")) { char *group = zmsg_popstr (incoming); printf ("I: %s joined %s\n", name, group); free (group); } else if (streq (event, "LEAVE")) { char *group = zmsg_popstr (incoming); printf ("I: %s left %s\n", name, group); free (group); } free (event); free (peer); free (name); zmsg_destroy (&incoming); // Send outgoing messages if needed if (to_peer) { zyre_whispers (node, to_peer, "%d", counter++); free (to_peer); to_peer = NULL; } if (to_group) { zyre_shouts (node, to_group, "%d", counter++); free (to_group); to_group = NULL; } if (cookie) { free (cookie); cookie = NULL; } } if (zclock_mono () >= trigger) { trigger = zclock_mono () + 1000; char group [10]; sprintf (group, "GROUP%03d", randof (MAX_GROUP)); if (randof (4) == 0) zyre_join (node, group); else if (randof (3) == 0) zyre_leave (node, group); } } zpoller_destroy (&poller); zyre_destroy (&node); }
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 main (int argc, char *argv []) { // First argument is this broker's name // Other arguments are our peers' names // if (argc < 2) { printf ("syntax: peering3 me {you}...\n"); exit (EXIT_FAILURE); } self = argv [1]; printf ("I: preparing broker at %s...\n", self); srandom ((unsigned) time (NULL)); // Prepare our context and sockets zctx_t *ctx = zctx_new (); char endpoint [256]; // Bind cloud frontend to endpoint void *cloudfe = zsocket_new (ctx, ZMQ_ROUTER); zsockopt_set_identity (cloudfe, self); zsocket_bind (cloudfe, "ipc://%s-cloud.ipc", self); // Bind state backend / publisher to endpoint void *statebe = zsocket_new (ctx, ZMQ_PUB); zsocket_bind (statebe, "ipc://%s-state.ipc", self); // Connect cloud backend to all peers void *cloudbe = zsocket_new (ctx, ZMQ_ROUTER); zsockopt_set_identity (cloudbe, self); int argn; for (argn = 2; argn < argc; argn++) { char *peer = argv [argn]; printf ("I: connecting to cloud frontend at '%s'\n", peer); zsocket_connect (cloudbe, "ipc://%s-cloud.ipc", peer); } // Connect statefe to all peers void *statefe = zsocket_new (ctx, ZMQ_SUB); for (argn = 2; argn < argc; argn++) { char *peer = argv [argn]; printf ("I: connecting to state backend at '%s'\n", peer); zsocket_connect (statefe, "ipc://%s-state.ipc", peer); } // Prepare local frontend and backend void *localfe = zsocket_new (ctx, ZMQ_ROUTER); zsocket_bind (localfe, "ipc://%s-localfe.ipc", self); void *localbe = zsocket_new (ctx, ZMQ_ROUTER); zsocket_bind (localbe, "ipc://%s-localbe.ipc", self); // Prepare monitor socket void *monitor = zsocket_new (ctx, ZMQ_PULL); zsocket_bind (monitor, "ipc://%s-monitor.ipc", self); // Start local workers int worker_nbr; for (worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++) zthread_new (ctx, worker_task, NULL); // Start local clients int client_nbr; for (client_nbr = 0; client_nbr < NBR_CLIENTS; client_nbr++) zthread_new (ctx, client_task, NULL); // Interesting part // ------------------------------------------------------------- // Publish-subscribe flow // - Poll statefe and process capacity updates // - Each time capacity changes, broadcast new value // Request-reply flow // - Poll primary and process local/cloud replies // - While worker available, route localfe to local or cloud // Queue of available workers int local_capacity = 0; int cloud_capacity = 0; zlist_t *workers = zlist_new (); while (1) { zmq_pollitem_t primary [] = { { localbe, 0, ZMQ_POLLIN, 0 }, { cloudbe, 0, ZMQ_POLLIN, 0 }, { statefe, 0, ZMQ_POLLIN, 0 }, { monitor, 0, ZMQ_POLLIN, 0 } }; // If we have no workers anyhow, wait indefinitely int rc = zmq_poll (primary, 4, local_capacity? 1000 * ZMQ_POLL_MSEC: -1); if (rc == -1) break; // Interrupted // Track if capacity changes during this iteration int previous = local_capacity; // Handle reply from local worker zmsg_t *msg = NULL; if (primary [0].revents & ZMQ_POLLIN) { msg = zmsg_recv (localbe); if (!msg) break; // Interrupted zframe_t *address = zmsg_unwrap (msg); zlist_append (workers, address); local_capacity++; // If it's READY, don't route the message any further zframe_t *frame = zmsg_first (msg); if (memcmp (zframe_data (frame), LRU_READY, 1) == 0) zmsg_destroy (&msg); } // Or handle reply from peer broker else if (primary [1].revents & ZMQ_POLLIN) { msg = zmsg_recv (cloudbe); if (!msg) break; // Interrupted // We don't use peer broker address for anything zframe_t *address = zmsg_unwrap (msg); zframe_destroy (&address); } // Route reply to cloud if it's addressed to a broker for (argn = 2; msg && argn < argc; argn++) { char *data = (char *) zframe_data (zmsg_first (msg)); size_t size = zframe_size (zmsg_first (msg)); if (size == strlen (argv [argn]) && memcmp (data, argv [argn], size) == 0) zmsg_send (&msg, cloudfe); } // Route reply to client if we still need to if (msg) zmsg_send (&msg, localfe); // Handle capacity updates if (primary [2].revents & ZMQ_POLLIN) { char *status = zstr_recv (statefe); cloud_capacity = atoi (status); free (status); } // Handle monitor message if (primary [3].revents & ZMQ_POLLIN) { char *status = zstr_recv (monitor); printf ("%s\n", status); free (status); } // Now route as many clients requests as we can handle // - If we have local capacity we poll both localfe and cloudfe // - If we have cloud capacity only, we poll just localfe // - Route any request locally if we can, else to cloud // while (local_capacity + cloud_capacity) { zmq_pollitem_t secondary [] = { { localfe, 0, ZMQ_POLLIN, 0 }, { cloudfe, 0, ZMQ_POLLIN, 0 } }; if (local_capacity) rc = zmq_poll (secondary, 2, 0); else rc = zmq_poll (secondary, 1, 0); assert (rc >= 0); if (secondary [0].revents & ZMQ_POLLIN) msg = zmsg_recv (localfe); else if (secondary [1].revents & ZMQ_POLLIN) msg = zmsg_recv (cloudfe); else break; // No work, go back to primary if (local_capacity) { zframe_t *frame = (zframe_t *) zlist_pop (workers); zmsg_wrap (msg, frame); zmsg_send (&msg, localbe); local_capacity--; } else { // Route to random broker peer int random_peer = randof (argc - 2) + 2; zmsg_pushmem (msg, argv [random_peer], strlen (argv [random_peer])); zmsg_send (&msg, cloudbe); } } if (local_capacity != previous) { // We stick our own address onto the envelope zstr_sendm (statebe, self); // Broadcast new capacity zstr_sendf (statebe, "%d", local_capacity); } } // 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 EXIT_SUCCESS; }
/// // Receive C string from socket. Caller must free returned string using // zstr_free(). Returns NULL if the context is being terminated or the // process was interrupted. QString QmlZstrAttached::recv (void *source) { char *retStr_ = zstr_recv (source); QString retQStr_ = QString (retStr_); free (retStr_); return retQStr_; };