Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here

czmq

High-level C binding for ØMQ

Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star half bd79095782ee4930099175e5ce7f4c89fa3ddabcd56fffcc7c74f6f2a2d46b27 (1 ratings)
Rated 4.5 out of 5
Subscribe to updates I use czmq


Statistics on czmq

Number of watchers on Github 658
Number of open issues 56
Average time to close an issue 10 days
Main language C
Average time to merge a PR about 3 hours
Open pull requests 4+
Closed pull requests 11+
Last commit over 1 year ago
Repo Created over 8 years ago
Repo Last Updated over 1 year ago
Size 12.4 MB
Homepage czmq.zeromq.org
Organization / Authorzeromq
Latest Releasev4.1.0
Contributors112
Page Updated
Do you use czmq? Leave a review!
View open issues (56)
View czmq activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating czmq for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

GitHub release OBS draft OBS stable license

CZMQ - High-level C binding for MQ

Linux & MacOSX Windows
Build Status Build status

Contents

Overview

Scope and Goals

Ownership and License

Using CZMQ

Building and Installing

Building on Windows

Linking with an Application

Use from Other Languages

API v3 Summary

Error Handling

CZMQ Actors

Under the Hood

Adding a New Class

Documentation

Development

Porting CZMQ

Hints to Contributors

Code Generation

This Document

Overview

Scope and Goals

CZMQ has these goals:

  • To wrap the MQ core API in semantics that lead to shorter, more readable applications.
  • To hide as far as possible the differences between different versions of MQ (2.x, 3.x, 4.x).
  • To provide a space for development of more sophisticated API semantics.
  • To wrap the MQ security features with high-level tools and APIs.
  • To become the basis for other language bindings built on top of CZMQ.

CZMQ grew out of concepts developed in MQ - The Guide.

1

Ownership and License

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

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

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

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

Using CZMQ

Building and Installing

