Zyre - an open-source framework for proximity-based peer-to-peer applications

Overview

GitHub release OBS draft OBS stable license

Zyre - Local Area Clustering for Peer-to-Peer Applications

Linux & MacOSX Windows
Build Status Build status

Contents

Overview

Scope and Goals

Ownership and License

Using Zyre

Building on Linux and macOS

Building on Windows

Building on Windows

Linking with an Application

Use from Other Languages

API Summary

Hints to Contributors

This Document

Overview

Scope and Goals

Zyre provides reliable group messaging over local area networks. It has these key characteristics:

  • Zyre needs no administration or configuration.
  • Peers may join and leave the network at any time.
  • Peers talk to each other without any central brokers or servers.
  • Peers can talk directly to each other.
  • Peers can join groups, and then talk to groups.
  • Zyre is reliable, and loses no messages even when the network is heavily loaded.
  • Zyre is fast and has low latency, requiring no consensus protocols.
  • Zyre is designed for WiFi networks, yet also works well on Ethernet networks.
  • Time for a new peer to join a network is about one second.

Typical use cases for Zyre are:

  • Local service discovery.
  • Clustering of a set of services on the same Ethernet network.
  • Controlling a network of smart devices (Internet of Things).
  • Multi-user mobile applications (like smart classrooms).

Technical details:

  • Uses RFC 36 (http://rfc.zeromq.org/spec:36/ZRE) protocol for discovery and heartbeating.
  • Uses reliable Dealer-Router pattern for interconnection, assuring that messages are not lost unless a peer application terminates.
  • Optimized for WiFi, using UDP broadcasts for discovery and heartbeating…
  • Offers alternative discovery mechanism (gossip) for Ethernet networks.

Ownership and License

The contributors are listed in AUTHORS. This project uses the MPL v2 license, see LICENSE.

Zyre uses the C4.1 (Collective Code Construction Contract) process for contributions.

Zyre uses the CLASS (C Language Style for Scalabilty) guide for code style.

To report an issue, use the Zyre issue tracker at github.com.

Using Zyre

Building on Linux and macOS

To start with, you need at least these packages:

  • git -- git is how we share code with other people.
  • build-essential, libtool, pkg-config - the C compiler and related tools.
  • autotools-dev, autoconf, automake - the GNU autoconf makefile generators.
  • cmake - the CMake makefile generators (an alternative to autoconf).

Plus some others:

  • uuid-dev, libpcre3-dev - utility libraries.
  • valgrind - a useful tool for checking your code.
  • pkg-config - an optional useful tool to make building with dependencies easier.

Which we install like this (using the Debian-style apt-get package manager):

    sudo apt-get update
    sudo apt-get install -y \
    git build-essential libtool \
    pkg-config autotools-dev autoconf automake cmake \
    uuid-dev libpcre3-dev valgrind

    # only execute this next line if interested in updating the man pages as
    # well (adds to build time):
    sudo apt-get install -y asciidoc

Here's how to build Zyre from GitHub (building from packages is very similar, you don't clone a repo but unpack a tarball), including the libsodium (for security) and libzmq (ZeroMQ core) libraries:

    git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
    cd libsodium
    ./autogen.sh && ./configure && make check
    sudo make install
    cd ..

    git clone git://github.com/zeromq/libzmq.git
    cd libzmq
    ./autogen.sh
    # do not specify "--with-libsodium" if you prefer to use internal tweetnacl
    # security implementation (recommended for development)
    ./configure --with-libsodium
    make check
    sudo make install
    sudo ldconfig
    cd ..

    git clone git://github.com/zeromq/czmq.git
    cd czmq
    ./autogen.sh && ./configure && make check
    sudo make install
    sudo ldconfig
    cd ..

    git clone git://github.com/zeromq/zyre.git
    cd zyre
    ./autogen.sh && ./configure && make check
    sudo make install
    sudo ldconfig
    cd ..

Test by running the zyre_selftest command:

zyre\src\.libs\zyre_selftest

Test by running the zpinger command, from two or more PCs.

zyre\src\.libs\zpinger

Building on Windows

To start with, you need MS Visual Studio (C/C++). The free community edition works well.

Then, install git, and make sure it works from a DevStudio command prompt:

git

Now let's build Zyre from GitHub:

    git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
    git clone git://github.com/zeromq/libzmq.git
    git clone git://github.com/zeromq/czmq.git
    git clone git://github.com/zeromq/zyre.git
    cd zyre\builds\msvc
    configure.bat
    cd build
    buildall.bat
    cd ..\..\..\..

Test by running the zyre_selftest command:

    dir/s/b zyre_selftest.exe
    zyre\builds\msvc\vs2013\DebugDEXE\zyre_selftest.exe
    zyre\builds\msvc\vs2013\ReleaseDEXE\zyre_selftest.exe

    :: select your choice and run it
    zyre\builds\msvc\vs2013\DebugDEXE\zyre_selftest.exe

Test by running zpinger from two or more PCs:

    dir/s/b zpinger.exe
    zyre\builds\msvc\vs2013\DebugDEXE\zpinger.exe
    zyre\builds\msvc\vs2013\ReleaseDEXE\zpinger.exe
    zyre\builds\msvc\vs2013\x64\DebugDEXE\zpinger.exe

    :: select your choice and run it
    zyre\builds\msvc\vs2013\ReleaseDEXE\zpinger.exe

Building on Windows

To start with, you need MS Visual Studio (C/C++). The free community edition works well.

Then, install git, and make sure it works from a DevStudio command prompt:

git

Using CMake

