zbeacon(3)
==========

NAME
----
zbeacon - LAN service announcement and discovery

SYNOPSIS
--------
----
//  Create a new beacon on a certain UDP port
CZMQ_EXPORT zbeacon_t *
    zbeacon_new (int port_nbr);
    
//  Destroy a beacon
CZMQ_EXPORT void
    zbeacon_destroy (zbeacon_t **self_p);

//  Return our own IP address as printable string
CZMQ_EXPORT char *
    zbeacon_hostname (zbeacon_t *self);

//  Set broadcast interval in milliseconds (default is 1000 msec)
CZMQ_EXPORT void
    zbeacon_set_interval (zbeacon_t *self, int interval);

//  Filter out any beacon that looks exactly like ours
CZMQ_EXPORT void
    zbeacon_noecho (zbeacon_t *self);

//  Start broadcasting beacon to peers at the specified interval
CZMQ_EXPORT void
    zbeacon_publish (zbeacon_t *self, byte *transmit, size_t size);
    
//  Stop broadcasting beacons
CZMQ_EXPORT void
    zbeacon_silence (zbeacon_t *self);

//  Start listening to other peers; zero-sized filter means get everything
CZMQ_EXPORT void
    zbeacon_subscribe (zbeacon_t *self, byte *filter, size_t size);

//  Stop listening to other peers
CZMQ_EXPORT void
    zbeacon_unsubscribe (zbeacon_t *self);

//  Get beacon pipe, for polling or receiving messages
CZMQ_EXPORT void *
    zbeacon_pipe (zbeacon_t *self);

//  Self test of this class
CZMQ_EXPORT void
    zbeacon_test (bool verbose);
----

DESCRIPTION
-----------

The zbeacon module implements a peer-to-peer discovery service for local
networks. A beacon can broadcast and/or capture service announcements
using UDP messages on the local area network. This implementation uses
IPv4 UDP broadcasts. You can define the format of your outgoing beacons,
and set a filter that validates incoming beacons. Beacons are sent and
received asynchronously in the background. The zbeacon API provides a
incoming beacons on a ZeroMQ socket (the pipe) that you can configure,
poll on, and receive messages on. Incoming beacons are always delivered
as two frames: the ipaddress of the sender (a string), and the beacon
data itself (binary, as published).


EXAMPLE
-------
.From zbeacon_test method
----
    zbeacon_t *node1 = zbeacon_new (5670);
    zbeacon_t *node2 = zbeacon_new (5670);
    zbeacon_t *node3 = zbeacon_new (5670);

    assert (*zbeacon_hostname (node1));
    assert (*zbeacon_hostname (node2));
    assert (*zbeacon_hostname (node3));
    
    zbeacon_set_interval (node1, 250);
    zbeacon_set_interval (node2, 250);
    zbeacon_set_interval (node3, 250);
    zbeacon_noecho (node1);
    zbeacon_publish (node1, (byte *) "NODE/1", 6);
    zbeacon_publish (node2, (byte *) "NODE/2", 6);
    zbeacon_publish (node3, (byte *) "GARBAGE", 7);
    zbeacon_subscribe (node1, (byte *) "NODE", 4);

    //  Poll on API pipe and on UDP socket
    zmq_pollitem_t pollitems [] = {
        { zbeacon_pipe (node1), 0, ZMQ_POLLIN, 0 },
        { zbeacon_pipe (node2), 0, ZMQ_POLLIN, 0 },
        { zbeacon_pipe (node3), 0, ZMQ_POLLIN, 0 }
    };
    uint64_t stop_at = zclock_time () + 1000;
    while (zclock_time () < stop_at) {
        long timeout = (long) (stop_at - zclock_time ());
        if (timeout < 0)
            timeout = 0;
        if (zmq_poll (pollitems, 3, timeout * ZMQ_POLL_MSEC) == -1)
            break;              //  Interrupted

        //  We cannot get messages on nodes 2 and 3
        assert ((pollitems [1].revents & ZMQ_POLLIN) == 0);
        assert ((pollitems [2].revents & ZMQ_POLLIN) == 0);

        //  If we get a message on node 1, it must be NODE/2
        if (pollitems [0].revents & ZMQ_POLLIN) {
            char *ipaddress = zstr_recv (zbeacon_pipe (node1));
            char *beacon = zstr_recv (zbeacon_pipe (node1));
            assert (streq (beacon, "NODE/2"));
            free (ipaddress);
            free (beacon);
        }
    }
    //  Stop listening
    zbeacon_unsubscribe (node1);
    
    //  Stop all node broadcasts
    zbeacon_silence (node1);
    zbeacon_silence (node2);
    zbeacon_silence (node3);

    //  Destroy the test nodes
    zbeacon_destroy (&node1);
    zbeacon_destroy (&node2);
    zbeacon_destroy (&node3);
----

SEE ALSO
--------
linkczmq:czmq[7]