To start with, you need at least these packages:

  • {{git-all}} -- 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-all 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 CZMQ from GitHub (building from packages is very similar, you don't clone a repo but unpack a tarball), including the libzmq (ZeroMQ core) library (NOTE: skip ldconfig on OSX):

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 ..

In general CZMQ works best with the latest libzmq master. If you already have an older version of libzmq installed on your system, e.g. in /usr/, then you can install libzmq master to your home directory ($HOME/local):

#   Building libzmq in our home directory
./configure --prefix=$HOME/local

And then to build CZMQ against this installation of libzmq:

export CFLAGS=-I$HOME/local/include
export LDFLAGS=-L$HOME/local/lib64
export PKG_CONFIG_PATH=$HOME/local/lib64/pkgconfig
./configure

NOTE: the PKG_CONFIG_PATH is not mandatory, and the actual directory might be different. If you cannot or do not want to use pkg-config, please make sure to MANUALLY add all the necessary CFLAGS and LDFLAGS from all dependencies (for example -DZMQ_BUILD_DRAFT_API=1 if you want the DRAFT APIs).

You will need the pkg-config, libtool, and autoreconf packages. After building, run the CZMQ selftests:

make check

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 CZMQ from GitHub:

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

    :: if libsodium is on disk, the Windows build of libzmq will automatically use it
    git clone git://github.com/zeromq/libzmq.git
    cd libzmq\builds\msvc
    configure.bat
    cd build
    buildall.bat
    cd ..\..\..\..

    git clone git://github.com/zeromq/czmq.git
    cd czmq\builds\msvc
    configure.bat
    cd build
    buildall.bat
    cd ..\..\..\..

Let's test by running czmq_selftest:

   czmq>dir/s/b czmq_selftest.exe
   czmq\builds\msvc\vs2013\DebugDEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\DebugLEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\DebugSEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\ReleaseDEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\ReleaseLEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\ReleaseSEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\DebugDEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\DebugLEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\DebugSEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\ReleaseDEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\ReleaseLEXE\czmq_selftest.exe
   czmq\builds\msvc\vs2013\x64\ReleaseSEXE\czmq_selftest.exe

    :: select your choice and run it
    czmq\builds\msvc\vs2013\x64\ReleaseDEXE\czmq_selftest.exe

Linking with an Application

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

gcc myapp.c -o myapp -lczmq -lzmq

Use from Other Languages

This is a list of auto-generated bindings:

  • https://github.com/zeromq/czmq/tree/master/bindings/jni - Java
  • https://github.com/zeromq/czmq/tree/master/bindings/nodejs - NodeJS
  • https://github.com/zeromq/czmq/tree/master/bindings/python - Python
  • https://github.com/zeromq/czmq/tree/master/bindings/python_cffi - Python (cffi)
  • https://github.com/zeromq/czmq/tree/master/bindings/qml - QML
  • https://github.com/zeromq/czmq/tree/master/bindings/qt - Qt
  • https://github.com/zeromq/czmq/tree/master/bindings/ruby - Ruby (FFI)

This is a list of known higher-level wrappers around CZMQ:

  • https://github.com/1100110/CZMQ - D bindings
  • https://github.com/methodmissing/rbczmq - Ruby
  • https://github.com/paddor/cztop - Ruby, based on generated FFI binding
  • https://github.com/zeromq/pyczmq - Python
  • https://github.com/lhope/cl-czmq - Common Lisp
  • https://github.com/fmp88/ocaml-czmq - Ocaml
  • https://github.com/gar1t/erlang-czmq - Erlang
  • https://github.com/mtortonesi/ruby-czmq-ffi - Ruby FFI
  • https://github.com/zeromq/goczmq - Go

API v3 Summary

This is the API provided by CZMQ v3.x, in alphabetical order.

zactor - simple actor framework

The zactor class provides a simple actor framework. It replaces the CZMQ zthread class, which had a complex API that did not fit the CLASS standard. A CZMQ actor is implemented as a thread plus a PAIR-PAIR pipe. The constructor and destructor are always synchronized, so the caller can be sure all resources are created, and destroyed, when these calls complete. (This solves a major problem with zthread, that a caller could not be sure when a child thread had finished.)

A zactor_t instance acts like a zsock_t and you can pass it to any CZMQ method that would take a zsock_t argument, including methods in zframe, zmsg, zstr, and zpoller. (zloop somehow escaped and needs catching.)

An actor function MUST call zsock_signal (pipe) when initialized and MUST listen to pipe and exit on $TERM command.

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

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.
    // Actors get a pipe and arguments from caller
    typedef void (zactor_fn) (
        zsock_t *pipe, void *args);

    //  Create a new actor passing arbitrary arguments reference.
    CZMQ_EXPORT zactor_t *
        zactor_new (zactor_fn task, void *args);

    //  Destroy an actor.
    CZMQ_EXPORT void
        zactor_destroy (zactor_t **self_p);

    //  Send a zmsg message to the actor, take ownership of the message
    //  and destroy when it has been sent.                             
    CZMQ_EXPORT int
        zactor_send (zactor_t *self, zmsg_t **msg_p);

    //  Receive a zmsg message from the actor. Returns NULL if the actor 
    //  was interrupted before the message could be received, or if there
    //  was a timeout on the actor.                                      
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zmsg_t *
        zactor_recv (zactor_t *self);

    //  Probe the supplied object, and report if it looks like a zactor_t.
    CZMQ_EXPORT bool
        zactor_is (void *self);

    //  Probe the supplied reference. If it looks like a zactor_t instance,
    //  return the underlying libzmq actor handle; else if it looks like   
    //  a libzmq actor handle, return the supplied value.                  
    CZMQ_EXPORT void *
        zactor_resolve (void *self);

    //  Return the actor's zsock handle. Use this when you absolutely need
    //  to work with the zsock instance rather than the actor.            
    CZMQ_EXPORT zsock_t *
        zactor_sock (zactor_t *self);

    //  Self test of this class.
    CZMQ_EXPORT void
        zactor_test (bool verbose);

    #ifdef CZMQ_BUILD_DRAFT_API
    // Function to be called on zactor_destroy. Default behavior is to send zmsg_t with string "$TERM" in a first frame.
    //
    // An example - to send $KTHXBAI string
    //
    //     if (zstr_send (self->pipe, "$KTHXBAI") == 0)
    //         zsock_wait (self->pipe);
    typedef void (zactor_destructor_fn) (
        zactor_t *self);

    //  *** Draft method, for development use, may change without warning ***
    //  Change default destructor by custom function. Actor MUST be able to handle new message instead of default $TERM.
    CZMQ_EXPORT void
        zactor_set_destructor (zactor_t *self, zactor_destructor_fn destructor);

    #endif // CZMQ_BUILD_DRAFT_API

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

This is the class self test code:

    zactor_t *actor = zactor_new (echo_actor, "Hello, World");
    assert (actor);
    zstr_sendx (actor, "ECHO", "This is a string", NULL);
    char *string = zstr_recv (actor);
    assert (streq (string, "This is a string"));
    free (string);
    zactor_destroy (&actor);

    // custom destructor
    // KTHXBAI_actor ends on "$KTHXBAI" string
    zactor_t *KTHXBAI = zactor_new (KTHXBAI_actor, NULL);
    assert (KTHXBAI);
    // which is the one sent by KTHXBAI_destructor
    zactor_set_destructor (KTHXBAI, KTHXBAI_destructor);
    zactor_destroy (&KTHXBAI);

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zauth - authentication for ZeroMQ security mechanisms

A zauth actor takes over authentication for all incoming connections in its context. You can whitelist or blacklist peers based on IP address, and define policies for securing PLAIN, CURVE, and GSSAPI connections.

This class replaces zauth_v2, and is meant for applications that use the CZMQ v3 API (meaning, zsock).

This is the class interface:

    #define CURVE_ALLOW_ANY "*"

    //  CZMQ v3 API (for use with zsock, not zsocket, which is deprecated).
    //
    //  Create new zauth actor instance. This installs authentication on all 
    //  zsock sockets. Until you add policies, all incoming NULL connections are
    //  allowed (classic ZeroMQ behaviour), and all PLAIN and CURVE connections
    //  are denied:
    //  
    //      zactor_t *auth = zactor_new (zauth, NULL);
    //
    //  Destroy zauth instance. This removes authentication and allows all
    //  connections to pass, without authentication:
    //  
    //      zactor_destroy (&auth);
    //
    //  Note that all zauth commands are synchronous, so your application always
    //  waits for a signal from the actor after each command.
    //
    //  Enable verbose logging of commands and activity. Verbose logging can help
    //  debug non-trivial authentication policies:
    //
    //      zstr_send (auth, "VERBOSE");
    //      zsock_wait (auth);
    //
    //  Allow (whitelist) a list of IP addresses. For NULL, all clients from
    //  these addresses will be accepted. For PLAIN and CURVE, they will be
    //  allowed to continue with authentication. You can call this method
    //  multiple times to whitelist more IP addresses. If you whitelist one
    //  or more addresses, any non-whitelisted addresses are treated as
    //  blacklisted:
    //  
    //      zstr_sendx (auth, "ALLOW", "127.0.0.1", "127.0.0.2", NULL);
    //      zsock_wait (auth);
    //  
    //  Deny (blacklist) a list of IP addresses. For all security mechanisms,
    //  this rejects the connection without any further authentication. Use
    //  either a whitelist, or a blacklist, not not both. If you define both
    //  a whitelist and a blacklist, only the whitelist takes effect:
    //  
    //      zstr_sendx (auth, "DENY", "192.168.0.1", "192.168.0.2", NULL);
    //      zsock_wait (auth);
    //
    //  Configure PLAIN authentication using a plain-text password file. You can
    //  modify the password file at any time; zauth will reload it automatically
    //  if modified externally:
    //  
    //      zstr_sendx (auth, "PLAIN", filename, NULL);
    //      zsock_wait (auth);
    //
    //  Configure CURVE authentication, using a directory that holds all public
    //  client certificates, i.e. their public keys. The certificates must be in
    //  zcert_save format. You can add and remove certificates in that directory
    //  at any time. To allow all client keys without checking, specify
    //  CURVE_ALLOW_ANY for the directory name:
    //
    //      zstr_sendx (auth, "CURVE", directory, NULL);
    //      zsock_wait (auth);
    //
    //  Configure GSSAPI authentication, using an underlying mechanism (usually
    //  Kerberos) to establish a secure context and perform mutual authentication:
    //
    //      zstr_sendx (auth, "GSSAPI", NULL);
    //      zsock_wait (auth);
    //
    //  This is the zauth constructor as a zactor_fn:
    CZMQ_EXPORT void
        zauth (zsock_t *pipe, void *certstore);

    //  Selftest
    CZMQ_EXPORT void
        zauth_test (bool verbose);

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

This is the class self test code:

    //  Create temporary directory for test files
    #   define TESTDIR ".test_zauth"
    zsys_dir_create (TESTDIR);

    //  Check there's no authentication
    zsock_t *server = zsock_new (ZMQ_PULL);
    assert (server);
    zsock_t *client = zsock_new (ZMQ_PUSH);
    assert (client);
    bool success = s_can_connect (&server, &client, true);
    assert (success);

    //  Install the authenticator
    zactor_t *auth = zactor_new (zauth, NULL);
    assert (auth);
    if (verbose) {
        zstr_sendx (auth, "VERBOSE", NULL);
        zsock_wait (auth);
    }
    //  Check there's no authentication on a default NULL server
    success = s_can_connect (&server, &client, true);
    assert (success);

    //  When we set a domain on the server, we switch on authentication
    //  for NULL sockets, but with no policies, the client connection
    //  will be allowed.
    zsock_set_zap_domain (server, "global");
    success = s_can_connect (&server, &client, true);
    assert (success);

    //  Blacklist 127.0.0.1, connection should fail
    zsock_set_zap_domain (server, "global");
    zstr_sendx (auth, "DENY", "127.0.0.1", NULL);
    zsock_wait (auth);
    success = s_can_connect (&server, &client, true);
    assert (!success);

    //  Whitelist our address, which overrides the blacklist
    zsock_set_zap_domain (server, "global");
    zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL);
    zsock_wait (auth);
    success = s_can_connect (&server, &client, true);
    assert (success);

    //  Try PLAIN authentication
    zsock_set_plain_server (server, 1);
    zsock_set_plain_username (client, "admin");
    zsock_set_plain_password (client, "Password");
    success = s_can_connect (&server, &client, true);
    assert (!success);

    FILE *password = fopen (TESTDIR "/password-file", "w");
    assert (password);
    fprintf (password, "admin=Password\n");
    fclose (password);
    zsock_set_plain_server (server, 1);
    zsock_set_plain_username (client, "admin");
    zsock_set_plain_password (client, "Password");
    zstr_sendx (auth, "PLAIN", TESTDIR "/password-file", NULL);
    zsock_wait (auth);
    success = s_can_connect (&server, &client, true);
    assert (success);

    zsock_set_plain_server (server, 1);
    zsock_set_plain_username (client, "admin");
    zsock_set_plain_password (client, "Bogus");
    success = s_can_connect (&server, &client, true);
    assert (!success);

    if (zsys_has_curve ()) {
        //  Try CURVE authentication
        //  We'll create two new certificates and save the client public
        //  certificate on disk; in a real case we'd transfer this securely
        //  from the client machine to the server machine.
        zcert_t *server_cert = zcert_new ();
        assert (server_cert);
        zcert_t *client_cert = zcert_new ();
        assert (client_cert);
        const char *server_key = zcert_public_txt (server_cert);

        //  Test without setting-up any authentication
        zcert_apply (server_cert, server);
        zcert_apply (client_cert, client);
        zsock_set_curve_server (server, 1);
        zsock_set_curve_serverkey (client, server_key);
        success = s_can_connect (&server, &client, true);
        assert (!success);

        //  Test CURVE_ALLOW_ANY
        zcert_apply (server_cert, server);
        zcert_apply (client_cert, client);
        zsock_set_curve_server (server, 1);
        zsock_set_curve_serverkey (client, server_key);
        zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
        zsock_wait (auth);
        success = s_can_connect (&server, &client, true);
        assert (success);

        //  Test full client authentication using certificates
        zcert_set_meta (client_cert, "Hello", "%s", "World!");
        zcert_apply (server_cert, server);
        zcert_apply (client_cert, client);
        zsock_set_curve_server (server, 1);
        zsock_set_curve_serverkey (client, server_key);
        zcert_save_public (client_cert, TESTDIR "/mycert.txt");
        zstr_sendx (auth, "CURVE", TESTDIR, NULL);
        zsock_wait (auth);
        success = s_can_connect (&server, &client, false);
        assert (success);

    #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
        // Test send/recv certificate metadata
        zframe_t *frame = zframe_recv (server);
        assert (frame != NULL);
        const char *meta = zframe_meta (frame, "Hello");
        assert (meta != NULL);
        assert (streq (meta, "World!"));
        zframe_destroy (&frame);
        s_renew_sockets(&server, &client);
    #endif

        zcert_destroy (&server_cert);
        zcert_destroy (&client_cert);

        // Test custom zcertstore
        zcertstore_t *certstore = zcertstore_new (NULL);
        zcertstore_set_loader (certstore, s_test_loader, NULL, NULL);
        zactor_destroy(&auth);
        auth = zactor_new (zauth, certstore);
        assert (auth);
        if (verbose) {
            zstr_sendx (auth, "VERBOSE", NULL);
            zsock_wait (auth);
        }

        byte public_key [32] = { 105, 76, 150, 58, 214, 191, 218, 65, 50, 172,
                                 131, 188, 247, 211, 136, 170, 227, 26, 57, 170,
                                 185, 63, 246, 225, 177, 230, 12, 8, 134, 136,
                                 105, 106 };
        byte secret_key [32] = { 245, 217, 172, 73, 106, 28, 195, 17, 218, 132,
                                 135, 209, 99, 240, 98, 232, 7, 137, 244, 100,
                                 242, 23, 29, 114, 70, 223, 83, 1, 113, 207,
                                 132, 149 };
        zcert_t *shared_cert = zcert_new_from (public_key, secret_key);
        assert (shared_cert);
        zcert_apply (shared_cert, server);
        zcert_apply (shared_cert, client);
        zsock_set_curve_server (server, 1);
        zsock_set_curve_serverkey (client, "x?T*N/1Y{8goubv{Ts}#&#f}TXJ//DVe#D2HkoLU");
        success = s_can_connect (&server, &client, true);
        assert (success);
        zcert_destroy (&shared_cert);
    }
    //  Remove the authenticator and check a normal connection works
    zactor_destroy (&auth);
    success = s_can_connect (&server, &client, true);
    assert (success);

    zsock_destroy (&client);
    zsock_destroy (&server);

    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);
    #endif

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zbeacon - LAN discovery and presence