zyre requires czmq and libzmq, so we need to build libzmq first. For libzmq, you can optionally use libsodium as the curve encryption library. So we will start from building libsodium in the following (and you can bypass the building of libsodium if you are ok with libzmq's default curve encryption library):

git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
cd libsodium\builds\msvc\build
buildall.bat
cd ..\..\..\..

Once done, you can find the library files under libsodium\bin\<Win32|x64>\<Debug|Release>\<Platform Toolset>\<dynamic|ltcg|static>.

Here, the <Platform Toolset> is the platform toolset you are using: v100 for VS2010, v140 for VS2015, v141 for VS2017, etc.

git clone git://github.com/zeromq/libzmq.git
cd libzmq
mkdir build
cd build
cmake .. -DBUILD_STATIC=OFF -DBUILD_SHARED=ON -DZMQ_BUILD_TESTS=ON -DWITH_LIBSODIUM=ON -DCMAKE_INCLUDE_PATH=..\libsodium\src\libsodium\include -DCMAKE_LIBRARY_PATH=..\libsodium\bin\Win32\Release\<Platform Toolset>\dynamic -DCMAKE_INSTALL_PREFIX=C:\projects\libs
cmake --build . --config Release --target install
cd ..\..\

-DWITH_LIBSODIUM=ON is necessary if you want to build libzmq with libsodium. CMAKE_INCLUDE_PATH option tells libzmq where to search for libsodium's header files. And the CMAKE_LIBRARY_PATH option tells where to search for libsodium library files. If you don't need libsodium support, you can omit these three options.

-DCMAKE_INSTALL_PREFIX=C:\libzmq means we want to install libzmq into the C:\libzmq. You may need to run your shell with administrator privilege in order to write to the system disk.

Next, let's build czmq:

git clone git://github.com/zeromq/czmq.git
cd czmq
mkdir build
cd build
cmake .. -DCZMQ_BUILD_SHARED=ON -DCZMQ_BUILD_STATIC=OFF -DCMAKE_PREFIX_PATH=C:\projects\libs -DCMAKE_INSTALL_PREFIX=C:\projects\libs
cmake --build . --config Release --target install

Remember that we installed libzmq to C:\projects\libs through specifying -DCMAKE_INSTALL_PREFIX in the previous step. We here use -DCMAKE_PREFIX_PATH=C:\projects\libs to tell czmq where to search for libzmq.

That is not the whole story. We didn't mention the building of libcurl, lz4, libuuid and other czmq optional libraries above. In fact, to build all of these optional libraries successfully is really tricky. Please refer issue #1972 for more details.

Now, it is time to build zyre:

git clone git://github.com/zeromq/zyre.git
cd zyre
mkdir build
cd build
cmake .. -DZYRE_BUILD_SHARED=ON -DZYRE_BUILD_STATIC=OFF -DCMAKE_PREFIX_PATH=C:\projects\libs
cmake --build . --config Release
ctest -C Release

Linking with an Application

Include zyre.h in your application and link with libzyre. Here is a typical gcc link command:

gcc myapp.c -lzyre -lczmq -lzmq -o myapp

Use from Other Languages

This is a list of auto-generated bindings:

API Summary

This is the API provided by Zyre 2.x, in alphabetical order.

zyre - API wrapping one Zyre node

Zyre does local area discovery and clustering. A Zyre node broadcasts UDP beacons, and connects to peers that it finds. This class wraps a Zyre node with a message-based API.

All incoming events are zmsg_t messages delivered via the zyre_recv call. The first frame defines the type of the message, and following frames provide further values:

ENTER fromnode name headers ipaddress:port
    a new peer has entered the network
EVASIVE fromnode name
    a peer is being evasive (i.e. quiet) and will be pinged manually
SILENT fromnode name
    a peer has been quiet and has not answered ping after 1 second
EXIT fromnode name
    a peer has left the network
JOIN fromnode name groupname
    a peer has joined a specific group
LEAVE fromnode name groupname
    a peer has joined a specific group
WHISPER fromnode name message
    a peer has sent this node a message
SHOUT fromnode name groupname message
    a peer has sent one of our groups a message

In SHOUT and WHISPER the message is zero or more frames, and can hold any ZeroMQ message. In ENTER, the headers frame contains a packed dictionary, see zhash_pack/unpack.

To join or leave a group, use the zyre_join and zyre_leave methods. To set a header value, use the zyre_set_header method. To send a message to a single peer, use zyre_whisper. To send a message to a group, use zyre_shout.

Todo: allow multipart contents

This is the class interface:

    //  This is a stable class, and may not change except for emergencies. It
    //  is provided in stable builds.
    //  This class has draft methods, which may change over time. They are not
    //  in stable releases, by default. Use --enable-drafts to enable.
    //  Constructor, creates a new Zyre node. Note that until you start the
    //  node it is silent and invisible to other nodes on the network.
    //  The node name is provided to other nodes during discovery. If you
    //  specify NULL, Zyre generates a randomized node name from the UUID.
    ZYRE_EXPORT zyre_t *
        zyre_new (const char *name);
    
    //  Destructor, destroys a Zyre node. When you destroy a node, any
    //  messages it is sending or receiving will be discarded.
    ZYRE_EXPORT void
        zyre_destroy (zyre_t **self_p);
    
    //  Return our node UUID string, after successful initialization
    ZYRE_EXPORT const char *
        zyre_uuid (zyre_t *self);
    
    //  Return our node name, after successful initialization. First 6
    //  characters of UUID by default.
    ZYRE_EXPORT const char *
        zyre_name (zyre_t *self);
    
    //  Set the public name of this node overriding the default. The name is
    //  provide during discovery and come in each ENTER message.
    ZYRE_EXPORT void
        zyre_set_name (zyre_t *self, const char *name);
    
    //  Set node header; these are provided to other nodes during discovery
    //  and come in each ENTER message.
    ZYRE_EXPORT void
        zyre_set_header (zyre_t *self, const char *name, const char *format, ...) CHECK_PRINTF (3);
    
    //  Set verbose mode; this tells the node to log all traffic as well as
    //  all major events.
    ZYRE_EXPORT void
        zyre_set_verbose (zyre_t *self);
    
    //  Set UDP beacon discovery port; defaults to 5670, this call overrides
    //  that so you can create independent clusters on the same network, for
    //  e.g. development vs. production. Has no effect after zyre_start().
    ZYRE_EXPORT void
        zyre_set_port (zyre_t *self, int port_nbr);
    
    //  Set the peer evasiveness timeout, in milliseconds. Default is 5000.
    //  This can be tuned in order to deal with expected network conditions
    //  and the response time expected by the application. This is tied to
    //  the beacon interval and rate of messages received.
    ZYRE_EXPORT void
        zyre_set_evasive_timeout (zyre_t *self, int interval);
    
    //  Set the peer silence timeout, in milliseconds. Default is 5000.
    //  This can be tuned in order to deal with expected network conditions
    //  and the response time expected by the application. This is tied to
    //  the beacon interval and rate of messages received.
    //  Silence is triggered one second after the timeout if peer has not
    //  answered ping and has not sent any message.
    //  NB: this is currently redundant with the evasiveness timeout. Both
    //  affect the same timeout value.
    ZYRE_EXPORT void
        zyre_set_silent_timeout (zyre_t *self, int interval);
    
    //  Set the peer expiration timeout, in milliseconds. Default is 30000.
    //  This can be tuned in order to deal with expected network conditions
    //  and the response time expected by the application. This is tied to
    //  the beacon interval and rate of messages received.
    ZYRE_EXPORT void
        zyre_set_expired_timeout (zyre_t *self, int interval);
    
    //  Set UDP beacon discovery interval, in milliseconds. Default is instant
    //  beacon exploration followed by pinging every 1,000 msecs.
    ZYRE_EXPORT void
        zyre_set_interval (zyre_t *self, size_t interval);
    
    //  Set network interface for UDP beacons. If you do not set this, CZMQ will
    //  choose an interface for you. On boxes with several interfaces you should
    //  specify which one you want to use, or strange things can happen.
    ZYRE_EXPORT void
        zyre_set_interface (zyre_t *self, const char *value);
    
    //  By default, Zyre binds to an ephemeral TCP port and broadcasts the local
    //  host name using UDP beaconing. When you call this method, Zyre will use
    //  gossip discovery instead of UDP beaconing. You MUST set-up the gossip
    //  service separately using zyre_gossip_bind() and _connect(). Note that the
    //  endpoint MUST be valid for both bind and connect operations. You can use
    //  inproc://, ipc://, or tcp:// transports (for tcp://, use an IP address
    //  that is meaningful to remote as well as local nodes). Returns 0 if
    //  the bind was successful, else -1.
    ZYRE_EXPORT int
        zyre_set_endpoint (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
    
    //  Set-up gossip discovery of other nodes. At least one node in the cluster
    //  must bind to a well-known gossip endpoint, so other nodes can connect to
    //  it. Note that gossip endpoints are completely distinct from Zyre node
    //  endpoints, and should not overlap (they can use the same transport).
    ZYRE_EXPORT void
        zyre_gossip_bind (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
    
    //  Set-up gossip discovery of other nodes. A node may connect to multiple
    //  other nodes, for redundancy paths. For details of the gossip network
    //  design, see the CZMQ zgossip class.
    ZYRE_EXPORT void
        zyre_gossip_connect (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
    
    //  Start node, after setting header values. When you start a node it
    //  begins discovery and connection. Returns 0 if OK, -1 if it wasn't
    //  possible to start the node.
    ZYRE_EXPORT int
        zyre_start (zyre_t *self);
    
    //  Stop node; this signals to other peers that this node will go away.
    //  This is polite; however you can also just destroy the node without
    //  stopping it.
    ZYRE_EXPORT void
        zyre_stop (zyre_t *self);
    
    //  Join a named group; after joining a group you can send messages to
    //  the group and all Zyre nodes in that group will receive them.
    ZYRE_EXPORT int
        zyre_join (zyre_t *self, const char *group);
    
    //  Leave a group
    ZYRE_EXPORT int
        zyre_leave (zyre_t *self, const char *group);
    
    //  Receive next message from network; the message may be a control
    //  message (ENTER, EXIT, JOIN, LEAVE) or data (WHISPER, SHOUT).
    //  Returns zmsg_t object, or NULL if interrupted
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zmsg_t *
        zyre_recv (zyre_t *self);
    
    //  Send message to single peer, specified as a UUID string
    //  Destroys message after sending
    ZYRE_EXPORT int
        zyre_whisper (zyre_t *self, const char *peer, zmsg_t **msg_p);
    
    //  Send message to a named group
    //  Destroys message after sending
    ZYRE_EXPORT int
        zyre_shout (zyre_t *self, const char *group, zmsg_t **msg_p);
    
    //  Send formatted string to a single peer specified as UUID string
    ZYRE_EXPORT int
        zyre_whispers (zyre_t *self, const char *peer, const char *format, ...) CHECK_PRINTF (3);
    
    //  Send formatted string to a named group
    ZYRE_EXPORT int
        zyre_shouts (zyre_t *self, const char *group, const char *format, ...) CHECK_PRINTF (3);
    
    //  Return zlist of current peer ids.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zlist_t *
        zyre_peers (zyre_t *self);
    
    //  Return zlist of current peers of this group.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zlist_t *
        zyre_peers_by_group (zyre_t *self, const char *name);
    
    //  Return zlist of currently joined groups.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zlist_t *
        zyre_own_groups (zyre_t *self);
    
    //  Return zlist of groups known through connected peers.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zlist_t *
        zyre_peer_groups (zyre_t *self);
    
    //  Return the endpoint of a connected peer.
    //  Returns empty string if peer does not exist.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT char *
        zyre_peer_address (zyre_t *self, const char *peer);
    
    //  Return the value of a header of a conected peer.
    //  Returns null if peer or key doesn't exits.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT char *
        zyre_peer_header_value (zyre_t *self, const char *peer, const char *name);
    
    //  Return socket for talking to the Zyre node, for polling
    ZYRE_EXPORT zsock_t *
        zyre_socket (zyre_t *self);
    
    //  Print zyre node information to stdout
    ZYRE_EXPORT void
        zyre_print (zyre_t *self);
    
    //  Return the Zyre version for run-time API detection; returns
    //  major * 10000 + minor * 100 + patch, as a single integer.
    ZYRE_EXPORT uint64_t
        zyre_version (void);
    
    //  Self test of this class.
    ZYRE_EXPORT void
        zyre_test (bool verbose);
    
    #ifdef ZYRE_BUILD_DRAFT_API
    //  *** Draft method, for development use, may change without warning ***
    //  Set the TCP port bound by the ROUTER peer-to-peer socket (beacon mode).
    //  Defaults to * (the port is randomly assigned by the system).
    //  This call overrides this, to bypass some firewall issues when ports are
    //  random. Has no effect after zyre_start().
    ZYRE_EXPORT void
        zyre_set_beacon_peer_port (zyre_t *self, int port_nbr);
    
    //  *** Draft method, for development use, may change without warning ***
    //  This options enables a peer to actively contest for leadership in the
    //  given group. If this option is not set the peer will still participate in
    //  elections but never gets elected. This ensures that a consent for a leader
    //  is reached within a group even though not every peer is contesting for
    //  leadership.
    ZYRE_EXPORT void
        zyre_set_contest_in_group (zyre_t *self, const char *group);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Set an alternative endpoint value when using GOSSIP ONLY. This is useful
    //  if you're advertising an endpoint behind a NAT.
    ZYRE_EXPORT void
        zyre_set_advertised_endpoint (zyre_t *self, const char *value);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Apply a azcert to a Zyre node.
    ZYRE_EXPORT void
        zyre_set_zcert (zyre_t *self, zcert_t *zcert);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Specify the ZAP domain (for use with CURVE).
    ZYRE_EXPORT void
        zyre_set_zap_domain (zyre_t *self, const char *domain);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Set-up gossip discovery with CURVE enabled.
    ZYRE_EXPORT void
        zyre_gossip_connect_curve (zyre_t *self, const char *public_key, const char *format, ...) CHECK_PRINTF (3);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Unpublish a GOSSIP node from local list, useful in removing nodes from list when they EXIT
    ZYRE_EXPORT void
        zyre_gossip_unpublish (zyre_t *self, const char *node);
    
    //  *** Draft method, for development use, may change without warning ***
    //  Explicitly connect to a peer
    ZYRE_EXPORT int
        zyre_require_peer (zyre_t *self, const char *uuid, const char *endpoint, const char *public_key);
    
    #endif // ZYRE_BUILD_DRAFT_API

Please add '@interface' section in './../src/zyre.c'.

This is the class self test code:

    //  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
    //  DRAFT-API: Security
    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);
    
        if (verbose) {
            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));
    
        // TODO- set_advertised_endpoint tests
    //        zyre_set_endpoint(node5, "tcp://127.0.0.1:9001");
    //        zyre_set_advertised_endpoint(node5, "tcp://localhost:9001");
    
        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");
    
        rc = zyre_start (node5);
        assert (rc == 0);
    
        rc = zyre_start (node6);
        assert (rc == 0);
    
        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);
        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
    }

