예제 #1
0
파일: zmonitor.c 프로젝트: sirithink/czmq
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 (!zctx_interrupted) {
        //  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);

        if (self->terminated)
            break;
    }
    zpoller_destroy (&poller);
    s_agent_destroy (&self);
}
예제 #2
0
파일: drops_agent.c 프로젝트: edgenet/drops
void
drops_agent_main (void *args, zctx_t *ctx, void *pipe)
{
    //  Create agent instance to pass around
    s_agent_t *self = s_agent_new (ctx, pipe);
    if (!self)                  //  Interrupted
        return;
    zstr_send (self->pipe, "OK");

    //  These are the sockets we will monitor for activity
    zpoller_t *poller = zpoller_new (
        self->pipe, zyre_socket (self->zyre), NULL);

    while (!zpoller_terminated (poller)) {
        //  Check directory once a second; this is a pretty nasty way of
        //  doing it, but portable and simple. Later I'd like to use file
        //  system monitoring library and get events back over a socket.
        void *which = zpoller_wait (poller, 1000);
        if (which == self->pipe)
            s_recv_from_api (self);
        else
        if (which == zyre_socket (self->zyre))
            s_recv_from_zyre (self);
        
        if (self->terminated)
            break;
        
        s_check_directory (self);
    }
    zpoller_destroy (&poller);
    s_agent_destroy (&self);
}
예제 #3
0
파일: zyre_node.c 프로젝트: Muraad/zyre
static zyre_node_t *
zyre_node_new (zsock_t *pipe, void *args)
{
    zyre_node_t *self = (zyre_node_t *) zmalloc (sizeof (zyre_node_t));
    self->inbox = zsock_new (ZMQ_ROUTER);
    if (self->inbox == NULL) {
        free (self);
        return NULL;            //  Could not create new socket
    }
    //  Use ZMQ_ROUTER_HANDOVER so that when a peer disconnects and
    //  then reconnects, the new client connection is treated as the
    //  canonical one, and any old trailing commands are discarded.
    zsock_set_router_handover (self->inbox, 1);
    
    self->pipe = pipe;
    self->outbox = (zsock_t *) args;
    self->poller = zpoller_new (self->pipe, NULL);
    self->beacon_port = ZRE_DISCOVERY_PORT;
    self->interval = 0;         //  Use default
    self->uuid = zuuid_new ();
    self->peers = zhash_new ();
    self->peer_groups = zhash_new ();
    self->own_groups = zhash_new ();
    self->headers = zhash_new ();
    zhash_autofree (self->headers);

    //  Default name for node is first 6 characters of UUID:
    //  the shorter string is more readable in logs
    self->name = (char *) zmalloc (7);
    memcpy (self->name, zuuid_str (self->uuid), 6);
    return self;
}
예제 #4
0
파일: zauth.c 프로젝트: AxelVoitier/czmq
static self_t *
s_self_new (zsock_t *pipe, zcertstore_t *certstore)
{
    self_t *self = (self_t *) zmalloc (sizeof (self_t));
    assert (self);
    if (certstore) {
        self->certstore = certstore;
        self->allow_any = false;
    }
    self->pipe = pipe;
    self->whitelist = zhashx_new ();
    assert (self->whitelist);
    self->blacklist = zhashx_new ();

    //  Create ZAP handler and get ready for requests
    assert (self->blacklist);
    self->handler = zsock_new (ZMQ_REP);
    assert (self->handler);
    int rc = zsock_bind (self->handler, ZAP_ENDPOINT);
    assert (rc == 0);
    self->poller = zpoller_new (self->pipe, self->handler, NULL);
    assert (self->poller);

    return self;
}
예제 #5
0
파일: zauth_v2.c 프로젝트: AxelVoitier/czmq
//  Checks whether client can connect to server
static bool
s_can_connect (zctx_t *ctx, void **server, void **client)
{
    int port_nbr = zsocket_bind (*server, "tcp://127.0.0.1:*");
    assert (port_nbr > 0);
    int rc = zsocket_connect (*client, "tcp://127.0.0.1:%d", port_nbr);
    assert (rc == 0);
    //  Give the connection time to fail if that's the plan
    zclock_sleep (200);

    //  By default PUSH sockets block if there's no peer
    zsock_set_sndtimeo (*server, 200);
    zstr_send (*server, "Hello, World");

    zpoller_t *poller = zpoller_new (*client, NULL);
    bool success = (zpoller_wait (poller, 400) == *client);
    zpoller_destroy (&poller);
    zsocket_destroy (ctx, *client);
    zsocket_destroy (ctx, *server);
    *server = zsocket_new (ctx, ZMQ_PUSH);
    assert (*server);
    *client = zsocket_new (ctx, ZMQ_PULL);
    assert (*client);
    return success;
}
예제 #6
0
static bool
s_can_connect (void *server, void *client)
{
    //  We'll do each test on a new port number since otherwise we have to
    //  destroy and recreate the sockets each time.
    static int port_nbr = 9000;
    int rc = zsocket_bind (server, "tcp://*:%d", port_nbr);
    assert (rc == port_nbr);
    rc = zsocket_connect (client, "tcp://localhost:%d", port_nbr);
    assert (rc == 0);
    
    zpoller_t *poller = zpoller_new (client, NULL);
    zstr_send (server, "Hello, World");
    //  Need up to half a second if running under Valgrind
    bool success = zpoller_wait (poller, 500) == client;
    if (success)
        free (zstr_recv (client));
    zpoller_destroy (&poller);
    rc = zsocket_unbind (server, "tcp://*:%d", port_nbr);
    assert (rc != -1);
    rc = zsocket_disconnect (client, "tcp://localhost:%d", port_nbr);
    assert (rc != -1);
    port_nbr++;
    return success;
}
예제 #7
0
파일: broker.c 프로젝트: emef/sprk
broker_t *
broker_new (const char *contexts_uri, const char *executors_uri)
{
    broker_t *self = (broker_t *) malloc (sizeof (broker_t));
    assert (self);

    printf ("[BROKER] binding to frontend %s\n", contexts_uri);
    self->contexts = zsock_new_router (contexts_uri);
    assert(self->contexts);

    printf ("[BROKER] binding to backend %s\n", executors_uri);
    self->executors = zsock_new_router (executors_uri);
    assert (self->executors);
    zsock_set_router_mandatory (self->executors, true);

    // Only poll on executors until we have executors available.
    self->poller = zpoller_new (self->executors, NULL);
    assert (self->poller);

    self->executor_lb = zlist_new ();
    assert (self->executor_lb);

    self->backlog = zlist_new ();
    assert (self->backlog);

    return self;
}
예제 #8
0
MessageProcessor::MessageProcessor(ServerLoader& loader)
    : server_(loader.getServer())
    , zmqSocket_(zsock_new_rep(NULL))
    , zmqAuth_(zactor_new(zauth, NULL))
    , zmqPoller_(zpoller_new(zmqSocket_, NULL))
{
    init(loader.getPort(), loader.getTransportKey());
}
예제 #9
0
JNIEXPORT jlong JNICALL
Java_org_zeromq_czmq_Zpoller__1_1new (JNIEnv *env, jclass c, jlong reader)
{
    //  Disable CZMQ signal handling; allow Java to deal with it
    zsys_handler_set (NULL);
    jlong new_ = (jlong) (intptr_t) zpoller_new ((void *) (intptr_t) reader);
    return new_;
}
예제 #10
0
파일: zmonitor.c 프로젝트: reqshark/czmq
static self_t *
s_self_new (zsock_t *pipe, zsock_t *sock)
{
    self_t *self = (self_t *) zmalloc (sizeof (self_t));
    self->pipe = pipe;
    self->monitored = zsock_resolve (sock);
    self->poller = zpoller_new (self->pipe, NULL);
    return self;
}
예제 #11
0
파일: zproxy.c 프로젝트: claws/czmq
static self_t *
s_self_new (zsock_t *pipe)
{
    self_t *self = (self_t *) zmalloc (sizeof (self_t));
    if (self) {
        self->pipe = pipe;
        self->poller = zpoller_new (self->pipe, NULL);
        if (!self->poller)
            s_self_destroy (&self);
    }
    return self;
}
예제 #12
0
static someactor_t *
someactor_new (zsock_t *pipe, void *args)
{
    someactor_t *self = (someactor_t *) zmalloc (sizeof (someactor_t));
    assert (self);

    self->pipe = pipe;
    self->terminated = false;
    self->poller = zpoller_new (self->pipe, NULL);

    //  TODO: Initialize properties

    return self;
}
예제 #13
0
static self_t *
s_self_new (zsock_t *pipe, void *sock)
{
    self_t *self = (self_t *) zmalloc (sizeof (self_t));
    if (!self)
        return NULL;

    self->pipe = pipe;
    self->monitored = zsock_resolve (sock);
    self->poller = zpoller_new (self->pipe, NULL);
    if (!self->poller)
        s_self_destroy (&self);
    return self;
}
예제 #14
0
파일: alerts.c 프로젝트: miska/mallory
static void
s_alerts (
    zsock_t *pipe,
    void *args) {

    const char *name = "ALERT";

    mlm_client_t *cl = mlm_client_new ();
    mlm_client_connect (cl, endpoint, 5000, __PRETTY_FUNCTION__);
    mlm_client_set_producer (cl, stream);

    zsock_t *msgpipe = mlm_client_msgpipe (cl);

    zpoller_t *poller = zpoller_new (pipe, msgpipe, NULL);

    char *alert_state = strdup ("NEW");

    zsock_signal (pipe, 0);
    while (!zsys_interrupted) {
        zsock_t *which = zpoller_wait (poller, 1000);

        if (!which) {
            mlm_client_sendx (cl, "alert://upsonbattery@ups1", alert_state, NULL);
            continue;
        }

        if (which == pipe)
            break;

        //which == msgpipe
        zmsg_t *msg = mlm_client_recv (cl);
        if (!streq (mlm_client_command (cl), "MAILBOX DELIVER"))
            goto msg_destroy;

        char *alert_name = zmsg_popstr (msg);

        zstr_free (&alert_state);
        alert_state = zmsg_popstr (msg);

        zsys_info ("%s: Alert '%s' new state is '%s'", name, alert_name, alert_state);
        zstr_free (&alert_name);
msg_destroy:
        zmsg_destroy (&msg);
    }

    zstr_free (&alert_state);
    zpoller_destroy (&poller);
    mlm_client_destroy (&cl);
}
예제 #15
0
upstream_t *
s_upstream_new (zsock_t *pipe)
{
    upstream_t *self = (upstream_t *) zmalloc (sizeof (upstream_t));
    assert (self);

    self->terminated = false;
    self->connected = false;
    self->pipe = pipe;
    self->poller = zpoller_new (self->pipe, NULL);
    self->push = zsock_new (ZMQ_PUSH);
    self->size = FRAGMENT_SIZE;
    self->variance = 1000;
    
    return self;
}
예제 #16
0
파일: zauth.c 프로젝트: hisitepu/czmq
static self_t *
s_self_new (zsock_t *pipe)
{
    self_t *self = (self_t *) zmalloc (sizeof (self_t));
    self->pipe = pipe;
    self->whitelist = zhash_new ();
    self->blacklist = zhash_new ();

    //  Create ZAP handler and get ready for requests
    self->handler = zsock_new (ZMQ_REP);
    assert (self->handler);
    int rc = zsock_bind (self->handler, "inproc://zeromq.zap.01");
    assert (rc == 0);
    self->poller = zpoller_new (self->pipe, self->handler, NULL);
    return self;
}
예제 #17
0
파일: zyre_node.c 프로젝트: mjhowell/zyre
void
zyre_node_engine (void *args, zctx_t *ctx, void *pipe)
{
    //  Create node instance to pass around
    zyre_node_t *self = zyre_node_new (ctx, pipe);
    if (!self)                  //  Interrupted
        return;
    zsocket_signal (self->pipe);

    uint64_t reap_at = zclock_time () + REAP_INTERVAL;
    zpoller_t *poller = zpoller_new (
        self->pipe, self->inbox, zbeacon_socket (self->beacon), NULL);

    while (!zpoller_terminated (poller)) {
        if (self->terminated)
            break;
        int timeout = (int) (reap_at - zclock_time ());
        assert (timeout <= REAP_INTERVAL);
        if (timeout < 0)
            timeout = 0;
        void *which = zpoller_wait (poller, timeout);
        if (which == self->pipe)
            zyre_node_recv_api (self);
        else
        if (which == self->inbox)
            zyre_node_recv_peer (self);
        else
        if (which == zbeacon_socket (self->beacon))
            zyre_node_recv_beacon (self);
        else
        if (zpoller_expired(poller)) {
            if (zclock_time () >= reap_at) {
                reap_at = zclock_time () + REAP_INTERVAL;
                //  Ping all peers and reap any expired ones
                zhash_foreach (self->peers, zyre_node_ping_peer, self);
            }
        }
        else
        if (zpoller_terminated(poller))
            break;
        else
            // This should never happen
            assert(false);
    }
    zpoller_destroy (&poller);
    zyre_node_destroy (&self);
}
예제 #18
0
static stream_engine_t *
s_stream_engine_new (zsock_t *cmdpipe, zsock_t *msgpipe)
{
    stream_engine_t *self = (stream_engine_t *) zmalloc (sizeof (stream_engine_t));
    if (self) {
        self->cmdpipe = cmdpipe;
        self->msgpipe = msgpipe;
        self->poller = zpoller_new (self->cmdpipe, self->msgpipe, NULL);
        if (self->poller)
            self->selectors = zlistx_new ();
        if (self->selectors)
            zlistx_set_destructor (self->selectors, (czmq_destructor *) s_selector_destroy);
        else
            s_stream_engine_destroy (&self);
    }
    return self;
}
예제 #19
0
파일: zauth.c 프로젝트: guruofquality/czmq
//  Checks whether client can connect to server
static bool
s_can_connect (zctx_t *ctx, void **server, void **client)
{
    int port_nbr = zsocket_bind (*server, "tcp://127.0.0.1:*");
    assert (port_nbr > 0);
    int rc = zsocket_connect (*client, "tcp://127.0.0.1:%d", port_nbr);
    assert (rc == 0);
    zstr_send (*server, "Hello, World");
    zpoller_t *poller = zpoller_new (*client, NULL);
    bool success = (zpoller_wait (poller, 200) == *client);
    zpoller_destroy (&poller);
    zsocket_destroy (ctx, *client);
    zsocket_destroy (ctx, *server);
    *server = zsocket_new (ctx, ZMQ_PUSH);
    *client = zsocket_new (ctx, ZMQ_PULL);
    return success;
}
예제 #20
0
파일: twps_server.c 프로젝트: zgwmike/TWPS
static void run(bool verbose, bool diagnostic, bool proxy_log) {
    hid_init();
    zsys_set_logsender(LOG_PUB_ENDPOINT);
//    zsys_set_logsystem(true);
    twps_server_t *self = twps_new(verbose, proxy_log);
    assert(self);
    self->diagnostic = diagnostic;
    zpoller_t *poller = zpoller_new(self->printer_store_sub, NULL);
    while (!zctx_interrupted) {
        void *which = zpoller_wait(poller, 200);
        if (which == self->printer_store_sub) {
            s_loop_handle_printer_store_sub(self);
        }
    }
    zpoller_destroy(&poller);
    twps_destroy(&self);
    hid_exit();
}
예제 #21
0
파일: maltcp_ctx.c 프로젝트: ccsdsmo/malc
int maltcp_ctx_poller_add_endpoint(
    void *self,
    mal_poller_t *mal_poller,
    mal_endpoint_t *mal_endpoint) {
  maltcp_poller_data_t *poller_data = (maltcp_poller_data_t *) mal_poller_get_poller_data(mal_poller);
  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_poller_add_endpoint(): %s\n", mal_endpoint_get_uri(mal_endpoint));

  maltcp_add_endpoint(poller_data, mal_endpoint);
  if (poller_data->poller == NULL)
    poller_data->poller = zpoller_new(endpoint_data->socket, NULL);
  else
    rc = zpoller_add(poller_data->poller, endpoint_data->socket);

  return rc;
}
예제 #22
0
파일: zhttp_client.c 프로젝트: sphaero/czmq
int
zhttp_client_wait (zhttp_client_t *self, int timeout) {
    zpoller_t *poller = zpoller_new (self, NULL);
    void* sock = zpoller_wait (poller, timeout);

    if (sock) {
        zpoller_destroy (&poller);
        return 0;
    }

    if (zpoller_expired (poller))
        errno = EAGAIN;
    else
        errno = ETERM;

    zpoller_destroy (&poller);

    return -1;
}
예제 #23
0
파일: 0mq.c 프로젝트: datto/RDPMux
/**
 * @brief Connects to the 0mq socket on path.
 *
 * Connects to the 0mq socket located on the file path passed in, then stores that socket in the global display struct
 * upon success.
 *
 * @returns Whether the connection succeeded.
 *
 * @param path The path to the 0mq socket in the filesystem.
 */