The zbeacon class 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.

This class replaces zbeacon_v2, and is meant for applications that use the CZMQ v3 API (meaning, zsock).

This is the class interface:

    //  Create new zbeacon actor instance:
    //
    //      zactor_t *beacon = zactor_new (zbeacon, NULL);
    //
    //  Destroy zbeacon instance:
    //
    //      zactor_destroy (&beacon);
    //
    //  Enable verbose logging of commands and activity:
    //
    //      zstr_send (beacon, "VERBOSE");
    //
    //  Configure beacon to run on specified UDP port, and return the name of
    //  the host, which can be used as endpoint for incoming connections. To
    //  force the beacon to operate on a given interface, set the environment
    //  variable ZSYS_INTERFACE, or call zsys_set_interface() before creating
    //  the beacon. If the system does not support UDP broadcasts (lacking a
    //  workable interface), returns an empty hostname:
    //
    //      //  Pictures: 's' = C string, 'i' = int
    //      zsock_send (beacon, "si", "CONFIGURE", port_number);
    //      char *hostname = zstr_recv (beacon);
    //
    //  Start broadcasting a beacon at a specified interval in msec. The beacon
    //  data can be at most UDP_FRAME_MAX bytes; this constant is defined in
    //  zsys.h to be 255:
    //
    //      //  Pictures: 'b' = byte * data + size_t size
    //      zsock_send (beacon, "sbi", "PUBLISH", data, size, interval);
    //
    //  Stop broadcasting the beacon:
    //
    //      zstr_sendx (beacon, "SILENCE", NULL);
    //
    //  Start listening to beacons from peers. The filter is used to do a prefix
    //  match on received beacons, to remove junk. Note that any received data
    //  that is identical to our broadcast beacon_data is discarded in any case.
    //  If the filter size is zero, we get all peer beacons:
    //  
    //      zsock_send (beacon, "sb", "SUBSCRIBE", filter_data, filter_size);
    //
    //  Stop listening to other peers
    //
    //      zstr_sendx (beacon, "UNSUBSCRIBE", NULL);
    //
    //  Receive next beacon from a peer. Received beacons are always a 2-frame
    //  message containing the ipaddress of the sender, and then the binary
    //  beacon data as published by the sender:
    //
    //      zmsg_t *msg = zmsg_recv (beacon);
    //
    //  This is the zbeacon constructor as a zactor_fn:
    CZMQ_EXPORT void
        zbeacon (zsock_t *pipe, void *unused);

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

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

This is the class self test code:

    //  Test 1 - two beacons, one speaking, one listening
    //  Create speaker beacon to broadcast our service
    zactor_t *speaker = zactor_new (zbeacon, NULL);
    assert (speaker);
    if (verbose)
        zstr_sendx (speaker, "VERBOSE", NULL);

    zsock_send (speaker, "si", "CONFIGURE", 9999);
    char *hostname = zstr_recv (speaker);
    if (!*hostname) {
        printf ("OK (skipping test, no UDP broadcasting)\n");
        zactor_destroy (&speaker);
        free (hostname);
        return;
    }
    free (hostname);

    //  Create listener beacon on port 9999 to lookup service
    zactor_t *listener = zactor_new (zbeacon, NULL);
    assert (listener);
    if (verbose)
        zstr_sendx (listener, "VERBOSE", NULL);
    zsock_send (listener, "si", "CONFIGURE", 9999);
    hostname = zstr_recv (listener);
    assert (*hostname);
    free (hostname);

    //  We will broadcast the magic value 0xCAFE
    byte announcement [2] = { 0xCA, 0xFE };
    zsock_send (speaker, "sbi", "PUBLISH", announcement, 2, 100);
    //  We will listen to anything (empty subscription)
    zsock_send (listener, "sb", "SUBSCRIBE", "", 0);

    //  Wait for at most 1/2 second if there's no broadcasting
    zsock_set_rcvtimeo (listener, 500);
    char *ipaddress = zstr_recv (listener);
    if (ipaddress) {
        zframe_t *content = zframe_recv (listener);
        assert (zframe_size (content) == 2);
        assert (zframe_data (content) [0] == 0xCA);
        assert (zframe_data (content) [1] == 0xFE);
        zframe_destroy (&content);
        zstr_free (&ipaddress);
        zstr_sendx (speaker, "SILENCE", NULL);
    }
    zactor_destroy (&listener);
    zactor_destroy (&speaker);

    //  Test subscription filter using a 3-node setup
    zactor_t *node1 = zactor_new (zbeacon, NULL);
    assert (node1);
    zsock_send (node1, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node1);
    assert (*hostname);
    free (hostname);

    zactor_t *node2 = zactor_new (zbeacon, NULL);
    assert (node2);
    zsock_send (node2, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node2);
    assert (*hostname);
    free (hostname);

    zactor_t *node3 = zactor_new (zbeacon, NULL);
    assert (node3);
    zsock_send (node3, "si", "CONFIGURE", 5670);
    hostname = zstr_recv (node3);
    assert (*hostname);
    free (hostname);

    zsock_send (node1, "sbi", "PUBLISH", "NODE/1", 6, 250);
    zsock_send (node2, "sbi", "PUBLISH", "NODE/2", 6, 250);
    zsock_send (node3, "sbi", "PUBLISH", "RANDOM", 6, 250);
    zsock_send (node1, "sb", "SUBSCRIBE", "NODE", 4);

    //  Poll on three API sockets at once
    zpoller_t *poller = zpoller_new (node1, node2, node3, NULL);
    assert (poller);
    int64_t stop_at = zclock_mono () + 1000;
    while (zclock_mono () < stop_at) {
        long timeout = (long) (stop_at - zclock_mono ());
        if (timeout < 0)
            timeout = 0;
        void *which = zpoller_wait (poller, timeout * ZMQ_POLL_MSEC);
        if (which) {
            assert (which == node1);
            char *ipaddress, *received;
            zstr_recvx (node1, &ipaddress, &received, NULL);
            assert (streq (received, "NODE/2"));
            zstr_free (&ipaddress);
            zstr_free (&received);
        }
    }
    zpoller_destroy (&poller);

    //  Stop listening
    zstr_sendx (node1, "UNSUBSCRIBE", NULL);

    //  Stop all node broadcasts
    zstr_sendx (node1, "SILENCE", NULL);
    zstr_sendx (node2, "SILENCE", NULL);
    zstr_sendx (node3, "SILENCE", NULL);

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

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zcert - work with CURVE security certificates