zyre_event - no title found

This class provides a higher-level API to the zyre_recv call, by doing work that you will want to do in many cases, such as unpacking the peer headers for each ENTER event received.

Please add '@discuss' section in './../src/zyre_event.c'.

This is the class interface:

    //  This is a stable class, and may not change except for emergencies. It
    //  is provided in stable builds.
    //  Constructor: receive an event from the zyre node, wraps zyre_recv.
    //  The event may be a control message (ENTER, EXIT, JOIN, LEAVE) or
    //  data (WHISPER, SHOUT).
    ZYRE_EXPORT zyre_event_t *
        zyre_event_new (zyre_t *node);
    
    //  Destructor; destroys an event instance
    ZYRE_EXPORT void
        zyre_event_destroy (zyre_event_t **self_p);
    
    //  Returns event type, as printable uppercase string. Choices are:
    //  "ENTER", "EXIT", "JOIN", "LEAVE", "EVASIVE", "WHISPER" and "SHOUT"
    //  and for the local node: "STOP"
    ZYRE_EXPORT const char *
        zyre_event_type (zyre_event_t *self);
    
    //  Return the sending peer's uuid as a string
    ZYRE_EXPORT const char *
        zyre_event_peer_uuid (zyre_event_t *self);
    
    //  Return the sending peer's public name as a string
    ZYRE_EXPORT const char *
        zyre_event_peer_name (zyre_event_t *self);
    
    //  Return the sending peer's ipaddress as a string
    ZYRE_EXPORT const char *
        zyre_event_peer_addr (zyre_event_t *self);
    
    //  Returns the event headers, or NULL if there are none
    ZYRE_EXPORT zhash_t *
        zyre_event_headers (zyre_event_t *self);
    
    //  Returns value of a header from the message headers
    //  obtained by ENTER. Return NULL if no value was found.
    ZYRE_EXPORT const char *
        zyre_event_header (zyre_event_t *self, const char *name);
    
    //  Returns the group name that a SHOUT event was sent to
    ZYRE_EXPORT const char *
        zyre_event_group (zyre_event_t *self);
    
    //  Returns the incoming message payload; the caller can modify the
    //  message but does not own it and should not destroy it.
    ZYRE_EXPORT zmsg_t *
        zyre_event_msg (zyre_event_t *self);
    
    //  Returns the incoming message payload, and pass ownership to the
    //  caller. The caller must destroy the message when finished with it.
    //  After called on the given event, further calls will return NULL.
    //  Caller owns return value and must destroy it when done.
    ZYRE_EXPORT zmsg_t *
        zyre_event_get_msg (zyre_event_t *self);
    
    //  Print event to zsys log
    ZYRE_EXPORT void
        zyre_event_print (zyre_event_t *self);
    
    //  Self test of this class.
    ZYRE_EXPORT void
        zyre_event_test (bool verbose);
    

