• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H24-Jan-2021-1817

api/H24-Jan-2021-705584

bindings/H24-Jan-2021-24,47915,688

builds/H24-Jan-2021-13,89311,323

doc/H03-May-2022-463314

examples/H24-Jan-2021-378247

include/H24-Jan-2021-512197

packaging/H24-Jan-2021-526418

src/H03-May-2022-9,8567,139

.clang-formatH A D24-Jan-20211.5 KiB5752

.editorconfigH A D24-Jan-2021546 2016

.gitattributesH A D24-Jan-2021185 54

.gitignoreH A D24-Jan-20211.5 KiB136113

.travis.ymlH A D24-Jan-20217.2 KiB192173

AUTHORSH A D24-Jan-2021437 3127

BUILD.mdH A D24-Jan-2021150 119

CONTRIBUTING.mdH A D24-Jan-20211.5 KiB2010

DockerfileH A D24-Jan-2021901 3225

Findczmq.cmakeH A D24-Jan-20211.6 KiB4740

Findlibsodium.cmakeH A D24-Jan-20211.7 KiB4841

Findlibzmq.cmakeH A D24-Jan-20213.5 KiB9681

Finduuid.cmakeH A D24-Jan-20211.6 KiB4841

JenkinsfileH A D24-Jan-202136.7 KiB574565

LICENSEH A D24-Jan-202116.3 KiB374293

Makefile.amH A D24-Jan-20211.9 KiB6643

NEWSH A D24-Jan-20212.9 KiB8555

README.mdH A D24-Jan-202140.5 KiB1,137879

VagrantfileH A D24-Jan-20211.4 KiB5948

acinclude.m4H A D24-Jan-2021468 1110

appveyor.ymlH A D24-Jan-20212.6 KiB7966

autogen.shH A D24-Jan-20211.9 KiB5333

ci_build.shH A D24-Jan-202115.2 KiB448384

ci_deploy.shH A D24-Jan-20211.1 KiB3018

ci_deploy_obs.shH A D24-Jan-2021900 209

configure.acH A D24-Jan-202129.3 KiB775678

generate.shH A D24-Jan-202164 83

license.xmlH A D24-Jan-2021399 118

project.gypH A D24-Jan-20213.5 KiB154152

project.xmlH A D24-Jan-20211.7 KiB4640

setup.pyH A D24-Jan-2021252 108

README.md