The zcert class provides a way to create and work with security certificates for the ZMQ CURVE mechanism. A certificate contains a public + secret key pair, plus metadata. It can be used as a temporary object in memory, or persisted to disk. On disk, a certificate is stored as two files. One is public and contains only the public key. The second is secret and contains both keys. The two have the same filename, with the secret file adding _secret. To exchange certificates, send the public file via some secure route. Certificates are not signed but are text files that can be verified by eye.

Certificates are stored in the ZPL (ZMQ RFC 4) format. They have two sections, metadata and curve. The first contains a list of 'name = value' pairs, one per line. Values may be enclosed in quotes. The curve section has a 'public-key = keyvalue' and, for secret certificates, a 'secret-key = keyvalue' line. The keyvalue is a Z85-encoded CURVE key.

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.
    //  Create and initialize a new certificate in memory
    CZMQ_EXPORT zcert_t *
        zcert_new (void);

    //  Accepts public/secret key pair from caller
    CZMQ_EXPORT zcert_t *
        zcert_new_from (const byte *public_key, const byte *secret_key);

    //  Load certificate from file
    CZMQ_EXPORT zcert_t *
        zcert_load (const char *filename);

    //  Destroy a certificate in memory
    CZMQ_EXPORT void
        zcert_destroy (zcert_t **self_p);

    //  Return public part of key pair as 32-byte binary string
    CZMQ_EXPORT const byte *
        zcert_public_key (zcert_t *self);

    //  Return secret part of key pair as 32-byte binary string
    CZMQ_EXPORT const byte *
        zcert_secret_key (zcert_t *self);

    //  Return public part of key pair as Z85 armored string
    CZMQ_EXPORT const char *
        zcert_public_txt (zcert_t *self);

    //  Return secret part of key pair as Z85 armored string
    CZMQ_EXPORT const char *
        zcert_secret_txt (zcert_t *self);

    //  Set certificate metadata from formatted string.
    CZMQ_EXPORT void
        zcert_set_meta (zcert_t *self, const char *name, const char *format, ...) CHECK_PRINTF (3);

    //  Get metadata value from certificate; if the metadata value doesn't
    //  exist, returns NULL.                                              
    CZMQ_EXPORT const char *
        zcert_meta (zcert_t *self, const char *name);

    //  Get list of metadata fields from certificate. Caller is responsible for
    //  destroying list. Caller should not modify the values of list items.    
    CZMQ_EXPORT zlist_t *
        zcert_meta_keys (zcert_t *self);

    //  Save full certificate (public + secret) to file for persistent storage  
    //  This creates one public file and one secret file (filename + "_secret").
    CZMQ_EXPORT int
        zcert_save (zcert_t *self, const char *filename);

    //  Save public certificate only to file for persistent storage
    CZMQ_EXPORT int
        zcert_save_public (zcert_t *self, const char *filename);

    //  Save secret certificate only to file for persistent storage
    CZMQ_EXPORT int
        zcert_save_secret (zcert_t *self, const char *filename);

    //  Apply certificate to socket, i.e. use for CURVE security on socket.
    //  If certificate was loaded from public file, the secret key will be 
    //  undefined, and this certificate will not work successfully.        
    CZMQ_EXPORT void
        zcert_apply (zcert_t *self, void *socket);

    //  Return copy of certificate; if certificate is NULL or we exhausted
    //  heap memory, returns NULL.                                        
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zcert_t *
        zcert_dup (zcert_t *self);

    //  Return true if two certificates have the same keys
    CZMQ_EXPORT bool
        zcert_eq (zcert_t *self, zcert_t *compare);

    //  Print certificate contents to stdout
    CZMQ_EXPORT void
        zcert_print (zcert_t *self);

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

    #ifdef CZMQ_BUILD_DRAFT_API
    //  *** Draft method, for development use, may change without warning ***
    //  Unset certificate metadata.
    CZMQ_EXPORT void
        zcert_unset_meta (zcert_t *self, const char *name);

    #endif // CZMQ_BUILD_DRAFT_API

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

This is the class self test code:

    //  Create temporary directory for test files
    #   define TESTDIR ".test_zcert"
    zsys_dir_create (TESTDIR);

    //  Create a simple certificate with metadata
    zcert_t *cert = zcert_new ();
    assert (cert);
    zcert_set_meta (cert, "email", "ph@imatix.com");
    zcert_set_meta (cert, "name", "Pieter Hintjens");
    zcert_set_meta (cert, "organization", "iMatix Corporation");
    zcert_set_meta (cert, "version", "%d", 1);
    zcert_set_meta (cert, "delete_me", "now");
    zcert_unset_meta (cert, "delete_me");
    assert (streq (zcert_meta (cert, "email"), "ph@imatix.com"));
    zlist_t *keys = zcert_meta_keys (cert);
    assert (zlist_size (keys) == 4);
    zlist_destroy (&keys);

    //  Check the dup and eq methods
    zcert_t *shadow = zcert_dup (cert);
    assert (zcert_eq (cert, shadow));
    zcert_destroy (&shadow);

    //  Check we can save and load certificate
    zcert_save (cert, TESTDIR "/mycert.txt");
    assert (zsys_file_exists (TESTDIR "/mycert.txt"));
    assert (zsys_file_exists (TESTDIR "/mycert.txt_secret"));

    //  Load certificate, will in fact load secret one
    shadow = zcert_load (TESTDIR "/mycert.txt");
    assert (shadow);
    assert (zcert_eq (cert, shadow));
    zcert_destroy (&shadow);

    //  Delete secret certificate, load public one
    int rc = zsys_file_delete (TESTDIR "/mycert.txt_secret");
    assert (rc == 0);
    shadow = zcert_load (TESTDIR "/mycert.txt");

    //  32-byte null key encodes as 40 '0' characters
    assert (streq (zcert_secret_txt (shadow), FORTY_ZEROES));

    zcert_destroy (&shadow);
    zcert_destroy (&cert);

    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zcertstore - work with CURVE security certificate stores

To authenticate new clients using the ZeroMQ CURVE security mechanism, we have to check that the client's public key matches a key we know and accept. There are numerous ways to store accepted client public keys. The mechanism CZMQ implements is certificates (plain text files) held in a certificate store (a disk directory). This class works with such certificate stores, and lets you easily load them from disk, and check if a given client public key is known or not. The zcert class does the work of managing a single certificate.