Please add '@interface' section in './../src/zyre_event.c'.

This is the class self test code:

    //  Create two nodes
    zyre_t *node1 = zyre_new ("node1");
    assert (node1);
    zyre_set_header (node1, "X-HELLO", "World");
    int rc = zyre_set_endpoint (node1, "inproc://zyre-node1");
    assert (rc == 0);
    // use gossiping instead of beaconing, suits Travis better
    zyre_gossip_bind (node1, "inproc://gossip-hub");
    if (verbose)
        zyre_set_verbose (node1);
    if (zyre_start (node1)) {
        zyre_destroy (&node1);
        printf ("OK (skipping test, no UDP discovery)\n");
        return;
    }
    zyre_join (node1, "GLOBAL");
    
    zyre_t *node2 = zyre_new ("node2");
    assert (node2);
    if (verbose)
        zyre_set_verbose (node2);
    rc = zyre_set_endpoint (node2, "inproc://zyre-node2");
    assert (rc == 0);
    // use gossiping instead of beaconing, suits Travis better
    zyre_gossip_connect (node2, "inproc://gossip-hub");
    rc = zyre_start (node2);
    assert (rc == 0);
    zyre_join (node2, "GLOBAL");
    
    //  Give time for them to interconnect
    zclock_sleep (250);
    
    //  One node shouts to GLOBAL
    zmsg_t *msg = zmsg_new ();
    zmsg_addstr (msg, "Hello, World");
    zyre_shout (node1, "GLOBAL", &msg);
    zclock_sleep (100);
    
    //  Parse ENTER
    zyre_event_t *event = zyre_event_new (node2);
    assert (streq (zyre_event_type (event), "ENTER"));
    const char *sender = zyre_event_peer_uuid (event);
    assert (sender);
    const char *name = zyre_event_peer_name (event);
    assert (name);
    assert (streq (name, "node1"));
    const char *address = zyre_event_peer_addr (event);
    assert (address);
    const char *header = zyre_event_header (event, "X-HELLO");
    assert (header);
    zyre_event_destroy (&event);
    
    //  Parse JOIN
    //  We tolerate other events, which we can get if there are instances
    //  of Zyre running somewhere on the network.
    event = zyre_event_new (node2);
    if (streq (zyre_event_type (event), "JOIN")) {
        //  Parse SHOUT
        zyre_event_destroy (&event);
        event = zyre_event_new (node2);
        if (streq (zyre_event_type (event), "SHOUT")) {
            assert (streq (zyre_event_group (event), "GLOBAL"));
            zmsg_t *msg = zyre_event_get_msg (event);
            char *string = zmsg_popstr (msg);
            zmsg_destroy (&msg);
            assert (streq (string, "Hello, World"));
            free (string);
        }
        zyre_event_destroy (&event);
    }
    zyre_destroy (&node1);
    zyre_destroy (&node2);

Hints to Contributors

Zyre is a nice, neat library, and you may not immediately appreciate why. Read the CLASS style guide please, and write your code to make it indistinguishable from the rest of the code in the library. That is the only real criteria for good style: it's invisible.

Don't include system headers in source files. The right place for these is CZMQ.

Do read your code after you write it and ask, "Can I make this simpler?" We do use a nice minimalist and yet readable style. Learn it, adopt it, use it.

Before opening a pull request read our contribution guidelines. Thanks!

This Document

This documentation was generated from zyre/README.txt using Gitdown