1
2[![GitHub release](https://img.shields.io/github/release/zeromq/zyre.svg)](https://github.com/zeromq/zyre/releases)
3[![OBS draft](https://img.shields.io/badge/OBS%20master-draft-yellow.svg)](http://software.opensuse.org/download.html?project=network%3Amessaging%3Azeromq%3Agit-draft&package=zyre)
4[![OBS stable](https://img.shields.io/badge/OBS%20master-stable-yellow.svg)](http://software.opensuse.org/download.html?project=network%3Amessaging%3Azeromq%3Agit-stable&package=zyre)
5<a target="_blank" href="http://webchat.freenode.net?channels=%23zeromq&uio=d4"><img src="https://cloud.githubusercontent.com/assets/493242/14886493/5c660ea2-0d51-11e6-8249-502e6c71e9f2.png" height = "20" /></a>
6[![license](https://img.shields.io/badge/license-MPL%202.0-green.svg)](https://github.com/zeromq/zyre/blob/master/LICENSE)
7
8# Zyre - Local Area Clustering for Peer-to-Peer Applications
9
10| Linux & MacOSX | Windows  |
11|:--------------:|:--------:|
12|[![Build Status](https://travis-ci.org/zeromq/zyre.png?branch=master)](https://travis-ci.org/zeromq/zyre)|[![Build status](https://ci.appveyor.com/api/projects/status/kuugogjji97yblqe?svg=true)](https://ci.appveyor.com/project/zeromq/zyre)|
13## Contents
14
15
16**[Overview](#overview)**
17
18**[Scope and Goals](#scope-and-goals)**
19
20**[Ownership and License](#ownership-and-license)**
21
22**[Using Zyre](#using-zyre)**
23
24**[Building on Linux and macOS](#building-on-linux-and-macos)**
25
26**[Building on Windows](#building-on-windows)**
27
28**[Building on Windows](#building-on-windows)**
29*  [Using CMake](#using-cmake)
30
31**[Linking with an Application](#linking-with-an-application)**
32
33**[Use from Other Languages](#use-from-other-languages)**
34
35**[API Summary](#api-summary)**
36*  [zyre - API wrapping one Zyre node](#zyre---api-wrapping-one-zyre-node)
37*  [zyre_event - no title found](#zyre_event---no-title-found)
38
39**[Hints to Contributors](#hints-to-contributors)**
40
41**[This Document](#this-document)**
42
43## Overview
44
45### Scope and Goals
46
47Zyre provides reliable group messaging over local area networks. It has these key characteristics:
48
49* Zyre needs no administration or configuration.
50* Peers may join and leave the network at any time.
51* Peers talk to each other without any central brokers or servers.
52* Peers can talk directly to each other.
53* Peers can join groups, and then talk to groups.
54* Zyre is reliable, and loses no messages even when the network is heavily loaded.
55* Zyre is fast and has low latency, requiring no consensus protocols.
56* Zyre is designed for WiFi networks, yet also works well on Ethernet networks.
57* Time for a new peer to join a network is about one second.
58
59Typical use cases for Zyre are:
60
61* Local service discovery.
62* Clustering of a set of services on the same Ethernet network.
63* Controlling a network of smart devices (Internet of Things).
64* Multi-user mobile applications (like smart classrooms).
65
66Technical details:
67
68* Uses RFC 36 (http://rfc.zeromq.org/spec:36/ZRE) protocol for discovery and heartbeating.
69* Uses reliable Dealer-Router pattern for interconnection, assuring that messages are not lost unless a peer application terminates.
70* Optimized for WiFi, using UDP broadcasts for discovery and heartbeating…
71* Offers alternative discovery mechanism (gossip) for Ethernet networks.
72
73### Ownership and License
74
75The contributors are listed in AUTHORS. This project uses the MPL v2 license, see LICENSE.
76
77Zyre uses the [C4.1 (Collective Code Construction Contract)](http://rfc.zeromq.org/spec:22) process for contributions.
78
79Zyre uses the [CLASS (C Language Style for Scalabilty)](http://rfc.zeromq.org/spec:21) guide for code style.
80
81To report an issue, use the [Zyre issue tracker](https://github.com/zeromq/zyre/issues) at github.com.
82
83## Using Zyre
84
85### Building on Linux and macOS
86
87To start with, you need at least these packages:
88* `git` -- git is how we share code with other people.
89* `build-essential`, `libtool`, `pkg-config` - the C compiler and related tools.
90* `autotools-dev`, `autoconf`, `automake` - the GNU autoconf makefile generators.
91* `cmake` - the CMake makefile generators (an alternative to autoconf).
92
93Plus some others:
94* `uuid-dev`, `libpcre3-dev` - utility libraries.
95* `valgrind` - a useful tool for checking your code.
96* `pkg-config` - an optional useful tool to make building with dependencies easier.
97
98Which we install like this (using the Debian-style apt-get package manager):
99
100```
101    sudo apt-get update
102    sudo apt-get install -y \
103    git build-essential libtool \
104    pkg-config autotools-dev autoconf automake cmake \
105    uuid-dev libpcre3-dev valgrind
106
107    # only execute this next line if interested in updating the man pages as
108    # well (adds to build time):
109    sudo apt-get install -y asciidoc
110```
111Here'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:
112
113```
114    git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
115    cd libsodium
116    ./autogen.sh && ./configure && make check
117    sudo make install
118    cd ..
119
120    git clone git://github.com/zeromq/libzmq.git
121    cd libzmq
122    ./autogen.sh
123    # do not specify "--with-libsodium" if you prefer to use internal tweetnacl
124    # security implementation (recommended for development)
125    ./configure --with-libsodium
126    make check
127    sudo make install
128    sudo ldconfig
129    cd ..
130
131    git clone git://github.com/zeromq/czmq.git
132    cd czmq
133    ./autogen.sh && ./configure && make check
134    sudo make install
135    sudo ldconfig
136    cd ..
137
138    git clone git://github.com/zeromq/zyre.git
139    cd zyre
140    ./autogen.sh && ./configure && make check
141    sudo make install
142    sudo ldconfig
143    cd ..
144```
145
146
147Test by running the `zyre_selftest` command:
148
149    zyre\src\.libs\zyre_selftest
150
151Test by running the `zpinger` command, from two or more PCs.
152
153    zyre\src\.libs\zpinger
154
155### Building on Windows
156
157To start with, you need MS Visual Studio (C/C++). The free community edition works well.
158
159Then, install git, and make sure it works from a DevStudio command prompt:
160
161```
162git
163```
164
165Now let's build Zyre from GitHub:
166
167```
168    git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
169    git clone git://github.com/zeromq/libzmq.git
170    git clone git://github.com/zeromq/czmq.git
171    git clone git://github.com/zeromq/zyre.git
172    cd zyre\builds\msvc
173    configure.bat
174    cd build
175    buildall.bat
176    cd ..\..\..\..
177```
178
179Test by running the `zyre_selftest` command:
180```
181    dir/s/b zyre_selftest.exe
182    zyre\builds\msvc\vs2013\DebugDEXE\zyre_selftest.exe
183    zyre\builds\msvc\vs2013\ReleaseDEXE\zyre_selftest.exe
184
185    :: select your choice and run it
186    zyre\builds\msvc\vs2013\DebugDEXE\zyre_selftest.exe
187```
188Test by running `zpinger` from two or more PCs:
189
190```
191    dir/s/b zpinger.exe
192    zyre\builds\msvc\vs2013\DebugDEXE\zpinger.exe
193    zyre\builds\msvc\vs2013\ReleaseDEXE\zpinger.exe
194    zyre\builds\msvc\vs2013\x64\DebugDEXE\zpinger.exe
195
196    :: select your choice and run it
197    zyre\builds\msvc\vs2013\ReleaseDEXE\zpinger.exe
198```
199
200### Building on Windows
201
202To start with, you need MS Visual Studio (C/C++). The free community edition works well.
203
204Then, install git, and make sure it works from a DevStudio command prompt:
205
206```
207git
208```
209
210#### Using CMake
211
212`zyre` requires `czmq` and `libzmq`, so we need to build `libzmq` first. For `libzmq`, you can optionally use [libsodium](https://github.com/jedisct1/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):
213
214```
215git clone --depth 1 -b stable https://github.com/jedisct1/libsodium.git
216cd libsodium\builds\msvc\build
217buildall.bat
218cd ..\..\..\..
219```
220
221Once done, you can find the library files under `libsodium\bin\<Win32|x64>\<Debug|Release>\<Platform Toolset>\<dynamic|ltcg|static>`.
222
223Here, the `<Platform Toolset>` is the platform toolset you are using: `v100` for `VS2010`, `v140` for `VS2015`, `v141` for `VS2017`, etc.
224
225```
226git clone git://github.com/zeromq/libzmq.git
227cd libzmq
228mkdir build
229cd build
230cmake .. -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
231cmake --build . --config Release --target install
232cd ..\..\
233```
234`-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.
235
236`-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.
237
238Next, let's build `czmq`:
239
240```
241git clone git://github.com/zeromq/czmq.git
242cd czmq
243mkdir build
244cd build
245cmake .. -DCZMQ_BUILD_SHARED=ON -DCZMQ_BUILD_STATIC=OFF -DCMAKE_PREFIX_PATH=C:\projects\libs -DCMAKE_INSTALL_PREFIX=C:\projects\libs
246cmake --build . --config Release --target install
247```
248
249Remember 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`.
250
251That 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](https://github.com/zeromq/czmq/issues/1972) for more details.
252
253Now, it is time to build `zyre`:
254
255```
256git clone git://github.com/zeromq/zyre.git
257cd zyre
258mkdir build
259cd build
260cmake .. -DZYRE_BUILD_SHARED=ON -DZYRE_BUILD_STATIC=OFF -DCMAKE_PREFIX_PATH=C:\projects\libs
261cmake --build . --config Release
262ctest -C Release
263```
264
265### Linking with an Application
266
267Include `zyre.h` in your application and link with libzyre. Here is a typical gcc link command:
268
269    gcc myapp.c -lzyre -lczmq -lzmq -o myapp
270
271### Use from Other Languages
272
273This is a list of auto-generated bindings:
274
275* https://github.com/zeromq/zyre/tree/master/bindings/jni - Java ([Examples](https://github.com/zeromq/zyre/tree/master/examples/jni))
276* https://github.com/zeromq/zyre/tree/master/bindings/nodejs - NodeJS
277* https://github.com/zeromq/zyre/tree/master/bindings/python - Python
278* https://github.com/zeromq/zyre/tree/master/bindings/python_cffi - Python (cffi)
279* https://github.com/zeromq/zyre/tree/master/bindings/qml - QML
280* https://github.com/zeromq/zyre/tree/master/bindings/qt - Qt
281* https://github.com/zeromq/zyre/tree/master/bindings/ruby - Ruby (FFI)
282
283### API Summary
284
285This is the API provided by Zyre 2.x, in alphabetical order.
286
287#### zyre - API wrapping one Zyre node
288
289Zyre does local area discovery and clustering. A Zyre node broadcasts
290UDP beacons, and connects to peers that it finds. This class wraps a
291Zyre node with a message-based API.
292
293All incoming events are zmsg_t messages delivered via the zyre_recv
294call. The first frame defines the type of the message, and following
295frames provide further values:
296
297    ENTER fromnode name headers ipaddress:port
298        a new peer has entered the network
299    EVASIVE fromnode name
300        a peer is being evasive (i.e. quiet) and will be pinged manually
301    SILENT fromnode name
302        a peer has been quiet and has not answered ping after 1 second
303    EXIT fromnode name
304        a peer has left the network
305    JOIN fromnode name groupname
306        a peer has joined a specific group
307    LEAVE fromnode name groupname
308        a peer has joined a specific group
309    WHISPER fromnode name message
310        a peer has sent this node a message
311    SHOUT fromnode name groupname message
312        a peer has sent one of our groups a message
313
314In SHOUT and WHISPER the message is zero or more frames, and can hold
315any ZeroMQ message. In ENTER, the headers frame contains a packed
316dictionary, see zhash_pack/unpack.
317
318To join or leave a group, use the zyre_join and zyre_leave methods.
319To set a header value, use the zyre_set_header method. To send a message
320to a single peer, use zyre_whisper. To send a message to a group, use
321zyre_shout.
322
323Todo: allow multipart contents
324
325This is the class interface:
326
327```h
328    //  This is a stable class, and may not change except for emergencies. It
329    //  is provided in stable builds.
330    //  This class has draft methods, which may change over time. They are not
331    //  in stable releases, by default. Use --enable-drafts to enable.
332    //  Constructor, creates a new Zyre node. Note that until you start the
333    //  node it is silent and invisible to other nodes on the network.
334    //  The node name is provided to other nodes during discovery. If you
335    //  specify NULL, Zyre generates a randomized node name from the UUID.
336    ZYRE_EXPORT zyre_t *
337        zyre_new (const char *name);
338
339    //  Destructor, destroys a Zyre node. When you destroy a node, any
340    //  messages it is sending or receiving will be discarded.
341    ZYRE_EXPORT void
342        zyre_destroy (zyre_t **self_p);
343
344    //  Return our node UUID string, after successful initialization
345    ZYRE_EXPORT const char *
346        zyre_uuid (zyre_t *self);
347
348    //  Return our node name, after successful initialization. First 6
349    //  characters of UUID by default.
350    ZYRE_EXPORT const char *
351        zyre_name (zyre_t *self);
352
353    //  Set the public name of this node overriding the default. The name is
354    //  provide during discovery and come in each ENTER message.
355    ZYRE_EXPORT void
356        zyre_set_name (zyre_t *self, const char *name);
357
358    //  Set node header; these are provided to other nodes during discovery
359    //  and come in each ENTER message.
360    ZYRE_EXPORT void
361        zyre_set_header (zyre_t *self, const char *name, const char *format, ...) CHECK_PRINTF (3);
362
363    //  Set verbose mode; this tells the node to log all traffic as well as
364    //  all major events.
365    ZYRE_EXPORT void
366        zyre_set_verbose (zyre_t *self);
367
368    //  Set UDP beacon discovery port; defaults to 5670, this call overrides
369    //  that so you can create independent clusters on the same network, for
370    //  e.g. development vs. production. Has no effect after zyre_start().
371    ZYRE_EXPORT void
372        zyre_set_port (zyre_t *self, int port_nbr);
373
374    //  Set the peer evasiveness timeout, in milliseconds. Default is 5000.
375    //  This can be tuned in order to deal with expected network conditions
376    //  and the response time expected by the application. This is tied to
377    //  the beacon interval and rate of messages received.
378    ZYRE_EXPORT void
379        zyre_set_evasive_timeout (zyre_t *self, int interval);
380
381    //  Set the peer silence timeout, in milliseconds. Default is 5000.
382    //  This can be tuned in order to deal with expected network conditions
383    //  and the response time expected by the application. This is tied to
384    //  the beacon interval and rate of messages received.
385    //  Silence is triggered one second after the timeout if peer has not
386    //  answered ping and has not sent any message.
387    //  NB: this is currently redundant with the evasiveness timeout. Both
388    //  affect the same timeout value.
389    ZYRE_EXPORT void
390        zyre_set_silent_timeout (zyre_t *self, int interval);
391
392    //  Set the peer expiration timeout, in milliseconds. Default is 30000.
393    //  This can be tuned in order to deal with expected network conditions
394    //  and the response time expected by the application. This is tied to
395    //  the beacon interval and rate of messages received.
396    ZYRE_EXPORT void
397        zyre_set_expired_timeout (zyre_t *self, int interval);
398
399    //  Set UDP beacon discovery interval, in milliseconds. Default is instant
400    //  beacon exploration followed by pinging every 1,000 msecs.
401    ZYRE_EXPORT void
402        zyre_set_interval (zyre_t *self, size_t interval);
403
404    //  Set network interface for UDP beacons. If you do not set this, CZMQ will
405    //  choose an interface for you. On boxes with several interfaces you should
406    //  specify which one you want to use, or strange things can happen.
407    ZYRE_EXPORT void
408        zyre_set_interface (zyre_t *self, const char *value);
409
410    //  By default, Zyre binds to an ephemeral TCP port and broadcasts the local
411    //  host name using UDP beaconing. When you call this method, Zyre will use
412    //  gossip discovery instead of UDP beaconing. You MUST set-up the gossip
413    //  service separately using zyre_gossip_bind() and _connect(). Note that the
414    //  endpoint MUST be valid for both bind and connect operations. You can use
415    //  inproc://, ipc://, or tcp:// transports (for tcp://, use an IP address
416    //  that is meaningful to remote as well as local nodes). Returns 0 if
417    //  the bind was successful, else -1.
418    ZYRE_EXPORT int
419        zyre_set_endpoint (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
420
421    //  Set-up gossip discovery of other nodes. At least one node in the cluster
422    //  must bind to a well-known gossip endpoint, so other nodes can connect to
423    //  it. Note that gossip endpoints are completely distinct from Zyre node
424    //  endpoints, and should not overlap (they can use the same transport).
425    ZYRE_EXPORT void
426        zyre_gossip_bind (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
427
428    //  Set-up gossip discovery of other nodes. A node may connect to multiple
429    //  other nodes, for redundancy paths. For details of the gossip network
430    //  design, see the CZMQ zgossip class.
431    ZYRE_EXPORT void
432        zyre_gossip_connect (zyre_t *self, const char *format, ...) CHECK_PRINTF (2);
433
434    //  Start node, after setting header values. When you start a node it
435    //  begins discovery and connection. Returns 0 if OK, -1 if it wasn't
436    //  possible to start the node.
437    ZYRE_EXPORT int
438        zyre_start (zyre_t *self);
439
440    //  Stop node; this signals to other peers that this node will go away.
441    //  This is polite; however you can also just destroy the node without
442    //  stopping it.
443    ZYRE_EXPORT void
444        zyre_stop (zyre_t *self);
445
446    //  Join a named group; after joining a group you can send messages to
447    //  the group and all Zyre nodes in that group will receive them.
448    ZYRE_EXPORT int
449        zyre_join (zyre_t *self, const char *group);
450
451    //  Leave a group
452    ZYRE_EXPORT int
453        zyre_leave (zyre_t *self, const char *group);
454
455    //  Receive next message from network; the message may be a control
456    //  message (ENTER, EXIT, JOIN, LEAVE) or data (WHISPER, SHOUT).
457    //  Returns zmsg_t object, or NULL if interrupted
458    //  Caller owns return value and must destroy it when done.
459    ZYRE_EXPORT zmsg_t *
460        zyre_recv (zyre_t *self);
461
462    //  Send message to single peer, specified as a UUID string
463    //  Destroys message after sending
464    ZYRE_EXPORT int
465        zyre_whisper (zyre_t *self, const char *peer, zmsg_t **msg_p);
466
467    //  Send message to a named group
468    //  Destroys message after sending
469    ZYRE_EXPORT int
470        zyre_shout (zyre_t *self, const char *group, zmsg_t **msg_p);
471
472    //  Send formatted string to a single peer specified as UUID string
473    ZYRE_EXPORT int
474        zyre_whispers (zyre_t *self, const char *peer, const char *format, ...) CHECK_PRINTF (3);
475
476    //  Send formatted string to a named group
477    ZYRE_EXPORT int
478        zyre_shouts (zyre_t *self, const char *group, const char *format, ...) CHECK_PRINTF (3);
479
480    //  Return zlist of current peer ids.
481    //  Caller owns return value and must destroy it when done.
482    ZYRE_EXPORT zlist_t *
483        zyre_peers (zyre_t *self);
484
485    //  Return zlist of current peers of this group.
486    //  Caller owns return value and must destroy it when done.
487    ZYRE_EXPORT zlist_t *
488        zyre_peers_by_group (zyre_t *self, const char *name);
489
490    //  Return zlist of currently joined groups.
491    //  Caller owns return value and must destroy it when done.
492    ZYRE_EXPORT zlist_t *
493        zyre_own_groups (zyre_t *self);
494
495    //  Return zlist of groups known through connected peers.
496    //  Caller owns return value and must destroy it when done.
497    ZYRE_EXPORT zlist_t *
498        zyre_peer_groups (zyre_t *self);
499
500    //  Return the endpoint of a connected peer.
501    //  Returns empty string if peer does not exist.
502    //  Caller owns return value and must destroy it when done.
503    ZYRE_EXPORT char *
504        zyre_peer_address (zyre_t *self, const char *peer);
505
506    //  Return the value of a header of a conected peer.
507    //  Returns null if peer or key doesn't exits.
508    //  Caller owns return value and must destroy it when done.
509    ZYRE_EXPORT char *
510        zyre_peer_header_value (zyre_t *self, const char *peer, const char *name);
511
512    //  Return socket for talking to the Zyre node, for polling
513    ZYRE_EXPORT zsock_t *
514        zyre_socket (zyre_t *self);
515
516    //  Print zyre node information to stdout
517    ZYRE_EXPORT void
518        zyre_print (zyre_t *self);
519
520    //  Return the Zyre version for run-time API detection; returns
521    //  major * 10000 + minor * 100 + patch, as a single integer.
522    ZYRE_EXPORT uint64_t
523        zyre_version (void);
524
525    //  Self test of this class.
526    ZYRE_EXPORT void
527        zyre_test (bool verbose);
528
529    #ifdef ZYRE_BUILD_DRAFT_API
530    //  *** Draft method, for development use, may change without warning ***
531    //  Set the TCP port bound by the ROUTER peer-to-peer socket (beacon mode).
532    //  Defaults to * (the port is randomly assigned by the system).
533    //  This call overrides this, to bypass some firewall issues when ports are
534    //  random. Has no effect after zyre_start().
535    ZYRE_EXPORT void
536        zyre_set_beacon_peer_port (zyre_t *self, int port_nbr);
537
538    //  *** Draft method, for development use, may change without warning ***
539    //  This options enables a peer to actively contest for leadership in the
540    //  given group. If this option is not set the peer will still participate in
541    //  elections but never gets elected. This ensures that a consent for a leader
542    //  is reached within a group even though not every peer is contesting for
543    //  leadership.
544    ZYRE_EXPORT void
545        zyre_set_contest_in_group (zyre_t *self, const char *group);
546
547    //  *** Draft method, for development use, may change without warning ***
548    //  Set an alternative endpoint value when using GOSSIP ONLY. This is useful
549    //  if you're advertising an endpoint behind a NAT.
550    ZYRE_EXPORT void
551        zyre_set_advertised_endpoint (zyre_t *self, const char *value);
552
553    //  *** Draft method, for development use, may change without warning ***
554    //  Apply a azcert to a Zyre node.
555    ZYRE_EXPORT void
556        zyre_set_zcert (zyre_t *self, zcert_t *zcert);
557
558    //  *** Draft method, for development use, may change without warning ***
559    //  Specify the ZAP domain (for use with CURVE).
560    ZYRE_EXPORT void
561        zyre_set_zap_domain (zyre_t *self, const char *domain);
562
563    //  *** Draft method, for development use, may change without warning ***
564    //  Set-up gossip discovery with CURVE enabled.
565    ZYRE_EXPORT void
566        zyre_gossip_connect_curve (zyre_t *self, const char *public_key, const char *format, ...) CHECK_PRINTF (3);
567
568    //  *** Draft method, for development use, may change without warning ***
569    //  Unpublish a GOSSIP node from local list, useful in removing nodes from list when they EXIT
570    ZYRE_EXPORT void
571        zyre_gossip_unpublish (zyre_t *self, const char *node);
572
573    //  *** Draft method, for development use, may change without warning ***
574    //  Explicitly connect to a peer
575    ZYRE_EXPORT int
576        zyre_require_peer (zyre_t *self, const char *uuid, const char *endpoint, const char *public_key);
577
578    #endif // ZYRE_BUILD_DRAFT_API
579```
580Please add '@interface' section in './../src/zyre.c'.
581
582This is the class self test code:
583
584```c
585    //  We'll use inproc gossip discovery so that this works without networking
586
587    uint64_t version = zyre_version ();
588    assert ((version / 10000) % 100 == ZYRE_VERSION_MAJOR);
589    assert ((version / 100) % 100 == ZYRE_VERSION_MINOR);
590    assert (version % 100 == ZYRE_VERSION_PATCH);
591
592    //  Create two nodes
593    zyre_t *node1 = zyre_new ("node1");
594    assert (node1);
595    assert (streq (zyre_name (node1), "node1"));
596    zyre_set_header (node1, "X-HELLO", "World");
597    if (verbose)
598        zyre_set_verbose (node1);
599
600    //  Set inproc endpoint for this node
601    int rc = zyre_set_endpoint (node1, "inproc://zyre-node1");
602    assert (rc == 0);
603    //  Set up gossip network for this node
604    zyre_gossip_bind (node1, "inproc://gossip-hub");
605    rc = zyre_start (node1);
606    assert (rc == 0);
607
608    zyre_t *node2 = zyre_new ("node2");
609    assert (node2);
610    assert (streq (zyre_name (node2), "node2"));
611    if (verbose)
612        zyre_set_verbose (node2);
613
614    //  Set inproc endpoint for this node
615    //  First, try to use existing name, it'll fail
616    rc = zyre_set_endpoint (node2, "inproc://zyre-node1");
617    assert (rc == -1);
618    //  Now use available name and confirm that it succeeds
619    rc = zyre_set_endpoint (node2, "inproc://zyre-node2");
620    assert (rc == 0);
621
622    //  Set up gossip network for this node
623    zyre_gossip_connect (node2, "inproc://gossip-hub");
624    rc = zyre_start (node2);
625    assert (rc == 0);
626    assert (strneq (zyre_uuid (node1), zyre_uuid (node2)));
627
628    zyre_join (node1, "GLOBAL");
629    zyre_join (node2, "GLOBAL");
630
631    //  Give time for them to interconnect
632    zclock_sleep (250);
633    if (verbose)
634        zyre_dump (node1);
635
636    zlist_t *peers = zyre_peers (node1);
637    assert (peers);
638    assert (zlist_size (peers) == 1);
639    zlist_destroy (&peers);
640
641    zyre_join (node1, "node1 group of one");
642    zyre_join (node2, "node2 group of one");
643
644    // Give them time to join their groups
645    zclock_sleep (250);
646
647    zlist_t *own_groups = zyre_own_groups (node1);
648    assert (own_groups);
649    assert (zlist_size (own_groups) == 2);
650    zlist_destroy (&own_groups);
651
652    zlist_t *peer_groups = zyre_peer_groups (node1);
653    assert (peer_groups);
654    assert (zlist_size (peer_groups) == 2);
655    zlist_destroy (&peer_groups);
656
657    char *value = zyre_peer_header_value (node2, zyre_uuid (node1), "X-HELLO");
658    assert (streq (value, "World"));
659    zstr_free (&value);
660
661    //  One node shouts to GLOBAL
662    zyre_shouts (node1, "GLOBAL", "Hello, World");
663
664    //  Second node should receive ENTER, JOIN, and SHOUT
665    zmsg_t *msg = zyre_recv (node2);
666    assert (msg);
667    char *command = zmsg_popstr (msg);
668    assert (streq (command, "ENTER"));
669    zstr_free (&command);
670    assert (zmsg_size (msg) == 4);
671    char *peerid = zmsg_popstr (msg);
672    char *name = zmsg_popstr (msg);
673    assert (streq (name, "node1"));
674    zstr_free (&name);
675    zframe_t *headers_packed = zmsg_pop (msg);
676
677    char *address = zmsg_popstr (msg);
678    char *endpoint = zyre_peer_address (node2, peerid);
679    assert (streq (address, endpoint));
680    zstr_free (&peerid);
681    zstr_free (&endpoint);
682    zstr_free (&address);
683
684    assert (headers_packed);
685    zhash_t *headers = zhash_unpack (headers_packed);
686    assert (headers);
687    zframe_destroy (&headers_packed);
688    assert (streq ((char *) zhash_lookup (headers, "X-HELLO"), "World"));
689    zhash_destroy (&headers);
690    zmsg_destroy (&msg);
691
692    msg = zyre_recv (node2);
693    assert (msg);
694    command = zmsg_popstr (msg);
695    assert (streq (command, "JOIN"));
696    zstr_free (&command);
697    assert (zmsg_size (msg) == 3);
698    zmsg_destroy (&msg);
699
700    msg = zyre_recv (node2);
701    assert (msg);
702    command = zmsg_popstr (msg);
703    assert (streq (command, "JOIN"));
704    zstr_free (&command);
705    assert (zmsg_size (msg) == 3);
706    zmsg_destroy (&msg);
707
708    msg = zyre_recv (node2);
709    assert (msg);
710    command = zmsg_popstr (msg);
711    assert (streq (command, "SHOUT"));
712    zstr_free (&command);
713    zmsg_destroy (&msg);
714
715    zyre_stop (node2);
716
717    msg = zyre_recv (node2);
718    assert (msg);
719    command = zmsg_popstr (msg);
720    assert (streq (command, "STOP"));
721    zstr_free (&command);
722    zmsg_destroy (&msg);
723
724    zyre_stop (node1);
725
726    zyre_destroy (&node1);
727    zyre_destroy (&node2);
728
729    printf ("OK\n");
730
731    #ifdef ZYRE_BUILD_DRAFT_API
732    //  DRAFT-API: Security
733    if (zsys_has_curve()){
734
735        printf (" * zyre-curve: ");
736        if (verbose)
737            printf ("\n");
738
739        if (verbose)
740            zsys_debug("----------------TESTING CURVE --------------");
741
742        zactor_t *speaker = zactor_new (zbeacon, NULL);
743        assert (speaker);
744        if (verbose)
745            zstr_sendx (speaker, "VERBOSE", NULL);
746
747        // ensuring we have a broadcast address
748        zsock_send (speaker, "si", "CONFIGURE", 9999);
749        char *hostname = zstr_recv (speaker);
750        if (!*hostname) {
751            printf ("OK (skipping test, no UDP broadcasting)\n");
752            zactor_destroy (&speaker);
753            freen (hostname);
754            return;
755        }
756        freen (hostname);
757        zactor_destroy (&speaker);
758
759
760        // zap setup
761        zactor_t *auth = zactor_new(zauth, NULL);
762        assert (auth);
763
764        if (verbose) {
765            zstr_sendx(auth, "VERBOSE", NULL);
766            zsock_wait(auth);
767        }
768
769        zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
770        zsock_wait (auth);
771
772        zyre_t *node3 = zyre_new ("node3");
773        zyre_t *node4 = zyre_new ("node4");
774
775        assert (node3);
776        assert (node4);
777
778        if (verbose) {
779            zyre_set_verbose (node3);
780            zyre_set_verbose (node4);
781        }
782
783        zyre_set_zap_domain(node3, "TEST");
784        zyre_set_zap_domain(node4, "TEST");
785
786        zsock_set_rcvtimeo(node3->inbox, 10000);
787        zsock_set_rcvtimeo(node4->inbox, 10000);
788
789        zcert_t *node3_cert = zcert_new ();
790        zcert_t *node4_cert = zcert_new ();
791
792        assert (node3_cert);
793        assert (node4_cert);
794
795        zyre_set_zcert (node3, node3_cert);
796        zyre_set_zcert (node4, node4_cert);
797
798        zyre_set_header (node3, "X-PUBLICKEY", "%s", zcert_public_txt (node3_cert));
799        zyre_set_header (node4, "X-PUBLICKEY", "%s", zcert_public_txt (node4_cert));
800
801        // test beacon
802        if (verbose)
803            zsys_debug ("----------------TESTING BEACON----------------");
804
805        rc = zyre_start (node3);
806        assert (rc == 0);
807
808        rc = zyre_start (node4);
809        assert (rc == 0);
810
811        zyre_join (node3, "GLOBAL");
812        zyre_join (node4, "GLOBAL");
813
814        zclock_sleep (1500);
815
816        if (verbose) {
817            zyre_dump (node3);
818            zyre_dump (node4);
819        }
820
821        zyre_shouts (node3, "GLOBAL", "Hello, World");
822
823        //  Second node should receive ENTER, JOIN, and SHOUT
824        msg = zyre_recv (node4);
825        assert (msg);
826        command = zmsg_popstr (msg);
827        assert (streq (command, "ENTER"));
828        zstr_free (&command);
829
830        char *peerid = zmsg_popstr (msg);
831        assert (peerid);
832        name = zmsg_popstr (msg);
833        assert (streq (name, "node3"));
834        zmsg_destroy (&msg);
835
836        msg = zyre_recv (node4);
837        assert (msg);
838        command = zmsg_popstr (msg);
839        assert (streq (command, "JOIN"));
840        zstr_free (&command);
841        zmsg_destroy (&msg);
842
843        msg = zyre_recv (node4);
844        assert (msg);
845        command = zmsg_popstr (msg);
846        assert (streq (command, "SHOUT"));
847        zstr_free (&command);
848        zmsg_destroy (&msg);
849
850        zyre_leave (node3, "GLOBAL");
851        zyre_leave (node4, "GLOBAL");
852
853        zstr_free (&name);
854        zstr_free (&peerid);
855        zstr_free (&command);
856
857        zyre_stop (node3);
858        zyre_stop (node4);
859
860        // give things a chance to settle...
861        zclock_sleep (250);
862
863        zyre_destroy(&node3);
864        zyre_destroy(&node4);
865
866        zcert_destroy(&node3_cert);
867        zcert_destroy(&node4_cert);
868
869        // test gossip
870        if (verbose)
871            zsys_debug ("----------------TESTING GOSSIP----------------");
872
873        zyre_t *node5 = zyre_new ("node5");
874        zyre_t *node6 = zyre_new ("node6");
875
876        assert (node5);
877        assert (node6);
878
879        if (verbose) {
880            zyre_set_verbose (node5);
881            zyre_set_verbose (node6);
882        }
883
884        // if it takes more than 10s, something probably went terribly wrong
885        zsock_set_rcvtimeo(node5->inbox, 10000);
886        zsock_set_rcvtimeo(node6->inbox, 10000);
887
888        zcert_t *node5_cert = zcert_new ();
889        zcert_t *node6_cert = zcert_new ();
890
891        assert (node5_cert);
892        assert (node6_cert);
893
894        zyre_set_zcert(node5, node5_cert);
895        zyre_set_zcert(node6, node6_cert);
896
897        zyre_set_header(node5, "X-PUBLICKEY", "%s", zcert_public_txt(node5_cert));
898        zyre_set_header(node6, "X-PUBLICKEY", "%s", zcert_public_txt(node6_cert));
899
900        // TODO- set_advertised_endpoint tests
901    //        zyre_set_endpoint(node5, "tcp://127.0.0.1:9001");
902    //        zyre_set_advertised_endpoint(node5, "tcp://localhost:9001");
903
904        const char *gossip_cert = zcert_public_txt (node5_cert);
905
906        // TODO- need to add zyre_gossip_port functions to get port from gossip bind(?)
907        zyre_gossip_bind(node5, "tcp://127.0.0.1:9001");
908        zyre_gossip_connect_curve(node6, gossip_cert, "tcp://127.0.0.1:9001");
909
910        rc = zyre_start (node5);
911        assert (rc == 0);
912
913        rc = zyre_start (node6);
914        assert (rc == 0);
915
916        zyre_join (node5, "GLOBAL");
917        zyre_join (node6, "GLOBAL");
918
919        // give things a chance to settle...
920        zclock_sleep (1500);
921
922        if (verbose) {
923            zyre_dump (node5);
924            zyre_dump (node6);
925        }
926
927        zyre_shouts (node5, "GLOBAL", "Hello, World");
928
929        //  Second node should receive ENTER, JOIN, and SHOUT
930        msg = zyre_recv (node6);
931        assert (msg);
932        command = zmsg_popstr (msg);
933        assert (streq (command, "ENTER"));
934        zstr_free (&command);
935
936        peerid = zmsg_popstr (msg);
937        assert (peerid);
938        name = zmsg_popstr (msg);
939        zmsg_destroy (&msg);
940
941        assert (streq (name, "node5"));
942        zstr_free (&name);
943
944        zyre_leave (node5, "GLOBAL");
945        zyre_leave (node6, "GLOBAL");
946
947        zyre_stop (node5);
948        zyre_stop (node6);
949
950        // give things a chance to settle...
951        zclock_sleep (250);
952
953        zstr_free (&peerid);
954
955        zcert_destroy (&node5_cert);
956        zcert_destroy (&node6_cert);
957
958        zyre_destroy (&node5);
959        zyre_destroy (&node6);
960        zactor_destroy (&auth);
961
962        printf ("OK\n");
963
964    }
965    #endif
966    }
967```
968
969#### zyre_event - no title found
970
971This class provides a higher-level API to the zyre_recv call, by doing
972work that you will want to do in many cases, such as unpacking the peer
973headers for each ENTER event received.
974
975Please add '@discuss' section in './../src/zyre_event.c'.
976
977This is the class interface:
978
979```h
980    //  This is a stable class, and may not change except for emergencies. It
981    //  is provided in stable builds.
982    //  Constructor: receive an event from the zyre node, wraps zyre_recv.
983    //  The event may be a control message (ENTER, EXIT, JOIN, LEAVE) or
984    //  data (WHISPER, SHOUT).
985    ZYRE_EXPORT zyre_event_t *
986        zyre_event_new (zyre_t *node);
987
988    //  Destructor; destroys an event instance
989    ZYRE_EXPORT void
990        zyre_event_destroy (zyre_event_t **self_p);
991
992    //  Returns event type, as printable uppercase string. Choices are:
993    //  "ENTER", "EXIT", "JOIN", "LEAVE", "EVASIVE", "WHISPER" and "SHOUT"
994    //  and for the local node: "STOP"
995    ZYRE_EXPORT const char *
996        zyre_event_type (zyre_event_t *self);
997
998    //  Return the sending peer's uuid as a string
999    ZYRE_EXPORT const char *
1000        zyre_event_peer_uuid (zyre_event_t *self);
1001
1002    //  Return the sending peer's public name as a string
1003    ZYRE_EXPORT const char *
1004        zyre_event_peer_name (zyre_event_t *self);
1005
1006    //  Return the sending peer's ipaddress as a string
1007    ZYRE_EXPORT const char *
1008        zyre_event_peer_addr (zyre_event_t *self);
1009
1010    //  Returns the event headers, or NULL if there are none
1011    ZYRE_EXPORT zhash_t *
1012        zyre_event_headers (zyre_event_t *self);
1013
1014    //  Returns value of a header from the message headers
1015    //  obtained by ENTER. Return NULL if no value was found.
1016    ZYRE_EXPORT const char *
1017        zyre_event_header (zyre_event_t *self, const char *name);
1018
1019    //  Returns the group name that a SHOUT event was sent to
1020    ZYRE_EXPORT const char *
1021        zyre_event_group (zyre_event_t *self);
1022
1023    //  Returns the incoming message payload; the caller can modify the
1024    //  message but does not own it and should not destroy it.
1025    ZYRE_EXPORT zmsg_t *
1026        zyre_event_msg (zyre_event_t *self);
1027
1028    //  Returns the incoming message payload, and pass ownership to the
1029    //  caller. The caller must destroy the message when finished with it.
1030    //  After called on the given event, further calls will return NULL.
1031    //  Caller owns return value and must destroy it when done.
1032    ZYRE_EXPORT zmsg_t *
1033        zyre_event_get_msg (zyre_event_t *self);
1034
1035    //  Print event to zsys log
1036    ZYRE_EXPORT void
1037        zyre_event_print (zyre_event_t *self);
1038
1039    //  Self test of this class.
1040    ZYRE_EXPORT void
1041        zyre_event_test (bool verbose);
1042
1043```
1044Please add '@interface' section in './../src/zyre_event.c'.
1045
1046This is the class self test code:
1047
1048```c
1049    //  Create two nodes
1050    zyre_t *node1 = zyre_new ("node1");
1051    assert (node1);
1052    zyre_set_header (node1, "X-HELLO", "World");
1053    int rc = zyre_set_endpoint (node1, "inproc://zyre-node1");
1054    assert (rc == 0);
1055    // use gossiping instead of beaconing, suits Travis better
1056    zyre_gossip_bind (node1, "inproc://gossip-hub");
1057    if (verbose)
1058        zyre_set_verbose (node1);
1059    if (zyre_start (node1)) {
1060        zyre_destroy (&node1);
1061        printf ("OK (skipping test, no UDP discovery)\n");
1062        return;
1063    }
1064    zyre_join (node1, "GLOBAL");
1065
1066    zyre_t *node2 = zyre_new ("node2");
1067    assert (node2);
1068    if (verbose)
1069        zyre_set_verbose (node2);
1070    rc = zyre_set_endpoint (node2, "inproc://zyre-node2");
1071    assert (rc == 0);
1072    // use gossiping instead of beaconing, suits Travis better
1073    zyre_gossip_connect (node2, "inproc://gossip-hub");
1074    rc = zyre_start (node2);
1075    assert (rc == 0);
1076    zyre_join (node2, "GLOBAL");
1077
1078    //  Give time for them to interconnect
1079    zclock_sleep (250);
1080
1081    //  One node shouts to GLOBAL
1082    zmsg_t *msg = zmsg_new ();
1083    zmsg_addstr (msg, "Hello, World");
1084    zyre_shout (node1, "GLOBAL", &msg);
1085    zclock_sleep (100);
1086
1087    //  Parse ENTER
1088    zyre_event_t *event = zyre_event_new (node2);
1089    assert (streq (zyre_event_type (event), "ENTER"));
1090    const char *sender = zyre_event_peer_uuid (event);
1091    assert (sender);
1092    const char *name = zyre_event_peer_name (event);
1093    assert (name);
1094    assert (streq (name, "node1"));
1095    const char *address = zyre_event_peer_addr (event);
1096    assert (address);
1097    const char *header = zyre_event_header (event, "X-HELLO");
1098    assert (header);
1099    zyre_event_destroy (&event);
1100
1101    //  Parse JOIN
1102    //  We tolerate other events, which we can get if there are instances
1103    //  of Zyre running somewhere on the network.
1104    event = zyre_event_new (node2);
1105    if (streq (zyre_event_type (event), "JOIN")) {
1106        //  Parse SHOUT
1107        zyre_event_destroy (&event);
1108        event = zyre_event_new (node2);
1109        if (streq (zyre_event_type (event), "SHOUT")) {
1110            assert (streq (zyre_event_group (event), "GLOBAL"));
1111            zmsg_t *msg = zyre_event_get_msg (event);
1112            char *string = zmsg_popstr (msg);
1113            zmsg_destroy (&msg);
1114            assert (streq (string, "Hello, World"));
1115            free (string);
1116        }
1117        zyre_event_destroy (&event);
1118    }
1119    zyre_destroy (&node1);
1120    zyre_destroy (&node2);
1121```
1122
1123
1124### Hints to Contributors
1125
1126Zyre 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.
1127
1128Don't include system headers in source files. The right place for these is CZMQ.
1129
1130Do 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.
1131
1132Before opening a pull request read our [contribution guidelines](https://github.com/zeromq/zyre/blob/master/CONTRIBUTING.md). Thanks!
1133
1134### This Document
1135
1136_This documentation was generated from zyre/README.txt using [Gitdown](https://github.com/zeromq/gitdown)_
1137