The certificate store can be memory-only, in which case you can load it yourself by inserting certificate objects one by one, or it can be loaded from disk, in which case you can add, modify, or remove certificates on disk at any time, and the store will detect such changes and refresh itself automatically. In most applications you won't use this class directly but through the zauth class, which provides a high-level API for authentication (and manages certificate stores for you). To actually create certificates on disk, use the zcert class in code, or the tools/zmakecert.c command line tool, or any text editor. The format of a certificate file is defined in the zcert man page.

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.
    //  Create a new certificate store from a disk directory, loading and        
    //  indexing all certificates in that location. The directory itself may be  
    //  absent, and created later, or modified at any time. The certificate store
    //  is automatically refreshed on any zcertstore_lookup() call. If the       
    //  location is specified as NULL, creates a pure-memory store, which you    
    //  can work with by inserting certificates at runtime.                      
    CZMQ_EXPORT zcertstore_t *
        zcertstore_new (const char *location);

    //  Destroy a certificate store object in memory. Does not affect anything
    //  stored on disk.                                                       
    CZMQ_EXPORT void
        zcertstore_destroy (zcertstore_t **self_p);

    //  Look up certificate by public key, returns zcert_t object if found,
    //  else returns NULL. The public key is provided in Z85 text format.  
    CZMQ_EXPORT zcert_t *
        zcertstore_lookup (zcertstore_t *self, const char *public_key);

    //  Insert certificate into certificate store in memory. Note that this
    //  does not save the certificate to disk. To do that, use zcert_save()
    //  directly on the certificate. Takes ownership of zcert_t object.    
    CZMQ_EXPORT void
        zcertstore_insert (zcertstore_t *self, zcert_t **cert_p);

    //  Print list of certificates in store to logging facility
    CZMQ_EXPORT void
        zcertstore_print (zcertstore_t *self);

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

    #ifdef CZMQ_BUILD_DRAFT_API
    // Loaders retrieve certificates from an arbitrary source.
    typedef void (zcertstore_loader) (
        zcertstore_t *self);

    // Destructor for loader state.
    typedef void (zcertstore_destructor) (
        void **self_p);

    //  *** Draft method, for development use, may change without warning ***
    //  Override the default disk loader with a custom loader fn.
    CZMQ_EXPORT void
        zcertstore_set_loader (zcertstore_t *self, zcertstore_loader loader, zcertstore_destructor destructor, void *state);

    //  *** Draft method, for development use, may change without warning ***
    //  Empty certificate hashtable. This wrapper exists to be friendly to bindings,
    //  which don't usually have access to struct internals.                        
    CZMQ_EXPORT void
        zcertstore_empty (zcertstore_t *self);

    #endif // CZMQ_BUILD_DRAFT_API

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

This is the class self test code:

    //  Create temporary directory for test files
    #   define TESTDIR ".test_zcertstore"
    zsys_dir_create (TESTDIR);

    //  Load certificate store from disk; it will be empty
    zcertstore_t *certstore = zcertstore_new (TESTDIR);
    assert (certstore);

    //  Create a single new certificate and save to disk
    zcert_t *cert = zcert_new ();
    assert (cert);
    char *client_key = strdup (zcert_public_txt (cert));
    assert (client_key);
    zcert_set_meta (cert, "name", "John Doe");
    zcert_save (cert, TESTDIR "/mycert.txt");
    zcert_destroy (&cert);

    //  Check that certificate store refreshes as expected
    cert = zcertstore_lookup (certstore, client_key);
    assert (cert);
    assert (streq (zcert_meta (cert, "name"), "John Doe"));

    //  Test custom loader
    test_loader_state *state = (test_loader_state *) zmalloc (sizeof (test_loader_state));
    state->index = 0;
    zcertstore_set_loader (certstore, s_test_loader, s_test_destructor, (void *)state);
    #if (ZMQ_VERSION_MAJOR >= 4)
    cert = zcertstore_lookup (certstore, client_key);
    assert (cert == NULL);
    cert = zcertstore_lookup (certstore, "abcdefghijklmnopqrstuvwxyzabcdefghijklmn");
    assert (cert);
    #endif

    free (client_key);

    if (verbose)
        zcertstore_print (certstore);
    zcertstore_destroy (&certstore);

    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zchunk - work with memory chunks

The zchunk class works with variable sized blobs. Not as efficient as ZeroMQ's messages but they do less weirdness and so are easier to understand. The chunk class has methods to read and write chunks from disk.

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

This is the class interface:

    //  This is a stable class, and may not change except for emergencies. It
    //  is provided in stable builds.
    //  Create a new chunk of the specified size. If you specify the data, it   
    //  is copied into the chunk. If you do not specify the data, the chunk is  
    //  allocated and left empty, and you can then add data using zchunk_append.
    CZMQ_EXPORT zchunk_t *
        zchunk_new (const void *data, size_t size);

    //  Destroy a chunk
    CZMQ_EXPORT void
        zchunk_destroy (zchunk_t **self_p);

    //  Resizes chunk max_size as requested; chunk_cur size is set to zero
    CZMQ_EXPORT void
        zchunk_resize (zchunk_t *self, size_t size);

    //  Return chunk cur size
    CZMQ_EXPORT size_t
        zchunk_size (zchunk_t *self);

    //  Return chunk max size
    CZMQ_EXPORT size_t
        zchunk_max_size (zchunk_t *self);

    //  Return chunk data
    CZMQ_EXPORT byte *
        zchunk_data (zchunk_t *self);

    //  Set chunk data from user-supplied data; truncate if too large. Data may
    //  be null. Returns actual size of chunk                                  
    CZMQ_EXPORT size_t
        zchunk_set (zchunk_t *self, const void *data, size_t size);

    //  Fill chunk data from user-supplied octet
    CZMQ_EXPORT size_t
        zchunk_fill (zchunk_t *self, byte filler, size_t size);

    //  Append user-supplied data to chunk, return resulting chunk size. If the 
    //  data would exceeded the available space, it is truncated. If you want to
    //  grow the chunk to accommodate new data, use the zchunk_extend method.   
    CZMQ_EXPORT size_t
        zchunk_append (zchunk_t *self, const void *data, size_t size);

    //  Append user-supplied data to chunk, return resulting chunk size. If the
    //  data would exceeded the available space, the chunk grows in size.      
    CZMQ_EXPORT size_t
        zchunk_extend (zchunk_t *self, const void *data, size_t size);

    //  Copy as much data from 'source' into the chunk as possible; returns the  
    //  new size of chunk. If all data from 'source' is used, returns exhausted  
    //  on the source chunk. Source can be consumed as many times as needed until
    //  it is exhausted. If source was already exhausted, does not change chunk. 
    CZMQ_EXPORT size_t
        zchunk_consume (zchunk_t *self, zchunk_t *source);

    //  Returns true if the chunk was exhausted by consume methods, or if the
    //  chunk has a size of zero.                                            
    CZMQ_EXPORT bool
        zchunk_exhausted (zchunk_t *self);

    //  Read chunk from an open file descriptor
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zchunk_t *
        zchunk_read (FILE *handle, size_t bytes);

    //  Write chunk to an open file descriptor
    CZMQ_EXPORT int
        zchunk_write (zchunk_t *self, FILE *handle);

    //  Try to slurp an entire file into a chunk. Will read up to maxsize of  
    //  the file. If maxsize is 0, will attempt to read the entire file and   
    //  fail with an assertion if that cannot fit into memory. Returns a new  
    //  chunk containing the file data, or NULL if the file could not be read.
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zchunk_t *
        zchunk_slurp (const char *filename, size_t maxsize);

    //  Create copy of chunk, as new chunk object. Returns a fresh zchunk_t   
    //  object, or null if there was not enough heap memory. If chunk is null,
    //  returns null.                                                         
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zchunk_t *
        zchunk_dup (zchunk_t *self);

    //  Return chunk data encoded as printable hex string. Caller must free
    //  string when finished with it.                                      
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT char *
        zchunk_strhex (zchunk_t *self);

    //  Return chunk data copied into freshly allocated string
    //  Caller must free string when finished with it.        
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT char *
        zchunk_strdup (zchunk_t *self);

    //  Return TRUE if chunk body is equal to string, excluding terminator
    CZMQ_EXPORT bool
        zchunk_streq (zchunk_t *self, const char *string);

    //  Transform zchunk into a zframe that can be sent in a message.
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zframe_t *
        zchunk_pack (zchunk_t *self);

    //  Transform a zframe into a zchunk.
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zchunk_t *
        zchunk_unpack (zframe_t *frame);

    //  Calculate SHA1 digest for chunk, using zdigest class.
    CZMQ_EXPORT const char *
        zchunk_digest (zchunk_t *self);

    //  Dump chunk to FILE stream, for debugging and tracing.
    CZMQ_EXPORT void
        zchunk_fprint (zchunk_t *self, FILE *file);

    //  Dump message to stderr, for debugging and tracing.
    //  See zchunk_fprint for details                     
    CZMQ_EXPORT void
        zchunk_print (zchunk_t *self);

    //  Probe the supplied object, and report if it looks like a zchunk_t.
    CZMQ_EXPORT bool
        zchunk_is (void *self);

    //  Self test of this class.
    CZMQ_EXPORT void
        zchunk_test (bool verbose);

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