Issues
  • Feature: Set port for gossip protocol

    Feature: Set port for gossip protocol

    I would like the ability to set the port for the gossip protocol. I use a firewall on all of my machines. The default ephemeral port means I have to create a new firewall rule, and potentially remove an old firewall rule, to allow the new port every time I start the application. In addition, creating a firewall rule means I have to have escalated root/admin privileges. This is something I would like to avoid if possible.

    Thank you for creating the Zyre protocol.

    opened by aletheia7 38
  • Problem: Zyre still uses LGPL+SLE license

    Problem: Zyre still uses LGPL+SLE license

    Solution: migrate to MPLv2, as explained here http://zeromq.org/area:licensing

    • [x] @twhittock
    • [x] @miniway
    • [x] @sappo
    • [x] @jemc
    • [x] @pijyoi
    • [x] @jossgray
    • [x] @mditzel
    • [x] @vperron
    • [x] @cekoski
    • [x] @m-marsella
    • [x] @moteus
    • [x] @keent
    • [x] @badbug0101
    • [x] @mvala
    • [x] @l00mi
    • [x] @c-rack
    • [x] @sphaero
    • [x] @codebrainz
    • [x] @stephen-wolf
    • [x] @shancat

    Could you kindly reply "I hereby agree to publish my contributions to Zyre under the MPLv2 license"?

    If you have any objection to relicensing your contributions, let me know the reasons. Thanks!

    opened by hintjens 32
  • selftest hangs

    selftest hangs

    I have installed LibZMQ 4.0.4 and latest (from git) CMZQ and Zyre. LibZMQ and CMZQ passes self-tests, but zyre_selftest just hangs (see below).

    Running self tests...

    • zyre_log: OK
    • zyre_peer: OK
    • zre_msg: OK
    • zre_log_msg: OK
    • zyre_group: OK
    • zyre_node: OK

    ^C

    opened by arthepsy 27
  • Build Zyre with ndk r19c

    Build Zyre with ndk r19c

    How should I build Zyre for the newer version of ndk? I get the following error:

    Android build failed for the following reasons: The CPP binary does not exist or is not executable /home/raphael/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-cpp The CC binary does not exist or is not executable /home/raphael/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc The CXX binary does not exist or is not executable /home/raphael/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++

    How should I replace these files?

    stale 
    opened by raphaelcfernandes 21
  • zyre example hangs

    zyre example hangs

    Hi All,

    i am running latest zmq,czmq,zyre and i wanted to try example. I found out that it hangs. Am i doing something wrong?

    Here is source and part where it hangs "// ***** HANGS here ***"

    zctx_t *ctx = zctx_new(); // Create two nodes zyre_t *node1 = zyre_new(ctx); zyre_t *node2 = zyre_new(ctx); zyre_set_header(node1, "X-FILEMQ", "tcp://128.0.0.1:6777"); zyre_set_header(node1, "X-HELLO", "World"); zyre_start(node1); zyre_start(node2); zyre_join(node1, "GLOBAL"); zyre_join(node2, "GLOBAL");

    // Give time for them to interconnect zclock_sleep(250);

    // One node shouts to GLOBAL zmsg_t *msg = zmsg_new(); zmsg_addstr(msg, "Hello, World"); zyre_shout(node1, "GLOBAL", &msg);

    // Parse ENTER // ***** HANGS here *** zyre_event_t *zyre_event = zyre_event_recv(node2);

    What am i doing wrong?

    Ciao

    Martin

    opened by mvala 19
  • Problem : #642 ping forces a false EVASIVE event

    Problem : #642 ping forces a false EVASIVE event

    Every five seconds, the test on evasive timeout in zyre_node.c/zyre_node_ping_peer is always true because no ping is sent when zyre_node_ping_peer is called and there is no evasive timeout. And no other mechanism sends pings.

    Solution : make zyre_node_ping_peer send ping every time it is called, including when evasive timeout is reached (but not when expired timeout is reached, i.e. when peer is removed).

    opened by stvales 18
  • Unable to run zyre_event self test on Windows

    Unable to run zyre_event self test on Windows

    Self-test does not complete on Windows, due to error WSAEADDRNOTAVAIL during interconnect. The endpoint appears to be tcp://0.0.0.0:49156 which seems invalid. This appears to be a race condition, as delaying for 5 seconds between ::connect calls in tcp_connecter_t::open allows the test to interconnect using the correct ip address (but, a separate issue, the test then fails to complete due to the "Parse SHOUT" event_new call entering an infinite loop)

    libzmq.dll!zmq::zmq_abort(const char * errmsg_) Line 71 C++
    libzmq.dll!zmq::tcp_connecter_t::connect() Line 314 C++
    libzmq.dll!zmq::tcp_connecter_t::out_event() Line 116   C++
    libzmq.dll!zmq::tcp_connecter_t::in_event() Line 108    C++
    libzmq.dll!zmq::select_t::loop() Line 190   C++
    libzmq.dll!zmq::select_t::worker_routine(void * arg_) Line 213  C++
    libzmq.dll!thread_routine(void * arg_) Line 35  C++
    
    opened by twhittock 18
  • zpoller and zyre_sock problem

    zpoller and zyre_sock problem

    I have simple code

    #include <zyre.h>
    int main (int argc, char *argv[])
    {
    
        zyre_t *node1 = zyre_new ();
        zyre_t *node2 = zyre_new ();
        zyre_start (node1);
        zyre_start (node2);
    
        zclock_log("%p", (void *) zyre_socket(node1));
    
        zpoller_t *poller = zpoller_new (zyre_socket(node1),  NULL);
        void *whichx = zpoller_wait (poller, -1);
        zclock_log("%p", (void *) whichx);
    
        zyre_stop (node1);
        zyre_stop (node2);
    
        zyre_destroy (&node1);
        zyre_destroy (&node2);
    
        return 0;
    }
    

    Before i had output [email protected] bugs $ ./a.out 14-05-24 22:06:34 0x1cd9bb0 14-05-24 22:06:34 0x1cd9bb0

    now it hangs

    [email protected] bugs $ ./a.out 14-05-24 22:09:44 0x100e170 ^CINTERRUPTED 14-05-24 22:09:46 (nil)

    Probably some recent changes in czmq with zsock and zpoller zyre_sock is returning-> zsock_resolve (self->actor);

    opened by mvala 18
  • Will there be another Zyre release?

    Will there be another Zyre release?

    Hi,

    We are looking at using Zyre in a new project. But we are wondering, why there are no new releases? and if there is intention for new releases in the future?

    Thanks Hasan

    opened by hasan-igl 16
  • building android version not working

    building android version not working

    Hello I tried to build android version for both master or tag v2.0.0 and really it is a miss, a lot of mistakes are made, for example you fixed checking specific versions of android of the toolchain and specific android version, you must test the installation in fresh computer and update the READ.ME:

    for example: local CPP="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-cpp" local CC="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-gcc" local CXX="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-g++" local LD="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ld" local AS="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-as" local AR="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ar" local RANLIB="${TOOLCHAIN_PATH}/${TOOLCHAIN_HOST}-ranlib"

    Those files does not exist any more in the toolchain, in many other place you hardcodes for example those path: android-ndk-r21d/platforms/android-8, android-ndk-r21d/platforms/android-9 , android-ndk-r21d/platforms/android-14. But those folder doe not exist any more.

    It is really a miss I wast 3 days to build the android ndk lib without success.

    stale 
    opened by mrabbah 14
  • zpinger / zyre chat example does not work on Odroid

    zpinger / zyre chat example does not work on Odroid

    Does any of you tried out Zyre on Odroids/ARM running Ubuntu? We are noticing strange things on our current setup of 2 Odroids/ARM and 1 laptop/i386

    The Odroids broadcast on their wlan0 interface and this is received by the laptop and connections are made, and vice versa the laptop's beacons are received by the Odroids. However, there is no connection established between the Odroids themselves...

    At application level this translates to receiving 2 ENTERs at the laptop (from the 2 Odroids) but only receiving 1 ENTER at each Odroid (from the laptop).

    To narrow down the issue we are running the chat example from the zyre source and have checked out the same master branch on all 3 devices.

    Another peculiar thing is that if we run netstat -lu on the laptop we see the broadcast udp with an empty Recv-Q, but on the Odroids this Recv-Q grows a 1000 bytes per second and keeps growing until it reaches 16k which is probably the allocated space...

    Help is very much appreciated!

    opened by maccradar 14
  • endpoints fail to reconnect after wifi reconnection

    endpoints fail to reconnect after wifi reconnection

    Using ZYRE on android phones with the latest build from the releases. Its working great except after the wifi connection drops and reconnects. It seems that the remote connection does not know that the connection was lost??? also worth noting, the name of the node is lost. It was set to the last four of the device serial. Any help or workarounds appreciated. Would zmq heartbeats help? Not quite sure how to enable and test. Any help or workarounds appreciated.

    PHONE 1 Log (this one lost wifi for ~5 seconds)

    zbeacon: failed to transmit, attempting reconnection. reason=invalid socket 03-02 17:54:18.551 18686 19027 D zsys : zbeacon: failed to transmit, attempting reconnection. reason=invalid socket 03-02 17:54:19.563 18686 19027 D zsys : zbeacon: failed to transmit, attempting reconnection. reason=invalid socket 03-02 17:54:20.565 18686 19027 D zsys : zbeacon: failed to transmit, attempting reconnection. reason=invalid socket 03-02 17:54:20.565 18686 19027 I zsys : zbeacon: interface=wlan0 address=10.9.8.122 broadcast=10.9.8.255 03-02 17:54:20.566 18686 19027 I zsys : zbeacon: configured, hostname=10.9.8.122 03-02 17:54:21.125 18686 19026 I zsys : (N42B) connect to peer: endpoint=tcp://10.9.8.127:49152 03-02 17:54:21.125 18686 19026 I zsys : (N42B) send HELLO to peer=- sequence=1 03-02 17:54:27.032 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:27.032 18686 19026 I zsys : (N42B) send PING to peer=- sequence=2 03-02 17:54:27.033 18686 19011 I zsys : zyre_event: 03-02 17:54:27.033 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:27.033 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:27.033 18686 19011 I zsys : zyre_event: 03-02 17:54:27.033 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:27.033 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:28.033 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:28.033 18686 19026 I zsys : (N42B) send PING to peer=- sequence=3 03-02 17:54:28.034 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:28.034 18686 19011 I zsys : zyre_event: 03-02 17:54:28.034 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:28.034 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:28.034 18686 19011 I zsys : zyre_event: 03-02 17:54:28.034 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:28.034 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:28.034 18686 19011 I zsys : zyre_event: 03-02 17:54:28.034 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:28.034 18686 19011 I zsys : - type=SILENT 03-02 17:54:28.034 18686 19011 I zsys : zyre_event: 03-02 17:54:28.034 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:28.035 18686 19011 I zsys : - type=SILENT 03-02 17:54:29.034 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:29.035 18686 19026 I zsys : (N42B) send PING to peer=- sequence=4 03-02 17:54:29.035 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:29.035 18686 19011 I zsys : zyre_event: 03-02 17:54:29.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:29.035 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:29.035 18686 19011 I zsys : zyre_event: 03-02 17:54:29.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:29.035 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:29.035 18686 19011 I zsys : zyre_event: 03-02 17:54:29.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:29.035 18686 19011 I zsys : - type=SILENT 03-02 17:54:29.035 18686 19011 I zsys : zyre_event: 03-02 17:54:29.036 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:29.036 18686 19011 I zsys : - type=SILENT 03-02 17:54:30.035 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:30.035 18686 19026 I zsys : (N42B) send PING to peer=- sequence=5 03-02 17:54:30.035 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:30.035 18686 19011 I zsys : zyre_event: 03-02 17:54:30.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:30.035 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:30.035 18686 19011 I zsys : zyre_event: 03-02 17:54:30.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:30.035 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:30.035 18686 19011 I zsys : zyre_event: 03-02 17:54:30.035 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:30.036 18686 19011 I zsys : - type=SILENT 03-02 17:54:30.036 18686 19011 I zsys : zyre_event: 03-02 17:54:30.036 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:30.036 18686 19011 I zsys : - type=SILENT 03-02 17:54:31.035 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:31.036 18686 19026 I zsys : (N42B) send PING to peer=- sequence=6 03-02 17:54:31.036 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:31.036 18686 19011 I zsys : zyre_event: 03-02 17:54:31.036 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:31.036 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:31.036 18686 19011 I zsys : zyre_event: 03-02 17:54:31.037 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:31.037 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:31.037 18686 19011 I zsys : zyre_event: 03-02 17:54:31.037 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:31.037 18686 19011 I zsys : - type=SILENT 03-02 17:54:31.037 18686 19011 I zsys : zyre_event: 03-02 17:54:31.037 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:31.037 18686 19011 I zsys : - type=SILENT 03-02 17:54:32.036 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:32.037 18686 19026 I zsys : (N42B) send PING to peer=- sequence=7 03-02 17:54:32.037 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:32.037 18686 19011 I zsys : zyre_event: 03-02 17:54:32.037 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:32.037 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:32.037 18686 19011 I zsys : zyre_event: 03-02 17:54:32.037 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:32.037 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:32.038 18686 19011 I zsys : zyre_event: 03-02 17:54:32.038 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:32.038 18686 19011 I zsys : - type=SILENT 03-02 17:54:32.038 18686 19011 I zsys : zyre_event: 03-02 17:54:32.038 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:32.038 18686 19011 I zsys : - type=SILENT 03-02 17:54:33.037 18686 19026 I zsys : (N42B) peer does not send messages (evasive) name= endpoint=tcp://10.9.8.127:49152 03-02 17:54:33.037 18686 19026 I zsys : (N42B) send PING to peer=- sequence=8 03-02 17:54:33.038 18686 19026 I zsys : (N42B) peer '' has not answered ping after 1000 milliseconds (silent) 03-02 17:54:33.040 18686 19011 I zsys : zyre_event: 03-02 17:54:33.040 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:33.040 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:33.040 18686 19011 I zsys : zyre_event: 03-02 17:54:33.040 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:33.040 18686 19011 I zsys : - type=EVASIVE 03-02 17:54:33.041 18686 19011 I zsys : zyre_event: 03-02 17:54:33.041 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:33.041 18686 19011 I zsys : - type=SILENT 03-02 17:54:33.041 18686 19011 I zsys : zyre_event: 03-02 17:54:33.041 18686 19011 I zsys : - from name= uuid=577D94087B82870C6B04C71AB95361D2 03-02 17:54:33.041 18686 19011 I zsys : - type=SILENT

    PHONE 2 Log

    03-02 17:54:26.405 32503 4106 I zsys : (YK7R) peer does not send messages (evasive) name=N42B endpoint=tcp://10.9.8.122:49152 03-02 17:54:26.405 32503 4106 I zsys : (YK7R) send PING to peer=N42B sequence=2 03-02 17:54:26.405 32503 4105 I zsys : zyre_event: 03-02 17:54:26.406 32503 4105 I zsys : - from name=N42B uuid=97B49BCFFD337455082C93B2A4F71099 03-02 17:54:26.406 32503 4105 I zsys : - type=EVASIVE 03-02 17:54:26.406 32503 4105 I zsys : zyre_event: 03-02 17:54:26.406 32503 4105 I zsys : - from name=N42B uuid=97B49BCFFD337455082C93B2A4F71099 03-02 17:54:26.406 32503 4105 I zsys : - type=EVASIVE 03-02 17:54:26.984 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=2 03-02 17:54:26.984 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=3 03-02 17:54:27.985 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=3 03-02 17:54:27.986 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=4 03-02 17:54:29.756 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=4 03-02 17:54:29.756 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=5 03-02 17:54:30.105 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=5 03-02 17:54:30.105 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=6 03-02 17:54:30.987 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=6 03-02 17:54:30.987 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=7 03-02 17:54:31.993 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=7 03-02 17:54:31.993 32503 4106 I zsys : (YK7R) send PING_OK to peer=N42B sequence=8 03-02 17:54:33.014 32503 4106 I zsys : (YK7R) recv PING from peer=N42B sequence=8

    opened by snyderra 3
  • Memory usage increases first 30-40 minutes

    Memory usage increases first 30-40 minutes

    Hi,

    I am running some simple resource tests. For example, I start 20 nodes and monitor memory usage. Right after startup, it uses about 35Mb. It then gradually increases until it reaches its max at 64Mb after about 40 minutes, where it seems to stop increasing.

    It doesn't matter whether I publish messages or not during this period. I have tried to tune zsys pipe limits, max message size, beaconing interval, evasive/expiration timeout, but still the same.

    I am on a memory-constrained device and would like to keep the consumption as low as possible.

    Anyone know why this is, and if it can be tuned?

    I can see the same using the perf_remote test included in the Zyre lib:

    zyre/src/perf_remote

    Monitor the memory, and get:

    zyre_perf_remote_memory

    Best regards, Stian

    opened by stianang 1
  • Network discovery

    Network discovery

    Hi all,

    I was just reading https://zguide.zeromq.org/docs/chapter8/ and saw the Harmony pattern, then got on to http://randalh.blogspot.com/2012/12/zeromq-true-peer-connectivity-harmony.html?m=1 which mentions Zyre. Hence ending up here :-)

    I'm currently exploring the sharing of data p2p for https://github.com/ghenry/SentryPeer and wanted to use 0mq for handling this at the application layer, not via replicated storage like rqlite (https://github.com/rqlite/rqlite). Are there any example use cases for Zyre, but with some kind of tracker? I'm really, really trying to not have any centralised systems.

    Thanks, Gavin.

    opened by ghenry 19
  • Problem with multiple IP address interfaces

    Problem with multiple IP address interfaces

    My application is a GO application, unning on a Linux/arm box. It uses the GOZYRE layer (for the full context).

    Initialization is like :

    	...
    	myIp := findMyIp() // returns "192.168.57.92" in the following
    	node :=	gozyre.New("myBox", myIp, 0, headers, false)
    	node.SetBeaconPeerPort(49374)
    	node.Start()
    	...
    

    GO to C is rather straightforward and does not seem to bring special things. Basically, it would look like:

    	node = zyre_new("myBox");
    	zyre_set_header(node, xxx, yyy);
    	zyre_set_interface(node, "192.168.57.92");
    	zyre_set_beacon_peer_port(49374);
    	...
    

    All is fine for years ;-)

    Now, I add another IP on the same unique interface:

    	[[email protected] ~]$ ifconfig eth0:1
    	eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    	        inet 192.168.1.201  netmask 255.255.255.0  broadcast 192.168.1.255
    	        ether b8:27:eb:9a:38:ce  txqueuelen 1000  (Ethernet)
    	[[email protected] ~]$ 
    

    Then, when the application is (re-)started, the other nodes in the network are confused. They show continuous Enter/.../Exit for this particular node.

    Using TCPDUMP, I see the following:

    • broadcast is performed on 192.168.57.255: ok.
    • source address of TCP connection is set to 192.168.57.92: ok.
    • content of the TCP flow shows tcp://192.168.1.201:49374 !! This requests other nodes to contact my Box on its wrong address.

    If one specifies the interface address with zyre_set_interface(), the same address should be used to identify the TCP connection, no ?

    Did I miss anything ? Did I miss a call to something special ? Or further investigations would be of interest ?

    opened by stephan57160 6