__PUBLIC bool mux_connect(const char *path)
{
    display->zmq.path = path;
    display->zmq.socket = zsock_new_dealer(display->zmq.path);
    zsys_handler_set(mux_handler);
    if (display->zmq.socket == NULL) {
        mux_printf_error("0mq socket creation failed");
        return false;
    }

    display->zmq.poller = zpoller_new(display->zmq.socket, NULL);
    if (display->zmq.poller == NULL) {
        mux_printf_error("Could not initialize socket poller");
        return false;
    }
    mux_printf("Bound to %s", path);

    return true;
}
예제 #24
0
static
void parser(zsock_t *pipe, void *args)
{
    parser_state_t *state = (parser_state_t*)args;
    state->pipe = pipe;
    set_thread_name(state->me);
    size_t id = state->id;

    // signal readyiness after sockets have been created
    zsock_signal(pipe, 0);

    zpoller_t *poller = zpoller_new(state->pipe, state->pull_socket, NULL);
    assert(poller);

    while (!zsys_interrupted) {
        // -1 == block until something is readable
        void *socket = zpoller_wait(poller, -1);
        zmsg_t *msg = NULL;
        if (socket == state->pipe) {
            msg = zmsg_recv(state->pipe);
            char *cmd = zmsg_popstr(msg);
            zmsg_destroy(&msg);
            if (streq(cmd, "$TERM")) {
                fprintf(stderr, "[D] parser [%zu]: received $TERM command\n", id);
                free(cmd);
                break;
            } else {
                fprintf(stderr, "[E] parser [%zu]: received unknown command: %s\n", id, cmd);
                free(cmd);
                assert(false);
            }
        } else if (socket == state->pull_socket) {
            process_logjam_message(state);
        } else {
            // socket == NULL, probably interrupted by signal handler
            break;
        }
    }

    printf("[I] parser [%zu]: shutting down\n", id);
    parser_state_destroy(&state);
    printf("[I] parser [%zu]: terminated\n", id);
}
예제 #25
0
파일: zyre_log.c 프로젝트: mjhowell/zyre
void
zyre_log_test (bool verbose)
{
    printf (" * zyre_log: ");

    //  @selftest
    zctx_t *ctx = zctx_new ();
    //  Get all incoming log messages
    void *collector = zsocket_new (ctx, ZMQ_SUB);
    zsocket_bind (collector, "tcp://127.0.0.1:5555");
    zsocket_set_subscribe (collector, "");

    //  Create a log instance to send log messages
    zyre_log_t *log = zyre_log_new (ctx, "this is me");
    zyre_log_connect (log, "tcp://127.0.0.1:5555");

    //  Workaround for issue 270; give time for connect to
    //  happen and subscriptions to go to pub socket; 200
    //  msec should be enough for under valgrind on a slow PC
    zpoller_t *poller = zpoller_new (collector, NULL);
    zpoller_wait (poller, 200);

    //  Send some messages
    zyre_log_info (log, ZRE_LOG_MSG_EVENT_JOIN, NULL, "this is you");
    zyre_log_info (log, ZRE_LOG_MSG_EVENT_EXIT, "Pizza time", "this is you");
    zyre_log_warning (log, "this is you", "Time flies like an %s", "arrow");
    zyre_log_error (log, "this is you", "Fruit flies like a %s", "banana");

    int count = 0;
    while (count < 4) {
        zre_log_msg_t *msg = zre_log_msg_recv (collector);
        assert (msg);
        if (verbose)
            zre_log_msg_dump (msg);
        zre_log_msg_destroy (&msg);
        count++;
    }
    zpoller_destroy (&poller);
    zyre_log_destroy (&log);
    zctx_destroy (&ctx);
    //  @end
    printf ("OK\n");
}
예제 #26
0
파일: echocli.c 프로젝트: zgwmike/broker
int main(int argc, const char *argv[]) {
    zsock_t *sock = zsock_new_req("tcp://127.0.0.1:5555");
    int count = 10000;

    zpoller_t *poller = zpoller_new(sock, NULL);
    while (count--) {
        zmsg_t *request = zmsg_new();
        zmsg_pushstr(request, "HELLO");
        zmsg_pushstr(request, "com.tw.echo");
        zmsg_pushstr(request, MDPC_CLIENT);
        zmsg_send(&request, sock);

        zmsg_t *msg = zmsg_recv(sock);
        zsys_info("GET RESPONSE: %d ", count);
        zmsg_print(msg);
        zmsg_destroy(&msg);
    }
    zsock_destroy(&sock);
    return 0;
}
예제 #27
0
파일: zauth.c 프로젝트: guruofquality/czmq
static void
s_agent_task (void *args, zctx_t *ctx, void *pipe)
{
    //  Create agent instance as we start this task
    agent_t *self = s_agent_new (ctx, pipe);
    if (!self)                  //  Interrupted
        return;
        
    zpoller_t *poller = zpoller_new (self->pipe, self->handler, NULL);
    while (!zpoller_terminated (poller) && !self->terminated) {
        void *which = zpoller_wait (poller, -1);
        if (which == self->pipe)
            s_agent_handle_pipe (self);
        else
        if (which == self->handler)
            s_agent_authenticate (self);
    }
    //  Done, free all agent resources
    zpoller_destroy (&poller);
    s_agent_destroy (&self);
}
예제 #28
0
파일: zyre_node.c 프로젝트: mvala/zyre
static int
zyre_node_stop (zyre_node_t *self)
{
    if (self->beacon) {
        //  Stop broadcast/listen beacon
        beacon_t beacon;
        beacon.protocol [0] = 'Z';
        beacon.protocol [1] = 'R';
        beacon.protocol [2] = 'E';
        beacon.version = BEACON_VERSION;
        beacon.port = 0;            //  Zero means we're stopping
        zuuid_export (self->uuid, beacon.uuid);
        zbeacon_publish (self->beacon, (byte *) &beacon, sizeof (beacon_t));
        zclock_sleep (1);           //  Allow 1 msec for beacon to go out
        zbeacon_destroy (&self->beacon);
    }
    //  Stop polling on inbox
    zpoller_destroy (&self->poller);
    self->poller = zpoller_new (self->pipe, NULL);
    return 0;
}
예제 #29
0
파일: zproxy.c 프로젝트: maxkozlovsky/czmq
// Checks whether client can connect to server
static bool
s_can_connect (zactor_t **proxy, zsock_t **faucet, zsock_t **sink, const char *frontend, const char *backend, bool verbose)
{
    assert (frontend);
    assert (*faucet);
    int rc = zsock_connect (*faucet, "%s", frontend);
    assert (rc == 0);

    assert (backend);
    assert (*sink);
    rc = zsock_connect (*sink, "%s", backend);
    assert (rc == 0);

    zstr_send (*faucet, "Hello, World");
    zpoller_t *poller = zpoller_new (*sink, NULL);
    assert (poller);
    bool success = (zpoller_wait (poller, 200) == *sink);
    zpoller_destroy (&poller);
    s_create_test_sockets (proxy, faucet, sink, verbose);

    return success;
}
예제 #30
0
파일: zlogger.c 프로젝트: hellogean/zyre
int main (int argc, char *argv [])
{
    zctx_t *ctx = zctx_new ();

    //  Use the CZMQ zbeacon class to make sure we listen on the
    //  same network interface as our peers
    zbeacon_t *beacon = zbeacon_new (ctx, ZRE_DISCOVERY_PORT);
    char *host = zbeacon_hostname (beacon);

    //  Bind to an ephemeral port
    void *collector = zsocket_new (ctx, ZMQ_SUB);
    int port = zsocket_bind (collector, "tcp://%s:*", host);
    zsocket_set_subscribe (collector, "");

    //  Announce this to all peers we connect to
    zyre_t *node = zyre_new (ctx);
    zyre_set_header (node, "X-ZRELOG", "tcp://%s:%d", host, port);
    zyre_start (node);

    zpoller_t *poller = zpoller_new (collector, zyre_socket (node), NULL);
    while (!zctx_interrupted) {
        void *which = zpoller_wait (poller, -1);
        if (which == collector)
            s_print_log_msg (collector);
        else if (which == zyre_socket (node)) {
            zmsg_t *msg = zyre_recv (node);
            if (!msg)
                break;              //  Interrupted
            zmsg_destroy (&msg);
        }
        else
            break;                  //  Interrupted
    }
    zyre_destroy (&node);
    zbeacon_destroy (&beacon);
    zctx_destroy (&ctx);
    return 0;
}