This is the class self test code:

    zchunk_t *chunk = zchunk_new ("1234567890", 10);
    assert (chunk);
    assert (zchunk_size (chunk) == 10);
    assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0);
    zchunk_destroy (&chunk);

    chunk = zchunk_new (NULL, 10);
    assert (chunk);
    zchunk_append (chunk, "12345678", 8);
    zchunk_append (chunk, "90ABCDEF", 8);
    zchunk_append (chunk, "GHIJKLMN", 8);
    assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0);
    assert (zchunk_size (chunk) == 10);
    assert (zchunk_streq (chunk, "1234567890"));
    assert (streq (zchunk_digest (chunk), "01B307ACBA4F54F55AAFC33BB06BBBF6CA803E9A"));
    char *string = zchunk_strdup (chunk);
    assert (streq (string, "1234567890"));
    free (string);
    string = zchunk_strhex (chunk);
    assert (streq (string, "31323334353637383930"));
    free (string);

    zframe_t *frame = zchunk_pack (chunk);
    assert (frame);

    zchunk_t *chunk2 = zchunk_unpack (frame);
    assert (chunk2);
    assert (memcmp (zchunk_data (chunk2), "1234567890", 10) == 0);
    zframe_destroy (&frame);
    zchunk_destroy (&chunk2);

    zchunk_t *copy = zchunk_dup (chunk);
    assert (copy);
    assert (memcmp (zchunk_data (copy), "1234567890", 10) == 0);
    assert (zchunk_size (copy) == 10);
    zchunk_destroy (&copy);
    zchunk_destroy (&chunk);

    chunk = zchunk_new (NULL, 0);
    zchunk_extend (chunk, "12345678", 8);
    zchunk_extend (chunk, "90ABCDEF", 8);
    zchunk_extend (chunk, "GHIJKLMN", 8);
    assert (zchunk_size (chunk) == 24);
    assert (zchunk_streq (chunk, "1234567890ABCDEFGHIJKLMN"));
    zchunk_destroy (&chunk);

    copy = zchunk_new ("1234567890abcdefghij", 20);
    assert (copy);
    chunk = zchunk_new (NULL, 8);
    assert (chunk);
    zchunk_consume (chunk, copy);
    assert (!zchunk_exhausted (copy));
    assert (memcmp (zchunk_data (chunk), "12345678", 8) == 0);
    zchunk_set (chunk, NULL, 0);
    zchunk_consume (chunk, copy);
    assert (!zchunk_exhausted (copy));
    assert (memcmp (zchunk_data (chunk), "90abcdef", 8) == 0);
    zchunk_set (chunk, NULL, 0);
    zchunk_consume (chunk, copy);
    assert (zchunk_exhausted (copy));
    assert (zchunk_size (chunk) == 4);
    assert (memcmp (zchunk_data (chunk), "ghij", 4) == 0);
    zchunk_destroy (&copy);
    zchunk_destroy (&chunk);

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zclock - millisecond clocks and delays

The zclock class provides essential sleep and system time functions, used to slow down threads for testing, and calculate timers for polling. Wraps the non-portable system calls in a simple portable API.

The Win32 Sleep() call defaults to 16ms resolution unless the system timer resolution is increased with a call to timeBeginPeriod() permitting 1ms granularity.

This is the class interface:

    //  This is a stable class, and may not change except for emergencies. It
    //  is provided in stable builds.
    //  Sleep for a number of milliseconds
    CZMQ_EXPORT void
        zclock_sleep (int msecs);

    //  Return current system clock as milliseconds. Note that this clock can  
    //  jump backwards (if the system clock is changed) so is unsafe to use for
    //  timers and time offsets. Use zclock_mono for that instead.             
    CZMQ_EXPORT int64_t
        zclock_time (void);

    //  Return current monotonic clock in milliseconds. Use this when you compute
    //  time offsets. The monotonic clock is not affected by system changes and  
    //  so will never be reset backwards, unlike a system clock.                 
    CZMQ_EXPORT int64_t
        zclock_mono (void);

    //  Return current monotonic clock in microseconds. Use this when you compute
    //  time offsets. The monotonic clock is not affected by system changes and  
    //  so will never be reset backwards, unlike a system clock.                 
    CZMQ_EXPORT int64_t
        zclock_usecs (void);

    //  Return formatted date/time as fresh string. Free using zstr_free().
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT char *
        zclock_timestr (void);

    //  Self test of this class.
    CZMQ_EXPORT void
        zclock_test (bool verbose);

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

This is the class self test code:

    int64_t start = zclock_time ();
    zclock_sleep (10);
    assert ((zclock_time () - start) >= 10);
    start = zclock_mono ();
    int64_t usecs = zclock_usecs ();
    zclock_sleep (10);
    assert ((zclock_mono () - start) >= 10);
    assert ((zclock_usecs () - usecs) >= 10000);
    char *timestr = zclock_timestr ();
    if (verbose)
        puts (timestr);
    free (timestr);

    #if defined (__WINDOWS__)
    zsys_shutdown();
    #endif

zconfig - work with config files written in rfc.zeromq.org/spec:4/ZPL.

Lets applications load, work with, and save configuration files. This implements rfc.zeromq.org/spec:4/ZPL, which is a simple structured text format for configuration files.

Here is an example ZPL stream and corresponding config structure:

context
    iothreads = 1
    verbose = 1      #   Ask for a trace
main
    type = zqueue    #  ZMQ_DEVICE type
    frontend
        option
            hwm = 1000
            swap = 25000000     #  25MB
        bind = 'inproc://addr1'
        bind = 'ipc://addr2'
    backend
        bind = inproc://addr3

root                    Down = child
|                     Across = next
v
context-->main
|         |
|         v
|       type=queue-->frontend-->backend
|                      |          |
|                      |          v
|                      |        bind=inproc://addr3
|                      v
|                    option-->bind=inproc://addr1-->bind=ipc://addr2
|                      |
|                      v
|                    hwm=1000-->swap=25000000
v
iothreads=1-->verbose=false