Releases(v2.0.1)
  • v2.0.1(Jan 24, 2021)

    Zyre version 2.0.1 stable, released on 2021/01/22

    • New features in DRAFT state

      • Leader election, allows to elect a group leader between participating peers
    • The following new APIs have been added to the Zyre class:

      • zyre_set_silent_timeout (zyre_t *self, int interval)
    • The following new DRAFT APIs have been added to the Zyre class:

      • zyre_set_beacon_peer_port (zyre_t *self, int port_nbr)
      • zyre_set_contest_in_group (zyre_t *self, const char *group)
      • zyre_set_advertised_endpoint (zyre_t *self, const char *group)
      • zyre_set_zcert (zyre_t *self, zcert_t *zcert_t)
      • zyre_set_zap_domain (zyre_t *self, const char *domain)
      • zyre_gossip_connect_curve (zyre_t *self, const)
      • zyre_gossip_unpublish (zyre_t *self, const char *node)
      • zyre_require_peer (zyre_t *self, const char *uuid, const char *endpoint, const char *public_key)
      • zyre_socket_zmq (zyre_t *self)
    • The following new DRAFT symbols have been added:

      • #define ZAP_DOMAIN_DEFAULT "global" # Default ZAP domain (auth)
    • Many bug fixes. See git log on https://github.com/zeromq/zyre/commits/master for more information.

    Source code(tar.gz)
    Source code(zip)
    MD5SUMS(101 bytes)
    SHA1SUMS(117 bytes)
    zyre-2.0.1.tar.gz(4.85 MB)
    zyre-2.0.1.zip(4.98 MB)
    zyre-android-all-2.0.1.jar(9.63 MB)
    zyre-android-arm64-v8a-2.0.1.jar(2.51 MB)
    zyre-android-armeabi-v7a-2.0.1.jar(2.17 MB)
    zyre-android-x86-2.0.1.jar(5.00 MB)
    zyre-android-x86_64-2.0.1.jar(2.59 MB)
  • v2.0.0(Jan 20, 2017)

    Zyre version 2.0.0 stable, released on 2017/01/20

    • v2.0.0 breaks API and ABI compatibility with the previous version. The ABI SONAME version has been bumped to 2.

    • The current zyre and zyre_event APIs have been declared STABLE, and will no longer change in an backward-incompatible way until they are DEPRECATED and then RETIRED.

    • The following backward-incompatbile changes have been made to the previously DRAFT APIs:

      • old: void zyre_version (int* major, int* minor, int* patch)

        new: uint64_t zyre_version (void)

      • old: zyre_event_type_t zyre_event_type (zyre_event_t *self)

        new: const char *zyre_event_type (zyre_event_t *self)

      The following symbols have been removed:

      • zyre_set_endpoint ( zyre_t* self, char const* format, ... )
      • zyre_shouts ( zyre_t* self, char const* group, char const* format, ... )
      • zyre_whispers ( zyre_t* self, char const* peer, char const* format, ... )
      • enum zyre_event_type_t
    • The ZRE MSG class is now private and its symbols are no longer exported.

    • The following new APIs have been added to the Zyre class:

      • zyre_set_evasive_timeout
      • zyre_set_expired_timeout
      • zyre_peers_by_group

      See doc/zyre.txt for more information.

    • The following new APIs have been added to the Zyre Event class:

      • zyre_event_get_msg

      See doc/zyre_event.txt for more information.

    • The zpinger program has a new option: -6/--ipv6, runs over IPv6. NOTE: needs support from CZMQ, will work only if Zbeacon supports IPv6.

    • The examples/chat program is now building again.

    • Many bug fixes. See git log on https://github.com/zeromq/zyre/commits/master for more information.

    Source code(tar.gz)
    Source code(zip)
    MD5SUMS(101 bytes)
    SHA1SUMS(117 bytes)
    zyre-2.0.0.tar.gz(400.31 KB)
    zyre-2.0.0.zip(435.31 KB)
    zyre-android-2.0.0.jar(2.39 MB)
  • v0.0.4(Feb 10, 2016)

