示例#1
0
文件: zre_msg.c 项目: karinies/coast
int
zre_msg_send_leave (
    void *output,
    uint16_t sequence,
    const char *group,
    byte status)
{
    zre_msg_t *self = zre_msg_new (ZRE_MSG_LEAVE);
    zre_msg_set_sequence (self, sequence);
    zre_msg_set_group (self, group);
    zre_msg_set_status (self, status);
    return zre_msg_send (&self, output);
}
示例#2
0
文件: zre_msg.c 项目: UIKit0/zyre
int
zre_msg_send_join (
    void *output,
    uint16_t sequence,
    char *group,
    byte status)
{
    zre_msg_t *self = zre_msg_new (ZRE_MSG_JOIN);
    zre_msg_set_sequence (self, sequence);
    zre_msg_set_group (self, group);
    zre_msg_set_status (self, status);
    return zre_msg_send (&self, output);
}
示例#3
0
文件: zre_msg.c 项目: UIKit0/zyre
int
zre_msg_send_shout (
    void *output,
    uint16_t sequence,
    char *group,
    zframe_t *content)
{
    zre_msg_t *self = zre_msg_new (ZRE_MSG_SHOUT);
    zre_msg_set_sequence (self, sequence);
    zre_msg_set_group (self, group);
    zre_msg_set_content (self, zframe_dup (content));
    return zre_msg_send (&self, output);
}
示例#4
0
static int
zyre_node_recv_api (zyre_node_t *self)
{
    //  Get the whole message off the pipe in one go
    zmsg_t *request = zmsg_recv (self->pipe);
    char *command = zmsg_popstr (request);
    if (!command)
        return -1;                  //  Interrupted

    if (streq (command, "SET")) {
        char *name = zmsg_popstr (request);
        char *value = zmsg_popstr (request);
        zhash_update (self->headers, name, value);
        zstr_free (&name);
        zstr_free (&value);
    }
    else
    if (streq (command, "START")) {
        zyre_node_start (self);
        zstr_send (self->pipe, "OK");
    }
    else
    if (streq (command, "STOP")) {
        zyre_node_stop (self);
        zstr_send (self->pipe, "OK");
    }
    else
    if (streq (command, "WHISPER")) {
        //  Get peer to send message to
        char *identity = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, identity);
        
        //  Send frame on out to peer's mailbox, drop message
        //  if peer doesn't exist (may have been destroyed)
        if (peer) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_WHISPER);
            zre_msg_set_content (msg, request);
            zyre_peer_send (peer, &msg);
            request = NULL;
        }
        zstr_free (&identity);
    }
    else
    if (streq (command, "SHOUT")) {
        //  Get group to send message to
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->peer_groups, name);
        if (group) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_SHOUT);
            zre_msg_set_group (msg, name);
            zre_msg_set_content (msg, request);
            zyre_group_send (group, &msg);
            request = NULL;
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "JOIN")) {
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name);
        if (!group) {
            //  Only send if we're not already in group
            group = zyre_group_new (name, self->own_groups);
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_JOIN);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            zhash_foreach (self->peers, zyre_node_send_peer, msg);
            zre_msg_destroy (&msg);
            zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_JOIN, NULL, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "LEAVE")) {
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name);
        if (group) {
            //  Only send if we are actually in group
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_LEAVE);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            zhash_foreach (self->peers, zyre_node_send_peer, msg);
            zre_msg_destroy (&msg);
            zhash_delete (self->own_groups, name);
            zyre_log_info (self->log, ZRE_LOG_MSG_EVENT_LEAVE, NULL, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "TERMINATE")) {
        self->terminated = true;
        zstr_send (self->pipe, "OK");
    }
    zstr_free (&command);
    zmsg_destroy (&request);
    return 0;
}
示例#5
0
文件: zyre_node.c 项目: opedroso/zyre
static void
zyre_node_recv_api (zyre_node_t *self)
{
    //  Get the whole message off the pipe in one go
    zmsg_t *request = zmsg_recv (self->pipe);
    if (!request)
        return;                 //  Interrupted

    char *command = zmsg_popstr (request);
    if (streq (command, "UUID"))
        zstr_send (self->pipe, zuuid_str (self->uuid));
    else
    if (streq (command, "NAME"))
        zstr_send (self->pipe, self->name);
    else
    if (streq (command, "SET NAME")) {
        free (self->name);
        self->name = zmsg_popstr (request);
        assert (self->name);
    }
    else
    if (streq (command, "SET HEADER")) {
        char *name = zmsg_popstr (request);
        char *value = zmsg_popstr (request);
        zhash_update (self->headers, name, value);
        zstr_free (&name);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET VERBOSE"))
        self->verbose = true;
    else
    if (streq (command, "SET PORT")) {
        char *value = zmsg_popstr (request);
        self->beacon_port = atoi (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET EVASIVE TIMEOUT")) {
        char *value = zmsg_popstr (request);
        self->evasive_timeout = atoi (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET EXPIRED TIMEOUT")) {
        char *value = zmsg_popstr (request);
        self->expired_timeout = atoi (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET INTERVAL")) {
        char *value = zmsg_popstr (request);
        self->interval = atol (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET ENDPOINT")) {
        zyre_node_gossip_start (self);
        char *endpoint = zmsg_popstr (request);
        if (zsock_bind (self->inbox, "%s", endpoint) != -1) {
            zstr_free (&self->endpoint);
            self->endpoint = endpoint;
            zsock_signal (self->pipe, 0);
        }
        else {
            zstr_free (&endpoint);
            zsock_signal (self->pipe, 1);
        }
    }
    else
    if (streq (command, "GOSSIP BIND")) {
        zyre_node_gossip_start (self);
        zstr_free (&self->gossip_bind);
        self->gossip_bind = zmsg_popstr (request);
        zstr_sendx (self->gossip, "BIND", self->gossip_bind, NULL);
    }
    else
    if (streq (command, "GOSSIP CONNECT")) {
        zyre_node_gossip_start (self);
        zstr_free (&self->gossip_connect);
        self->gossip_connect = zmsg_popstr (request);
        zstr_sendx (self->gossip, "CONNECT", self->gossip_connect, NULL);
    }
    else
    if (streq (command, "START"))
        zsock_signal (self->pipe, zyre_node_start (self));
    else
    if (streq (command, "STOP"))
        zsock_signal (self->pipe, zyre_node_stop (self));
    else
    if (streq (command, "WHISPER")) {
        //  Get peer to send message to
        char *identity = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, identity);

        //  Send frame on out to peer's mailbox, drop message
        //  if peer doesn't exist (may have been destroyed)
        if (peer) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_WHISPER);
            zre_msg_set_content (msg, &request);
            zyre_peer_send (peer, &msg);
        }
        zstr_free (&identity);
    }
    else
    if (streq (command, "SHOUT")) {
        //  Get group to send message to
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->peer_groups, name);
        if (group) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_SHOUT);
            zre_msg_set_group (msg, name);
            zre_msg_set_content (msg, &request);
            zyre_group_send (group, &msg);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "JOIN")) {
        char *name = zmsg_popstr (request);
        if (!zlist_exists (self->own_groups, name)) {
            void *item;
            //  Only send if we're not already in group
            zlist_append (self->own_groups, name);
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_JOIN);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            for (item = zhash_first (self->peers); item != NULL;
                    item = zhash_next (self->peers))
                zyre_node_send_peer (zhash_cursor (self->peers), item, msg);
            zre_msg_destroy (&msg);
            if (self->verbose)
                zsys_info ("(%s) JOIN group=%s", self->name, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "LEAVE")) {
        char *name = zmsg_popstr (request);
        if (zlist_exists (self->own_groups, name)) {
            void *item;
            //  Only send if we are actually in group
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_LEAVE);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            for (item = zhash_first (self->peers); item != NULL;
                    item = zhash_next (self->peers))
                zyre_node_send_peer (zhash_cursor (self->peers), item, msg);
            zre_msg_destroy (&msg);
            zlist_remove (self->own_groups, name);
            if (self->verbose)
                zsys_info ("(%s) LEAVE group=%s", self->name, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "PEERS"))
        zsock_send (self->pipe, "p", zhash_keys (self->peers));
    else
    if (streq (command, "GROUP PEERS")) {
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->peer_groups, name);
        if (group)
            zsock_send (self->pipe, "p", zyre_group_peers (group));
        else
            zsock_send (self->pipe, "p", NULL);

        zstr_free (&name);
    }
    else
    if (streq (command, "PEER ENDPOINT")) {
        char *uuid = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, uuid);
        assert (peer);
        zsock_send (self->pipe, "s", zyre_peer_endpoint (peer));
        zstr_free (&uuid);
    }
    else
    if (streq (command, "PEER NAME")) {
        char *uuid = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, uuid);
        assert (peer);
        zsock_send (self->pipe, "s", zyre_peer_name (peer));
        zstr_free (&uuid);
    }
    else
    if (streq (command, "PEER HEADER")) {
        char *uuid = zmsg_popstr (request);
        char *key = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, uuid);
        if (!peer)
            zstr_send (self->pipe, "");
        else
            zstr_send (self->pipe, zyre_peer_header (peer, key, NULL));
        zstr_free (&uuid);
        zstr_free (&key);
    }
    else
    if (streq (command, "PEER GROUPS"))
        zsock_send (self->pipe, "p", zhash_keys (self->peer_groups));
    else
    if (streq (command, "OWN GROUPS"))
        zsock_send (self->pipe, "p", zlist_dup (self->own_groups));
    else
    if (streq (command, "DUMP"))
        zyre_node_dump (self);
    else
    if (streq (command, "$TERM"))
        self->terminated = true;
    else {
        zsys_error ("invalid command '%s'", command);
        assert (false);
    }
    zstr_free (&command);
    zmsg_destroy (&request);
}
示例#6
0
文件: zre_msg.c 项目: karinies/coast
int
zre_msg_test (bool verbose)
{
    printf (" * zre_msg: ");

    //  @selftest
    //  Simple create/destroy test
    zre_msg_t *self = zre_msg_new (0);
    assert (self);
    zre_msg_destroy (&self);

    //  Create pair of sockets we can send through
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    void *output = zsocket_new (ctx, ZMQ_DEALER);
    assert (output);
    zsocket_bind (output, "inproc://selftest");

    void *input = zsocket_new (ctx, ZMQ_ROUTER);
    assert (input);
    zsocket_connect (input, "inproc://selftest");
    
    //  Encode/send/decode and verify each message type
    int instance;
    zre_msg_t *copy;
    self = zre_msg_new (ZRE_MSG_HELLO);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    zre_msg_set_ipaddress (self, "Life is short but Now lasts for ever");
    zre_msg_set_mailbox (self, 123);
    zre_msg_groups_append (self, "Name: %s", "Brutus");
    zre_msg_groups_append (self, "Age: %d", 43);
    zre_msg_set_status (self, 123);
    zre_msg_headers_insert (self, "Name", "Brutus");
    zre_msg_headers_insert (self, "Age", "%d", 43);
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        assert (streq (zre_msg_ipaddress (self), "Life is short but Now lasts for ever"));
        assert (zre_msg_mailbox (self) == 123);
        assert (zre_msg_groups_size (self) == 2);
        assert (streq (zre_msg_groups_first (self), "Name: Brutus"));
        assert (streq (zre_msg_groups_next (self), "Age: 43"));
        assert (zre_msg_status (self) == 123);
        assert (zre_msg_headers_size (self) == 2);
        assert (streq (zre_msg_headers_string (self, "Name", "?"), "Brutus"));
        assert (zre_msg_headers_number (self, "Age", 0) == 43);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_WHISPER);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    zmsg_t *whisper_content = zmsg_new ();
    zre_msg_set_content (self, &whisper_content);
    zmsg_addstr (zre_msg_content (self), "Hello, World");
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        assert (zmsg_size (zre_msg_content (self)) == 1);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_SHOUT);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zmsg_t *shout_content = zmsg_new ();
    zre_msg_set_content (self, &shout_content);
    zmsg_addstr (zre_msg_content (self), "Hello, World");
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
        assert (zmsg_size (zre_msg_content (self)) == 1);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_JOIN);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zre_msg_set_status (self, 123);
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
        assert (zre_msg_status (self) == 123);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_LEAVE);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zre_msg_set_status (self, 123);
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
        assert (zre_msg_status (self) == 123);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_PING);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        zre_msg_destroy (&self);
    }
    self = zre_msg_new (ZRE_MSG_PING_OK);
    
    //  Check that _dup works on empty message
    copy = zre_msg_dup (self);
    assert (copy);
    zre_msg_destroy (&copy);

    zre_msg_set_sequence (self, 123);
    //  Send twice from same object
    zre_msg_send_again (self, output);
    zre_msg_send (&self, output);

    for (instance = 0; instance < 2; instance++) {
        self = zre_msg_recv (input);
        assert (self);
        assert (zre_msg_routing_id (self));
        
        assert (zre_msg_sequence (self) == 123);
        zre_msg_destroy (&self);
    }

    zctx_destroy (&ctx);
    //  @end

    printf ("OK\n");
    return 0;
}
示例#7
0
文件: zyre_node.c 项目: mvala/zyre
static int
zyre_node_recv_api (zyre_node_t *self)
{
    //  Get the whole message off the pipe in one go
    zmsg_t *request = zmsg_recv (self->pipe);
    char *command = zmsg_popstr (request);
    if (!command)
        return -1;                  //  Interrupted

    if (streq (command, "SET NAME")) {
        free (self->name);
        self->name = zmsg_popstr (request);
        assert (self->name);
    }
    else
    if (streq (command, "SET HEADER")) {
        char *name = zmsg_popstr (request);
        char *value = zmsg_popstr (request);
        zhash_update (self->headers, name, value);
        zstr_free (&name);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET VERBOSE"))
        self->verbose = true;
    else
    if (streq (command, "SET PORT")) {
        char *value = zmsg_popstr (request);
        self->beacon_port = atoi (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "SET INTERVAL")) {
        char *value = zmsg_popstr (request);
        self->interval = atol (value);
        zstr_free (&value);
    }
    else
    if (streq (command, "UUID"))
        zstr_send (self->pipe, zuuid_str (self->uuid));
    else
    if (streq (command, "NAME"))
        zstr_send (self->pipe, self->name);
    else
    if (streq (command, "BIND")) {
        char *endpoint = zmsg_popstr (request);
        zsock_signal (self->pipe, zyre_node_bind (self, endpoint));
        zstr_free (&endpoint);
    }
    else
    if (streq (command, "CONNECT")) {
        char *endpoint = zmsg_popstr (request);
        zsock_signal (self->pipe, zyre_node_connect (self, endpoint));
        zstr_free (&endpoint);
    }
    else
    if (streq (command, "START"))
        zsock_signal (self->pipe, zyre_node_start (self));
    else
    if (streq (command, "STOP"))
        zsock_signal (self->pipe, zyre_node_stop (self));
    else
    if (streq (command, "WHISPER")) {
        //  Get peer to send message to
        char *identity = zmsg_popstr (request);
        zyre_peer_t *peer = (zyre_peer_t *) zhash_lookup (self->peers, identity);
        
        //  Send frame on out to peer's mailbox, drop message
        //  if peer doesn't exist (may have been destroyed)
        if (peer) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_WHISPER);
            zre_msg_set_content (msg, &request);
            zyre_peer_send (peer, &msg);
        }
        zstr_free (&identity);
    }
    else
    if (streq (command, "SHOUT")) {
        //  Get group to send message to
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->peer_groups, name);
        if (group) {
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_SHOUT);
            zre_msg_set_group (msg, name);
            zre_msg_set_content (msg, &request);
            zyre_group_send (group, &msg);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "JOIN")) {
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name);
        if (!group) {
            //  Only send if we're not already in group
            group = zyre_group_new (name, self->own_groups);
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_JOIN);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            zhash_foreach (self->peers, zyre_node_send_peer, msg);
            zre_msg_destroy (&msg);
            if (self->verbose)
                zsys_info ("(%s) JOIN group=%s", self->name, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "LEAVE")) {
        char *name = zmsg_popstr (request);
        zyre_group_t *group = (zyre_group_t *) zhash_lookup (self->own_groups, name);
        if (group) {
            //  Only send if we are actually in group
            zre_msg_t *msg = zre_msg_new (ZRE_MSG_LEAVE);
            zre_msg_set_group (msg, name);
            //  Update status before sending command
            zre_msg_set_status (msg, ++(self->status));
            zhash_foreach (self->peers, zyre_node_send_peer, msg);
            zre_msg_destroy (&msg);
            zhash_delete (self->own_groups, name);
            if (self->verbose)
                zsys_info ("(%s) LEAVE group=%s", self->name, name);
        }
        zstr_free (&name);
    }
    else
    if (streq (command, "DUMP"))
        zyre_node_dump (self);
    else
    if (streq (command, "$TERM"))
        self->terminated = true;
    else {
        zsys_error ("invalid command '%s'\n", command);
        assert (false);
    }
    zstr_free (&command);
    zmsg_destroy (&request);
    return 0;
}
示例#8
0
文件: zre_msg.c 项目: UIKit0/zyre
int
zre_msg_test (bool verbose)
{
    printf (" * zre_msg: ");

    //  @selftest
    //  Simple create/destroy test
    zre_msg_t *self = zre_msg_new (0);
    assert (self);
    zre_msg_destroy (&self);

    //  Create pair of sockets we can send through
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    void *output = zsocket_new (ctx, ZMQ_DEALER);
    assert (output);
    zsocket_bind (output, "inproc://selftest");
    void *input = zsocket_new (ctx, ZMQ_ROUTER);
    assert (input);
    zsocket_connect (input, "inproc://selftest");
    
    //  Encode/send/decode and verify each message type

    self = zre_msg_new (ZRE_MSG_HELLO);
    zre_msg_set_sequence (self, 123);
    zre_msg_set_ipaddress (self, "Life is short but Now lasts for ever");
    zre_msg_set_mailbox (self, 123);
    zre_msg_groups_append (self, "Name: %s", "Brutus");
    zre_msg_groups_append (self, "Age: %d", 43);
    zre_msg_set_status (self, 123);
    zre_msg_headers_insert (self, "Name", "Brutus");
    zre_msg_headers_insert (self, "Age", "%d", 43);
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    assert (streq (zre_msg_ipaddress (self), "Life is short but Now lasts for ever"));
    assert (zre_msg_mailbox (self) == 123);
    assert (zre_msg_groups_size (self) == 2);
    assert (streq (zre_msg_groups_first (self), "Name: Brutus"));
    assert (streq (zre_msg_groups_next (self), "Age: 43"));
    assert (zre_msg_status (self) == 123);
    assert (zre_msg_headers_size (self) == 2);
    assert (streq (zre_msg_headers_string (self, "Name", "?"), "Brutus"));
    assert (zre_msg_headers_number (self, "Age", 0) == 43);
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_WHISPER);
    zre_msg_set_sequence (self, 123);
    zre_msg_set_content (self, zframe_new ("Captcha Diem", 12));
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    assert (zframe_streq (zre_msg_content (self), "Captcha Diem"));
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_SHOUT);
    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zre_msg_set_content (self, zframe_new ("Captcha Diem", 12));
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
    assert (zframe_streq (zre_msg_content (self), "Captcha Diem"));
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_JOIN);
    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zre_msg_set_status (self, 123);
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
    assert (zre_msg_status (self) == 123);
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_LEAVE);
    zre_msg_set_sequence (self, 123);
    zre_msg_set_group (self, "Life is short but Now lasts for ever");
    zre_msg_set_status (self, 123);
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    assert (streq (zre_msg_group (self), "Life is short but Now lasts for ever"));
    assert (zre_msg_status (self) == 123);
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_PING);
    zre_msg_set_sequence (self, 123);
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    zre_msg_destroy (&self);

    self = zre_msg_new (ZRE_MSG_PING_OK);
    zre_msg_set_sequence (self, 123);
    zre_msg_send (&self, output);
    
    self = zre_msg_recv (input);
    assert (self);
    assert (zre_msg_sequence (self) == 123);
    zre_msg_destroy (&self);

    zctx_destroy (&ctx);
    //  @end

    printf ("OK\n");
    return 0;
}