This is the class interface:

    //  This is a stable class, and may not change except for emergencies. It
    //  is provided in stable builds.
    // 
    typedef int (zconfig_fct) (
        zconfig_t *self, void *arg, int level);

    //  Create new config item
    CZMQ_EXPORT zconfig_t *
        zconfig_new (const char *name, zconfig_t *parent);

    //  Load a config tree from a specified ZPL text file; returns a zconfig_t  
    //  reference for the root, if the file exists and is readable. Returns NULL
    //  if the file does not exist.                                             
    CZMQ_EXPORT zconfig_t *
        zconfig_load (const char *filename);

    //  Equivalent to zconfig_load, taking a format string instead of a fixed
    //  filename.                                                            
    CZMQ_EXPORT zconfig_t *
        zconfig_loadf (const char *format, ...) CHECK_PRINTF (1);

    //  Destroy a config item and all its children
    CZMQ_EXPORT void
        zconfig_destroy (zconfig_t **self_p);

    //  Return name of config item
    CZMQ_EXPORT char *
        zconfig_name (zconfig_t *self);

    //  Return value of config item
    CZMQ_EXPORT char *
        zconfig_value (zconfig_t *self);

    //  Insert or update configuration key with value
    CZMQ_EXPORT void
        zconfig_put (zconfig_t *self, const char *path, const char *value);

    //  Equivalent to zconfig_put, accepting a format specifier and variable
    //  argument list, instead of a single string value.                    
    CZMQ_EXPORT void
        zconfig_putf (zconfig_t *self, const char *path, const char *format, ...) CHECK_PRINTF (3);

    //  Get value for config item into a string value; leading slash is optional
    //  and ignored.                                                            
    CZMQ_EXPORT char *
        zconfig_get (zconfig_t *self, const char *path, const char *default_value);

    //  Set config item name, name may be NULL
    CZMQ_EXPORT void
        zconfig_set_name (zconfig_t *self, const char *name);

    //  Set new value for config item. The new value may be a string, a printf  
    //  format, or NULL. Note that if string may possibly contain '%', or if it 
    //  comes from an insecure source, you must use '%s' as the format, followed
    //  by the string.                                                          
    CZMQ_EXPORT void
        zconfig_set_value (zconfig_t *self, const char *format, ...) CHECK_PRINTF (2);

    //  Find our first child, if any
    CZMQ_EXPORT zconfig_t *
        zconfig_child (zconfig_t *self);

    //  Find our first sibling, if any
    CZMQ_EXPORT zconfig_t *
        zconfig_next (zconfig_t *self);

    //  Find a config item along a path; leading slash is optional and ignored.
    CZMQ_EXPORT zconfig_t *
        zconfig_locate (zconfig_t *self, const char *path);

    //  Locate the last config item at a specified depth
    CZMQ_EXPORT zconfig_t *
        zconfig_at_depth (zconfig_t *self, int level);

    //  Execute a callback for each config item in the tree; returns zero if
    //  successful, else -1.                                                
    CZMQ_EXPORT int
        zconfig_execute (zconfig_t *self, zconfig_fct handler, void *arg);

    //  Add comment to config item before saving to disk. You can add as many
    //  comment lines as you like. If you use a null format, all comments are
    //  deleted.                                                             
    CZMQ_EXPORT void
        zconfig_set_comment (zconfig_t *self, const char *format, ...) CHECK_PRINTF (2);

    //  Return comments of config item, as zlist.
    CZMQ_EXPORT zlist_t *
        zconfig_comments (zconfig_t *self);

    //  Save a config tree to a specified ZPL text file, where a filename
    //  "-" means dump to standard output.                               
    CZMQ_EXPORT int
        zconfig_save (zconfig_t *self, const char *filename);

    //  Equivalent to zconfig_save, taking a format string instead of a fixed
    //  filename.                                                            
    CZMQ_EXPORT int
        zconfig_savef (zconfig_t *self, const char *format, ...) CHECK_PRINTF (2);

    //  Report filename used during zconfig_load, or NULL if none
    CZMQ_EXPORT const char *
        zconfig_filename (zconfig_t *self);

    //  Reload config tree from same file that it was previously loaded from.
    //  Returns 0 if OK, -1 if there was an error (and then does not change  
    //  existing data).                                                      
    CZMQ_EXPORT int
        zconfig_reload (zconfig_t **self_p);

    //  Load a config tree from a memory chunk
    CZMQ_EXPORT zconfig_t *
        zconfig_chunk_load (zchunk_t *chunk);

    //  Save a config tree to a new memory chunk
    CZMQ_EXPORT zchunk_t *
        zconfig_chunk_save (zconfig_t *self);

    //  Load a config tree from a null-terminated string
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT zconfig_t *
        zconfig_str_load (const char *string);

    //  Save a config tree to a new null terminated string
    //  Caller owns return value and must destroy it when done.
    CZMQ_EXPORT char *
        zconfig_str_save (zconfig_t *self);

    //  Return true if a configuration tree was loaded from a file and that
    //  file has changed in since the tree was loaded.                     
    CZMQ_EXPORT bool
        zconfig_has_changed (zconfig_t *self);

    //  Print the config file to open stream
    CZMQ_EXPORT void
        zconfig_fprint (zconfig_t *self, FILE *file);

    //  Print properties of object
    CZMQ_EXPORT void
        zconfig_print (zconfig_t *self);

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

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

This is the class self test code:

    //  Create temporary directory for test files
    #   define TESTDIR ".test_zconfig"
    zsys_dir_create (TESTDIR);

    zconfig_t *root = zconfig_new ("root", NULL);
    assert (root);
    zconfig_t *section, *item;

    section = zconfig_new ("headers", root);
    assert (section);
    item = zconfig_new ("email", section);
    assert (item);
    zconfig_set_value (item, "some@random.com");
    item = zconfig_new ("name", section);
    assert (item);
    zconfig_set_value (item, "Justin Kayce");
    zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret");
    zconfig_set_comment (root, "   CURVE certificate");
    zconfig_set_comment (root, "   -----------------");
    assert (zconfig_comments (root));
    zconfig_save (root, TESTDIR "/test.cfg");
    zconfig_destroy (&root);
    root = zconfig_load (TESTDIR "/test.cfg");
    if (verbose)
        zconfig_save (root, "-");
    assert (streq (zconfig_filename (root), TESTDIR "/test.cfg"));

    char *email = zconfig_get (root, "/headers/email", NULL);
    assert (email);
    assert (streq (email, "some@random.com"));
    char *passwd = zconfig_get (root, "/curve/secret-key", NULL);
    assert (passwd);
    assert (streq (passwd, "Top Secret"));

    zconfig_savef (root, "%s/%s", TESTDIR, "test.cfg");
    assert (!zconfig_has_changed (root));
    int rc = zconfig_reload (&root);
    assert (rc == 0);
    assert (!zconfig_has_changed (root));
    zconfig_destroy (&root);

    //  Test chunk load/save
    root = zconfig_new ("root", NULL);
    assert (root);
    section = zconfig_
czmq open issues Ask a question     (View All Issues)
  • about 3 years CZMQ fails: Symbol not found: _zsys_handler_reset
  • about 3 years The README.md references the command 'ldconfig' which is not present on OSX 10.11.6 (15G1004)
  • about 3 years zactor_new on MIPS architecture causes a SIGABRT
  • about 3 years CZMQ won't compile with CFLAGS="-DNDEBUG"
  • about 3 years node.js binding windows build
  • over 3 years zsys_run_as exits with -1 on Windows even if it's a no-op
  • over 3 years VS2015 build.bat has 'other' configuration entry names
  • over 3 years Curve Server : Assertion failure during processing of INITIATE command
  • over 3 years zeromq/czmq fails while creating too many incproc connections
  • over 3 years How do i access tuple(s) in zgossip?
  • over 3 years czmq_selftest was suffering from crash using mingw when entering zsock test
  • over 3 years Problem: JNI binding for zactor not generated
  • over 3 years README.md / Building on Windows needs to be updated
  • over 3 years Problem: OS X build of nodejs bindings fails test
  • over 3 years Problem: the function zproxy seems to have some issues
  • over 3 years Problem : the function zsock_destory doesn't work
  • almost 4 years Windows binding is not building
  • almost 4 years Zbeacon hangs when one beacon disappears
  • almost 4 years Problem: in jni binding, there is no task to publish artifacts locally
  • about 4 years Issues of Windows CI
  • about 4 years czmq zsock_unbind does naught onWindows?
  • about 4 years Problem: zpoller does not work with ZMQ_CLIENT sockets
  • about 4 years libzmq doesn't build on freebsd 10.2
  • about 4 years Problem: zrex fails to match
  • over 4 years problems with "make check" over RPI 2
  • over 4 years win32: strdup vs _strdup causing MSVC runtime heap check debug asserts and crashes
  • over 4 years Problem: link error in making zmakecert.
  • over 4 years Problem: zhash_autofree implies the value must be a string, but the documentation does not mention this
  • over 4 years zmsg_remove updates msg size no matter if frame is/isn't a member of the msg
  • over 4 years cross compiling with mingw on linux to windows fails
czmq open pull requests (View All Pulls)
  • Problem: Build instructions are out of date in README.md
  • Added buildall.bat file
  • Problem: zsys_run_as returns -1 for windows even for no-op
  • Updating readme for issue #1401
czmq questions on Stackoverflow (View All Questions)
  • CZMQ actors allow only one publish & one subscribe
  • Message passing with czmq
  • memory leak in czmq on Windows build
  • czmq: how do I end a thread upon interrupt signal?
  • what is the meaning of stable in zfile_stable - CZMQ
czmq latest release notes
v4.1.0 CZMQ 4.1.0