Owner
The ZeroMQ project
The ZeroMQ project
C++ peer to peer library, built on the top of boost

Breep What is Breep? Breep is a c++ bridged peer to peer library. What does that mean? It means that even though the network is constructed as a peer

Lucas Lazare 110 Jun 16, 2022
Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration.

Husarnet Client Husarnet is a Peer-to-Peer VPN to connect your laptops, servers and microcontrollers over the Internet with zero configuration. Key fe

Husarnet 128 Jun 19, 2022
QuantumGate is a peer-to-peer (P2P) communications protocol, library and API written in C++.

About QuantumGate is a peer-to-peer (P2P) communications protocol, library and API. The long-term goal for QuantumGate is to become a platform for dis

Karel Donk 82 May 28, 2022
Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications.

Restbed Restbed is a comprehensive and consistent programming model for building applications that require seamless and secure communication over HTTP

Corvusoft 1.7k Jun 21, 2022
Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications.

Restbed Restbed is a comprehensive and consistent programming model for building applications that require seamless and secure communication over HTTP

Corvusoft 1.4k Mar 8, 2021
OtterCastAmp is an open-source WiFi Speaker amplifier, based on a Sochip S3 SoC. Powered by any USB PD adapter for up to 100W of music.

OtterCastAmp is an open-source WiFi Speaker amplifier, based on a Sochip S3 SoC. Powered by any USB PD adapter for up to 100W of music.