CZMQ version 4.1.0 stable, released on 2017/12/31

  • New STABLE APIs have been added to wrap new libzmq context options:

    • zsys_set_thread_sched_policy
    • zsys_set_thread_priority See zsys manpage for more details.
  • New DRAFT class to parse command line arguments in a platform independent way: zargs. See zargs manpage for more info.

  • New DRAFT APIs have been added to the zproc class to manage subprocesses in a platform-independent unified API. See the zproc manpage for more details.

  • New DRAFT APIs have been added to the zactor class to override the default destructor:

    • zactor_destructor_fn
    • zactor_set_destructor See zactor manpage for more info.
  • New DRAFT APIs have been added to the zcertstore class to return a zlistx of all the certificates in the store:

    • zcertstore_certs See zcertstore manpage for more info.
  • New DRAFT APIs have been added to the zcert class to create a new zcert from public/secret keypair in text form:

    • zcert_new_from_txt See zcert manpage for more info.
  • New DRAFT APIs have been added to the zsys class to get/set the default stable age value of files in zfile:

    • zsys_file_stable_age_msec
    • zsys_set_file_stable_age_msec See zsys and zfile manpages for more info.
  • New DRAFT APIs have been added to the zstr class to send and receive compressed strings:

    • zstr_recv_compress
    • zstr_send_compress
    • zstr_sendm_compress To enable them, build with the new (optional) lz4 dependency. See zstr manpage for more info.
  • New DRAFT APIs have been added to the zgossip class to support CURVE security:

    • ZAP DOMAIN actor message to set the ZAP domain for authentication
    • SET PUBLICKEY actor message to set the local public key
    • SET SECRETKEY actor message to set the local secret key
    • new optional parameter appended to CONNECT actor message, public key of the server See zgossip manpage for more info.
  • New DRAFT APIs have been added to the zfile class to support managing temporary files in a platform independent way:

    • zfile_tmp See zfile manpage for more info.
  • New DRAFT APIs have been added to the zconfig class to support removing a node and its subtrees or only the subtrees:

    • zconfig_remove_subtree
    • zconfig_remove See zconfig manpage for more info.
  • Added new FFI Python and Ruby bindings.

  • Add support for new ZMQ socket monitoring events to the zmonitor class:

    • HANDSHAKE_SUCCEEDED
    • HANDSHAKE_FAILED_NO_DETAIL
    • HANDSHAKE_FAILED_PROTOCOL
    • HANDSHAKE_FAILED_AUTH Requires libzmq version 4.2.3 or higher with DRAFT APIs enabled.
  • Fixed #1811 - add CZMQ_BUILD_SHARED/STATIC options to CMake to control whether to build shared/static libraries. Default to ON. The minimum required CMake version has been bumped from 2.8 to 2.8.8.

  • Fixed #1802 - fix using ziflist in a VirtualBox VM running on OSX.

  • Fixed #1798 - fix build on Cygwin.

  • Fixed #1773 - fix zfile_restat on Windows XP with newer MSVC++.

  • Fixed #1765 - fix build on OpenBSD.

  • Fixed #1755 - improve reliability of zproxy selftest in slower environments.

  • Fixed #1753 - fix zloop_set_nonstop to actually use the parameter passed by the user rather than always setting nonstop to true.

  • Fixed #1747 - check for OOM condition in zstr_send* functions.

  • Fixed #1730 - improve the internal usage of system random generator APIs to be more reliable.

  • Fixed #1728 - chomp all leading / in zfile_filename.

  • Fixed #1726 - do not bind to hard-coded TCP ports in self tests.

  • Fixed #1722 - define the PRI* types if not available on Windows.

  • Fixed #1715 - document ZSYS_SIGHANDLER behaviour w.r.t. the zsys_catch_interrupts API.

  • Fixed #1712 - clarify zsock_brecv documentation w.r.t buffers.

  • Fixed #1711 - set User-Id field in ZAP responses.

  • Fixed #1710 - clarify documentation of zframe_meta - the caller must not modify the returned value.

  • Fixed #1702 - clarify documentation of zhashx_set_key_comparator and zhashx_set_key_hasher.

  • Fixed #1675 - fix zhashx_purge memory leak when shrinking.

  • Fixed #1672 - fix compile error 'sockaddr_in': undeclared identifier on MSVC.

  • Fixed #1671 - add support for new (DRAFT) socket types in zframe_recv_nowait and zmsg_recv_nowait.

  • Fixed #1671 - correctly complete multipart receives in zmsg_recv_nowait.

  • Fixed #1667 - if ZSYS_IPV6_ADDRESS is link-local but does not have the %interface suffix, append it from ZSYS_INTERFACE.

  • Fixed #1659 - reset all CZMQ internal state in zsys_shutdown to facilitate use with fork without exec.

  • Fixed #1649 - set static pointers to NULL to fix restarting CZMQ via zsys_shutdown -> zsys_init.

  • Fixed #1644 - zbeacon on Windows only sends on one interfaces with INADDR_BROADCAST set (interface option *).

  • Fixed #1634 - zloop is using reader callback after zloop_reader_end.

  • Fixed #1632 - NULL pointer exception in ziflist on Windows if network adapters are added/removed whilst being enumerated.

  • Fixed #1623 - remove mentions of retired APIs from manpages.

  • Fixed #1618 - fix build with GCC 7.

  • Fixed #1616 - zsys_udp_recv will now return NULL when failing to retrieve the peer's address instead of silently failing.

  • Fixed #1616 - zsys_udp_recv's parameter peername must now be at least NI_MAXHOST long when IPv6 is enabled.

  • Fixed #1616 - add IPv6 support to zbeacon using, by default, link-local all-node address fe02::1 in lieu of broadcast (which does not exist on v6). The multicast address can be specified via zsys so, theoretically, it should work across multiple networks as well (untested!).

  • Fixed #1615 - add link-local all-node fe02::1 as the default zsys IPv6 multicast address.

  • Fixed #1615 - add IPv6 support to ziflist on *nix through new (DRAFT) APIs to avoid changing the output of old ones: ziflist_new_ipv6, ziflist_reload_ipv6 and ziflist_is_ipv6.

  • Fixed #1603 - generated socket options, and public API/ABI, were changing depending on the version of libzmq used at build time. Keep all the symbols stable instead and add additional runtime checks. Socket options APIs will now be built as empty stubs if unavailable in the libzmq version used at build time, and will return an error if not available in the libzmq version used at runtime.

  • Fixed #1609 - fix zdir selftest on Windows.

  • Fixed #1608 - document that on Windows it is necessary to call zsys_shutdown manually as DLLs do not support atexit() callbacks, and manually call it from all unit tests.

  • Fixed #1606 - use inproc instead of ipc in zproxy selftest to fix failure on Windows.

  • Fixed #1602 - ZSYS_INTERFACE: if the value is a single digit, interpret it as an index. Facilitates using it on Windows with complicated interface names.

  • Fixed #1599 - correctly handle CTRL_CLOSE_EVENT in Windows.

  • Fixed #1597 - added czmq_private_selftest to test private classes without exporting their symbols in the shared library.

  • Fixed #1597 - declare some internal-only helper functions as static to avoid exporting their symbols.

  • Fixed #1594 - correctly return -1 and set errno to EINVAL from zpoller_remove if the reader does not exist

  • Fixed #1590 - zsys_shutdown does not call zmq_term when it closes sockets which results in dangling sockets warnings.

  • Fixed #1588 - fix debian/kfreebsd build and always use external UUID library, if available, regardless of the OS.

  • Fixed #1459 - clarify zgossip documentation.

  • Fixed #1026 - zmsg_remove decreased count of frames even when it failed.

  • Fixed #1032 - clarify documentation of zhash_autofree and zhashx callbacks.

v4.0.2 CZMQ 4.0.2

CZMQ version 4.0.2 stable, released on 2016/12/31

  • Fixed #1559 - DRAFT zsock_new_*_checked symbols leak
  • Fixed #1560 - zsock options could be available at build time but not at runtime. Added runtime check, an error will be printed if the option is not available.
  • Fixed #1565 - improved compatibility with Solaris/Illumos
  • Fixed #1573 - memory leak when message send fails in internal usage
v4.0.1 CZMQ 4.0.1

CZMQ version 4.0.1 stable, released on 2016/11/10

  • Version 4.0.0 introduced the DRAFT mechanism, but it had a flaw: the internally defined DRAFT symbols were leaking as global in the shared library. This meant that although the API was stable, the ABI could in some cases not be. This has now been fixed using compiler's visibility attribute to avoid this problem.
Other projects in C