Ottercast 244 May 25, 2022
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 692 Jun 3, 2022
A WiFi-enabled microcontroller capable of communicating with web-based service APIs for fast prototyping applications.

A WiFi-enabled microcontroller capable of communicating with web-based service APIs for fast prototyping applications.

Mark Hofmeister 2 Mar 9, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Jun 20, 2022
An easy to use and powerful open source websocket library written in C.

libwebsock Easy to use C library for websockets This library allows for quick and easy development of applications that use the websocket protocol, wi

Jonathan Hall 46 May 4, 2022
RakNet is a cross platform, open source, C++ networking engine for game programmers.

RakNet 4.081 Copyright (c) 2014, Oculus VR, Inc. Package notes The Help directory contains index.html, which is full help documentation in HTML format

Facebook Archive 3.1k Jun 27, 2022
Open Source IoT Operating System

IoTaaP OS Open Source IoT Operating System Usage Include IoTaaP_OS.h to your project and define IoTaaP OS object Usage example #include <IoTaaP_OS.h>

IoTaaP 38 Nov 23, 2021
ASN intelligence information (IP to ASN mapping) collected and distributed in open source and transparent way

ASN Intelligence The main goal of this project to retrieve information required to map IP address to ASN number in open source and transparent way. Wh

Pavel Odintsov 60 Jun 27, 2021
Open source file system for small embedded systems

STORfs Open Source File System Release Version 1.0.2 Created by: KrauseGLOBAL Solutions, LLC What is STORfs? STORfs is an open source flash file syste

null 16 Apr 23, 2022
STUNTMAN - An open source STUN server

Version 1.2. This is the source code to STUNTMAN - an open source STUN server and client code by john selbie. Compliant with the latest RFCs including 5389, 5769, and 5780. Also includes backwards compatibility for RFC 3489. Compiles on Linux, MacOS, BSD, Solaris, and Win32 with Cygwin. Windows binaries avaialble from www.stunprotocol.org.

John Selbie 1.1k Jun 15, 2022
Eclipse Mosquitto - An open source MQTT broker

Mosquitto is an open source implementation of a server for version 5.0, 3.1.1, and 3.1 of the MQTT protocol. It also includes a C and C++ client library, and the mosquitto_pub and mosquitto_sub utilities for publishing and subscribing.

Eclipse Foundation 6.4k Jun 27, 2022
A virtual network Differential GNSS server-client project using Precise Point Positioning (PPP). Global coverage. Without physical base station construction needed. An open-source virtual base station approach.

Virtual-Network-DGNSS-Project This project is the software implementation for a publicly available, open-source, client/server VN-DGNSS implementation

null 10 May 20, 2022
rdesktop is an open source client for Microsoft's RDP protocol

?? rdesktop is in need of a new maintainter. Please see the home page for more details. ??

null 1.1k Jun 20, 2022
Open source SDR 4G/5G software suite from Software Radio Systems (SRS)

Open source SDR 4G/5G software suite from Software Radio Systems (SRS)

srsRAN 2.7k Jun 29, 2022