rbczmq 1.6.2 → 1.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -3
- data/.gitmodules +6 -0
- data/.travis.yml +5 -1
- data/CHANGELOG.rdoc +15 -0
- data/Gemfile.lock +2 -2
- data/README.rdoc +5 -2
- data/Rakefile +8 -3
- data/ext/czmq/.gitignore +52 -0
- data/ext/czmq/.travis.yml +18 -0
- data/ext/czmq/AUTHORS +9 -0
- data/ext/czmq/COPYING +674 -0
- data/ext/czmq/COPYING.LESSER +178 -0
- data/ext/czmq/ChangeLog +0 -0
- data/ext/czmq/Makefile.am +22 -0
- data/ext/czmq/NEWS +263 -0
- data/ext/czmq/README +0 -0
- data/ext/czmq/README.md +1122 -0
- data/ext/czmq/README.txt +327 -0
- data/ext/czmq/autogen.sh +46 -0
- data/ext/czmq/builds/android/Android.mk +35 -0
- data/ext/czmq/builds/android/Application.mk +1 -0
- data/ext/czmq/builds/android/build.sh +59 -0
- data/ext/czmq/builds/android/clean.sh +26 -0
- data/ext/czmq/builds/mingw32/Makefile.mingw32 +38 -0
- data/ext/czmq/builds/mingw32/platform.h +0 -0
- data/ext/czmq/builds/msvc/.gitignore +18 -0
- data/ext/czmq/builds/msvc/README.txt +17 -0
- data/ext/czmq/builds/msvc/czmq.sln +69 -0
- data/ext/czmq/builds/msvc/czmq.vcproj +2246 -0
- data/ext/czmq/builds/msvc/czmq.vcxproj +329 -0
- data/ext/czmq/builds/msvc/czmq.vcxproj.filters +117 -0
- data/ext/czmq/builds/msvc/czmq11.sln +36 -0
- data/ext/czmq/builds/msvc/czmq_selftest.vcproj +840 -0
- data/ext/czmq/builds/msvc/czmq_selftest.vcxproj +189 -0
- data/ext/czmq/builds/msvc/czmq_selftest.vcxproj.filters +14 -0
- data/ext/czmq/c +520 -0
- data/ext/czmq/configure.ac +229 -0
- data/ext/czmq/doc/Makefile.am +49 -0
- data/ext/czmq/doc/asciidoc.conf +57 -0
- data/ext/czmq/doc/czmq.txt +334 -0
- data/ext/czmq/doc/mkman +100 -0
- data/ext/czmq/doc/mksite +65 -0
- data/ext/czmq/doc/wdput +43 -0
- data/ext/czmq/doc/xml2wd.pl +242 -0
- data/ext/czmq/doc/zbeacon.txt +173 -0
- data/ext/czmq/doc/zclock.txt +51 -0
- data/ext/czmq/doc/zconfig.txt +92 -0
- data/ext/czmq/doc/zctx.txt +111 -0
- data/ext/czmq/doc/zfile.txt +77 -0
- data/ext/czmq/doc/zframe.txt +222 -0
- data/ext/czmq/doc/zhash.txt +225 -0
- data/ext/czmq/doc/zlist.txt +176 -0
- data/ext/czmq/doc/zloop.txt +106 -0
- data/ext/czmq/doc/zmsg.txt +315 -0
- data/ext/czmq/doc/zmutex.txt +54 -0
- data/ext/czmq/doc/zsocket.txt +110 -0
- data/ext/czmq/doc/zsockopt.txt +528 -0
- data/ext/czmq/doc/zstr.txt +80 -0
- data/ext/czmq/doc/zsys.txt +44 -0
- data/ext/czmq/doc/zthread.txt +126 -0
- data/ext/czmq/doc/ztree.txt +236 -0
- data/ext/czmq/images/README_1.png +0 -0
- data/ext/czmq/images/README_2.png +0 -0
- data/ext/czmq/include/czmq.h +64 -0
- data/ext/czmq/include/czmq_prelude.h +504 -0
- data/ext/czmq/include/zbeacon.h +91 -0
- data/ext/czmq/include/zclock.h +56 -0
- data/ext/czmq/include/zconfig.h +117 -0
- data/ext/czmq/include/zctx.h +96 -0
- data/ext/czmq/include/zfile.h +82 -0
- data/ext/czmq/include/zframe.h +145 -0
- data/ext/czmq/include/zhash.h +127 -0
- data/ext/czmq/include/zlist.h +113 -0
- data/ext/czmq/include/zloop.h +98 -0
- data/ext/czmq/include/zmsg.h +165 -0
- data/ext/czmq/include/zmutex.h +62 -0
- data/ext/czmq/include/zsocket.h +104 -0
- data/ext/czmq/include/zsockopt.h +249 -0
- data/ext/czmq/include/zstr.h +69 -0
- data/ext/czmq/include/zsys.h +66 -0
- data/ext/czmq/include/zthread.h +62 -0
- data/ext/czmq/include/ztree.h +133 -0
- data/ext/czmq/mkdoc +14 -0
- data/ext/czmq/model/generate +2 -0
- data/ext/czmq/model/sockopts.xml +101 -0
- data/ext/czmq/notes.txt +21 -0
- data/ext/czmq/scripts/sockopts.gsl +325 -0
- data/ext/czmq/src/Makefile.am +61 -0
- data/ext/czmq/src/czmq_selftest.c +60 -0
- data/ext/czmq/src/libczmq.pc.in +11 -0
- data/ext/czmq/src/selftest +7 -0
- data/ext/czmq/src/selftest.cfg +5 -0
- data/ext/czmq/src/valgrind.supp +14 -0
- data/ext/czmq/src/vg +2 -0
- data/ext/czmq/src/zbeacon.c +787 -0
- data/ext/czmq/src/zclock.c +143 -0
- data/ext/czmq/src/zconfig.c +691 -0
- data/ext/czmq/src/zctx.c +287 -0
- data/ext/czmq/src/zfile.c +237 -0
- data/ext/czmq/src/zframe.c +551 -0
- data/ext/czmq/src/zhash.c +664 -0
- data/ext/czmq/src/zlist.c +459 -0
- data/ext/czmq/src/zloop.c +496 -0
- data/ext/czmq/src/zmsg.c +854 -0
- data/ext/czmq/src/zmutex.c +134 -0
- data/ext/czmq/src/zsocket.c +313 -0
- data/ext/czmq/src/zsockopt.c +1756 -0
- data/ext/czmq/src/zstr.c +297 -0
- data/ext/czmq/src/zsys.c +136 -0
- data/ext/czmq/src/zthread.c +269 -0
- data/ext/czmq/src/ztree.c +888 -0
- data/ext/czmq/version.sh +21 -0
- data/ext/rbczmq/extconf.rb +1 -18
- data/ext/rbczmq/poller.c +4 -1
- data/ext/rbczmq/socket.c +28 -5
- data/ext/rbczmq/socket.h +1 -0
- data/ext/zeromq/AUTHORS +110 -0
- data/ext/zeromq/CMakeLists.txt +392 -0
- data/ext/zeromq/COPYING +674 -0
- data/ext/zeromq/COPYING.LESSER +179 -0
- data/ext/zeromq/INSTALL +246 -0
- data/ext/zeromq/MAINTAINERS +56 -0
- data/ext/zeromq/Makefile.am +40 -0
- data/ext/zeromq/NEWS +333 -0
- data/ext/zeromq/README +39 -0
- data/ext/zeromq/acinclude.m4 +930 -0
- data/ext/zeromq/autogen.sh +45 -0
- data/ext/zeromq/branding.bmp +0 -0
- data/ext/zeromq/builds/msvc/Makefile.am +33 -0
- data/ext/zeromq/builds/msvc/c_local_lat/c_local_lat.vcproj +176 -0
- data/ext/zeromq/builds/msvc/c_local_lat/c_local_lat.vcxproj +87 -0
- data/ext/zeromq/builds/msvc/c_local_thr/c_local_thr.vcproj +176 -0
- data/ext/zeromq/builds/msvc/c_local_thr/c_local_thr.vcxproj +87 -0
- data/ext/zeromq/builds/msvc/c_remote_lat/c_remote_lat.vcproj +176 -0
- data/ext/zeromq/builds/msvc/c_remote_lat/c_remote_lat.vcxproj +87 -0
- data/ext/zeromq/builds/msvc/c_remote_thr/c_remote_thr.vcproj +176 -0
- data/ext/zeromq/builds/msvc/c_remote_thr/c_remote_thr.vcxproj +87 -0
- data/ext/zeromq/builds/msvc/errno.cpp +32 -0
- data/ext/zeromq/builds/msvc/errno.hpp +56 -0
- data/ext/zeromq/builds/msvc/inproc_lat/inproc_lat.vcproj +174 -0
- data/ext/zeromq/builds/msvc/inproc_lat/inproc_lat.vcxproj +86 -0
- data/ext/zeromq/builds/msvc/inproc_thr/inproc_thr.vcproj +174 -0
- data/ext/zeromq/builds/msvc/inproc_thr/inproc_thr.vcxproj +86 -0
- data/ext/zeromq/builds/msvc/libzmq/libzmq.vcproj +804 -0
- data/ext/zeromq/builds/msvc/libzmq/libzmq.vcxproj +252 -0
- data/ext/zeromq/builds/msvc/libzmq/libzmq.vcxproj.filters +431 -0
- data/ext/zeromq/builds/msvc/msvc.sln +89 -0
- data/ext/zeromq/builds/msvc/msvc10.sln +116 -0
- data/ext/zeromq/builds/msvc/platform.hpp +32 -0
- data/ext/zeromq/builds/msvc/properties/Common.props +21 -0
- data/ext/zeromq/builds/msvc/properties/Debug.props +19 -0
- data/ext/zeromq/builds/msvc/properties/Dynamic.props +20 -0
- data/ext/zeromq/builds/msvc/properties/Executable.props +19 -0
- data/ext/zeromq/builds/msvc/properties/Precompiled.props +14 -0
- data/ext/zeromq/builds/msvc/properties/Release.props +22 -0
- data/ext/zeromq/builds/msvc/properties/Win32.props +12 -0
- data/ext/zeromq/builds/msvc/properties/Win32_Release.props +17 -0
- data/ext/zeromq/builds/msvc/properties/WithOpenPGM.props +12 -0
- data/ext/zeromq/builds/msvc/properties/ZeroMQ.props +23 -0
- data/ext/zeromq/builds/msvc/properties/x64.props +12 -0
- data/ext/zeromq/builds/redhat/zeromq.spec.in +160 -0
- data/ext/zeromq/builds/valgrind/valgrind.supp +14 -0
- data/ext/zeromq/builds/valgrind/vg +1 -0
- data/ext/zeromq/cmake/Modules/TestZMQVersion.cmake +35 -0
- data/ext/zeromq/cmake/Modules/zmq_version.cpp +31 -0
- data/ext/zeromq/cmake/NSIS.template32.in +952 -0
- data/ext/zeromq/cmake/NSIS.template64.in +960 -0
- data/ext/zeromq/configure.in +428 -0
- data/ext/zeromq/doc/Makefile.am +51 -0
- data/ext/zeromq/doc/asciidoc.conf +56 -0
- data/ext/zeromq/doc/zmq.txt +233 -0
- data/ext/zeromq/doc/zmq_bind.txt +102 -0
- data/ext/zeromq/doc/zmq_close.txt +52 -0
- data/ext/zeromq/doc/zmq_connect.txt +98 -0
- data/ext/zeromq/doc/zmq_ctx_destroy.txt +66 -0
- data/ext/zeromq/doc/zmq_ctx_get.txt +67 -0
- data/ext/zeromq/doc/zmq_ctx_new.txt +49 -0
- data/ext/zeromq/doc/zmq_ctx_set.txt +75 -0
- data/ext/zeromq/doc/zmq_disconnect.txt +67 -0
- data/ext/zeromq/doc/zmq_epgm.txt +162 -0
- data/ext/zeromq/doc/zmq_errno.txt +50 -0
- data/ext/zeromq/doc/zmq_getsockopt.txt +516 -0
- data/ext/zeromq/doc/zmq_init.txt +52 -0
- data/ext/zeromq/doc/zmq_inproc.txt +85 -0
- data/ext/zeromq/doc/zmq_ipc.txt +85 -0
- data/ext/zeromq/doc/zmq_msg_close.txt +55 -0
- data/ext/zeromq/doc/zmq_msg_copy.txt +57 -0
- data/ext/zeromq/doc/zmq_msg_data.txt +48 -0
- data/ext/zeromq/doc/zmq_msg_get.txt +72 -0
- data/ext/zeromq/doc/zmq_msg_init.txt +65 -0
- data/ext/zeromq/doc/zmq_msg_init_data.txt +85 -0
- data/ext/zeromq/doc/zmq_msg_init_size.txt +58 -0
- data/ext/zeromq/doc/zmq_msg_more.txt +63 -0
- data/ext/zeromq/doc/zmq_msg_move.txt +52 -0
- data/ext/zeromq/doc/zmq_msg_recv.txt +125 -0
- data/ext/zeromq/doc/zmq_msg_send.txt +122 -0
- data/ext/zeromq/doc/zmq_msg_set.txt +45 -0
- data/ext/zeromq/doc/zmq_msg_size.txt +48 -0
- data/ext/zeromq/doc/zmq_pgm.txt +162 -0
- data/ext/zeromq/doc/zmq_poll.txt +132 -0
- data/ext/zeromq/doc/zmq_proxy.txt +97 -0
- data/ext/zeromq/doc/zmq_recv.txt +93 -0
- data/ext/zeromq/doc/zmq_recvmsg.txt +123 -0
- data/ext/zeromq/doc/zmq_send.txt +100 -0
- data/ext/zeromq/doc/zmq_sendmsg.txt +119 -0
- data/ext/zeromq/doc/zmq_setsockopt.txt +523 -0
- data/ext/zeromq/doc/zmq_socket.txt +369 -0
- data/ext/zeromq/doc/zmq_socket_monitor.txt +288 -0
- data/ext/zeromq/doc/zmq_strerror.txt +55 -0
- data/ext/zeromq/doc/zmq_tcp.txt +101 -0
- data/ext/zeromq/doc/zmq_term.txt +66 -0
- data/ext/zeromq/doc/zmq_unbind.txt +65 -0
- data/ext/zeromq/doc/zmq_version.txt +53 -0
- data/ext/zeromq/foreign/openpgm/Makefile.am +8 -0
- data/ext/zeromq/foreign/openpgm/libpgm-5.1.118~dfsg.tar.gz +0 -0
- data/ext/zeromq/include/zmq.h +402 -0
- data/ext/zeromq/include/zmq_utils.h +64 -0
- data/ext/zeromq/installer.ico +0 -0
- data/ext/zeromq/perf/Makefile.am +22 -0
- data/ext/zeromq/perf/inproc_lat.cpp +233 -0
- data/ext/zeromq/perf/inproc_thr.cpp +241 -0
- data/ext/zeromq/perf/local_lat.cpp +109 -0
- data/ext/zeromq/perf/local_thr.cpp +133 -0
- data/ext/zeromq/perf/remote_lat.cpp +122 -0
- data/ext/zeromq/perf/remote_thr.cpp +105 -0
- data/ext/zeromq/src/Makefile.am +171 -0
- data/ext/zeromq/src/address.cpp +78 -0
- data/ext/zeromq/src/address.hpp +52 -0
- data/ext/zeromq/src/array.hpp +155 -0
- data/ext/zeromq/src/atomic_counter.hpp +197 -0
- data/ext/zeromq/src/atomic_ptr.hpp +196 -0
- data/ext/zeromq/src/blob.hpp +129 -0
- data/ext/zeromq/src/clock.cpp +147 -0
- data/ext/zeromq/src/clock.hpp +60 -0
- data/ext/zeromq/src/command.hpp +154 -0
- data/ext/zeromq/src/config.hpp +89 -0
- data/ext/zeromq/src/ctx.cpp +352 -0
- data/ext/zeromq/src/ctx.hpp +173 -0
- data/ext/zeromq/src/dealer.cpp +133 -0
- data/ext/zeromq/src/dealer.hpp +92 -0
- data/ext/zeromq/src/decoder.cpp +166 -0
- data/ext/zeromq/src/decoder.hpp +248 -0
- data/ext/zeromq/src/devpoll.cpp +190 -0
- data/ext/zeromq/src/devpoll.hpp +105 -0
- data/ext/zeromq/src/dist.cpp +194 -0
- data/ext/zeromq/src/dist.hpp +105 -0
- data/ext/zeromq/src/encoder.cpp +102 -0
- data/ext/zeromq/src/encoder.hpp +200 -0
- data/ext/zeromq/src/epoll.cpp +178 -0
- data/ext/zeromq/src/epoll.hpp +101 -0
- data/ext/zeromq/src/err.cpp +291 -0
- data/ext/zeromq/src/err.hpp +155 -0
- data/ext/zeromq/src/fd.hpp +45 -0
- data/ext/zeromq/src/fq.cpp +141 -0
- data/ext/zeromq/src/fq.hpp +74 -0
- data/ext/zeromq/src/i_decoder.hpp +49 -0
- data/ext/zeromq/src/i_encoder.hpp +55 -0
- data/ext/zeromq/src/i_engine.hpp +55 -0
- data/ext/zeromq/src/i_msg_sink.hpp +43 -0
- data/ext/zeromq/src/i_msg_source.hpp +44 -0
- data/ext/zeromq/src/i_poll_events.hpp +47 -0
- data/ext/zeromq/src/io_object.cpp +108 -0
- data/ext/zeromq/src/io_object.hpp +81 -0
- data/ext/zeromq/src/io_thread.cpp +104 -0
- data/ext/zeromq/src/io_thread.hpp +91 -0
- data/ext/zeromq/src/ip.cpp +109 -0
- data/ext/zeromq/src/ip.hpp +41 -0
- data/ext/zeromq/src/ipc_address.cpp +84 -0
- data/ext/zeromq/src/ipc_address.hpp +67 -0
- data/ext/zeromq/src/ipc_connecter.cpp +265 -0
- data/ext/zeromq/src/ipc_connecter.hpp +128 -0
- data/ext/zeromq/src/ipc_listener.cpp +206 -0
- data/ext/zeromq/src/ipc_listener.hpp +99 -0
- data/ext/zeromq/src/kqueue.cpp +201 -0
- data/ext/zeromq/src/kqueue.hpp +107 -0
- data/ext/zeromq/src/lb.cpp +148 -0
- data/ext/zeromq/src/lb.hpp +73 -0
- data/ext/zeromq/src/libzmq.pc.in +10 -0
- data/ext/zeromq/src/likely.hpp +33 -0
- data/ext/zeromq/src/mailbox.cpp +87 -0
- data/ext/zeromq/src/mailbox.hpp +75 -0
- data/ext/zeromq/src/msg.cpp +299 -0
- data/ext/zeromq/src/msg.hpp +148 -0
- data/ext/zeromq/src/mtrie.cpp +428 -0
- data/ext/zeromq/src/mtrie.hpp +93 -0
- data/ext/zeromq/src/mutex.hpp +118 -0
- data/ext/zeromq/src/object.cpp +393 -0
- data/ext/zeromq/src/object.hpp +134 -0
- data/ext/zeromq/src/options.cpp +562 -0
- data/ext/zeromq/src/options.hpp +135 -0
- data/ext/zeromq/src/own.cpp +206 -0
- data/ext/zeromq/src/own.hpp +145 -0
- data/ext/zeromq/src/pair.cpp +136 -0
- data/ext/zeromq/src/pair.hpp +79 -0
- data/ext/zeromq/src/pgm_receiver.cpp +283 -0
- data/ext/zeromq/src/pgm_receiver.hpp +141 -0
- data/ext/zeromq/src/pgm_sender.cpp +218 -0
- data/ext/zeromq/src/pgm_sender.hpp +113 -0
- data/ext/zeromq/src/pgm_socket.cpp +706 -0
- data/ext/zeromq/src/pgm_socket.hpp +124 -0
- data/ext/zeromq/src/pipe.cpp +447 -0
- data/ext/zeromq/src/pipe.hpp +207 -0
- data/ext/zeromq/src/poll.cpp +176 -0
- data/ext/zeromq/src/poll.hpp +105 -0
- data/ext/zeromq/src/poller.hpp +82 -0
- data/ext/zeromq/src/poller_base.cpp +99 -0
- data/ext/zeromq/src/poller_base.hpp +86 -0
- data/ext/zeromq/src/precompiled.cpp +21 -0
- data/ext/zeromq/src/precompiled.hpp +47 -0
- data/ext/zeromq/src/proxy.cpp +150 -0
- data/ext/zeromq/src/proxy.hpp +32 -0
- data/ext/zeromq/src/pub.cpp +57 -0
- data/ext/zeromq/src/pub.hpp +69 -0
- data/ext/zeromq/src/pull.cpp +79 -0
- data/ext/zeromq/src/pull.hpp +81 -0
- data/ext/zeromq/src/push.cpp +76 -0
- data/ext/zeromq/src/push.hpp +80 -0
- data/ext/zeromq/src/random.cpp +52 -0
- data/ext/zeromq/src/random.hpp +37 -0
- data/ext/zeromq/src/reaper.cpp +117 -0
- data/ext/zeromq/src/reaper.hpp +80 -0
- data/ext/zeromq/src/rep.cpp +137 -0
- data/ext/zeromq/src/rep.hpp +80 -0
- data/ext/zeromq/src/req.cpp +185 -0
- data/ext/zeromq/src/req.hpp +91 -0
- data/ext/zeromq/src/router.cpp +364 -0
- data/ext/zeromq/src/router.hpp +138 -0
- data/ext/zeromq/src/select.cpp +216 -0
- data/ext/zeromq/src/select.hpp +126 -0
- data/ext/zeromq/src/session_base.cpp +503 -0
- data/ext/zeromq/src/session_base.hpp +156 -0
- data/ext/zeromq/src/signaler.cpp +406 -0
- data/ext/zeromq/src/signaler.hpp +63 -0
- data/ext/zeromq/src/socket_base.cpp +1236 -0
- data/ext/zeromq/src/socket_base.hpp +255 -0
- data/ext/zeromq/src/stdint.hpp +63 -0
- data/ext/zeromq/src/stream_engine.cpp +594 -0
- data/ext/zeromq/src/stream_engine.hpp +149 -0
- data/ext/zeromq/src/sub.cpp +93 -0
- data/ext/zeromq/src/sub.hpp +71 -0
- data/ext/zeromq/src/tcp.cpp +131 -0
- data/ext/zeromq/src/tcp.hpp +38 -0
- data/ext/zeromq/src/tcp_address.cpp +613 -0
- data/ext/zeromq/src/tcp_address.hpp +100 -0
- data/ext/zeromq/src/tcp_connecter.cpp +319 -0
- data/ext/zeromq/src/tcp_connecter.hpp +123 -0
- data/ext/zeromq/src/tcp_listener.cpp +293 -0
- data/ext/zeromq/src/tcp_listener.hpp +91 -0
- data/ext/zeromq/src/thread.cpp +107 -0
- data/ext/zeromq/src/thread.hpp +79 -0
- data/ext/zeromq/src/trie.cpp +337 -0
- data/ext/zeromq/src/trie.hpp +79 -0
- data/ext/zeromq/src/v1_decoder.cpp +162 -0
- data/ext/zeromq/src/v1_decoder.hpp +68 -0
- data/ext/zeromq/src/v1_encoder.cpp +103 -0
- data/ext/zeromq/src/v1_encoder.hpp +60 -0
- data/ext/zeromq/src/v1_protocol.hpp +43 -0
- data/ext/zeromq/src/version.rc.in +93 -0
- data/ext/zeromq/src/windows.hpp +181 -0
- data/ext/zeromq/src/wire.hpp +99 -0
- data/ext/zeromq/src/xpub.cpp +200 -0
- data/ext/zeromq/src/xpub.hpp +110 -0
- data/ext/zeromq/src/xsub.cpp +242 -0
- data/ext/zeromq/src/xsub.hpp +108 -0
- data/ext/zeromq/src/ypipe.hpp +210 -0
- data/ext/zeromq/src/yqueue.hpp +199 -0
- data/ext/zeromq/src/zmq.cpp +1058 -0
- data/ext/zeromq/src/zmq_utils.cpp +61 -0
- data/ext/zeromq/tests/Makefile.am +55 -0
- data/ext/zeromq/tests/test_connect_delay.cpp +260 -0
- data/ext/zeromq/tests/test_connect_resolve.cpp +54 -0
- data/ext/zeromq/tests/test_disconnect_inproc.cpp +120 -0
- data/ext/zeromq/tests/test_hwm.cpp +83 -0
- data/ext/zeromq/tests/test_invalid_rep.cpp +92 -0
- data/ext/zeromq/tests/test_last_endpoint.cpp +60 -0
- data/ext/zeromq/tests/test_monitor.cpp +289 -0
- data/ext/zeromq/tests/test_msg_flags.cpp +78 -0
- data/ext/zeromq/tests/test_pair_inproc.cpp +53 -0
- data/ext/zeromq/tests/test_pair_ipc.cpp +53 -0
- data/ext/zeromq/tests/test_pair_tcp.cpp +54 -0
- data/ext/zeromq/tests/test_reqrep_device.cpp +143 -0
- data/ext/zeromq/tests/test_reqrep_inproc.cpp +53 -0
- data/ext/zeromq/tests/test_reqrep_ipc.cpp +53 -0
- data/ext/zeromq/tests/test_reqrep_tcp.cpp +54 -0
- data/ext/zeromq/tests/test_router_mandatory.cpp +62 -0
- data/ext/zeromq/tests/test_shutdown_stress.cpp +93 -0
- data/ext/zeromq/tests/test_sub_forward.cpp +99 -0
- data/ext/zeromq/tests/test_term_endpoint.cpp +118 -0
- data/ext/zeromq/tests/test_timeo.cpp +119 -0
- data/ext/zeromq/tests/testutil.hpp +77 -0
- data/ext/zeromq/version.sh +21 -0
- data/lib/zmq/version.rb +1 -1
- data/rbczmq.gemspec +16 -3
- data/test/test_socket.rb +13 -1
- metadata +398 -9
- checksums.yaml +0 -15
- data/ext/czmq-1.4.1.tar.gz +0 -0
- data/ext/zeromq-3.2.3.tar.gz +0 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
lib_LTLIBRARIES = libczmq.la
|
2
|
+
|
3
|
+
pkgconfigdir = $(libdir)/pkgconfig
|
4
|
+
pkgconfig_DATA = libczmq.pc
|
5
|
+
|
6
|
+
include_HEADERS = \
|
7
|
+
../include/czmq.h \
|
8
|
+
../include/czmq_prelude.h \
|
9
|
+
../include/zbeacon.h \
|
10
|
+
../include/zclock.h \
|
11
|
+
../include/zconfig.h \
|
12
|
+
../include/zctx.h \
|
13
|
+
../include/zfile.h \
|
14
|
+
../include/zframe.h \
|
15
|
+
../include/zhash.h \
|
16
|
+
../include/zlist.h \
|
17
|
+
../include/zloop.h \
|
18
|
+
../include/zmsg.h \
|
19
|
+
../include/zmutex.h \
|
20
|
+
../include/zsocket.h \
|
21
|
+
../include/zsockopt.h \
|
22
|
+
../include/zstr.h \
|
23
|
+
../include/zsys.h \
|
24
|
+
../include/zthread.h \
|
25
|
+
../include/ztree.h
|
26
|
+
|
27
|
+
libczmq_la_SOURCES = \
|
28
|
+
zbeacon.c \
|
29
|
+
zclock.c \
|
30
|
+
zconfig.c \
|
31
|
+
zctx.c \
|
32
|
+
zfile.c \
|
33
|
+
zframe.c \
|
34
|
+
zhash.c \
|
35
|
+
zlist.c \
|
36
|
+
zloop.c \
|
37
|
+
zmsg.c \
|
38
|
+
zmutex.c \
|
39
|
+
zsocket.c \
|
40
|
+
zsockopt.c \
|
41
|
+
zstr.c \
|
42
|
+
zsys.c \
|
43
|
+
zthread.c \
|
44
|
+
ztree.c
|
45
|
+
|
46
|
+
AM_CFLAGS = -g
|
47
|
+
|
48
|
+
INCLUDES = -I$(top_srcdir)/include
|
49
|
+
bin_PROGRAMS = czmq_selftest
|
50
|
+
czmq_selftest_LDADD = libczmq.la
|
51
|
+
czmq_selftest_SOURCES = czmq_selftest.c
|
52
|
+
|
53
|
+
if ON_MINGW
|
54
|
+
libczmq_la_LDFLAGS = -no-undefined -avoid-version -version-info @LTVER@
|
55
|
+
else
|
56
|
+
libczmq_la_LDFLAGS = -version-info @LTVER@
|
57
|
+
endif
|
58
|
+
|
59
|
+
TESTS = czmq_selftest
|
60
|
+
|
61
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/* =========================================================================
|
2
|
+
czmq_tests.c - run selftests
|
3
|
+
|
4
|
+
Runs all selftests.
|
5
|
+
|
6
|
+
-------------------------------------------------------------------------
|
7
|
+
Copyright (c) 1991-2013 iMatix Corporation <www.imatix.com>
|
8
|
+
Copyright other contributors as noted in the AUTHORS file.
|
9
|
+
|
10
|
+
This file is part of czmq, the high-level C binding for 0MQ:
|
11
|
+
http://czmq.zeromq.org.
|
12
|
+
|
13
|
+
This is free software; you can redistribute it and/or modify it under
|
14
|
+
the terms of the GNU Lesser General Public License as published by
|
15
|
+
the Free Software Foundation; either version 3 of the License, or (at
|
16
|
+
your option) any later version.
|
17
|
+
|
18
|
+
This software is distributed in the hope that it will be useful, but
|
19
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
20
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
21
|
+
Lesser General Public License for more details.
|
22
|
+
|
23
|
+
You should have received a copy of the GNU Lesser General Public
|
24
|
+
License along with this program. If not, see
|
25
|
+
<http://www.gnu.org/licenses/>.
|
26
|
+
=========================================================================
|
27
|
+
*/
|
28
|
+
|
29
|
+
#include "../include/czmq.h"
|
30
|
+
|
31
|
+
int main (int argc, char *argv [])
|
32
|
+
{
|
33
|
+
bool verbose;
|
34
|
+
if (argc == 2 && streq (argv [1], "-v"))
|
35
|
+
verbose = true;
|
36
|
+
else
|
37
|
+
verbose = false;
|
38
|
+
|
39
|
+
printf ("Running czmq self tests...\n");
|
40
|
+
|
41
|
+
zclock_test (verbose);
|
42
|
+
zconfig_test (verbose);
|
43
|
+
zctx_test (verbose);
|
44
|
+
zfile_test (verbose);
|
45
|
+
zframe_test (verbose);
|
46
|
+
zhash_test (verbose);
|
47
|
+
ztree_test (verbose);
|
48
|
+
zlist_test (verbose);
|
49
|
+
zloop_test (verbose);
|
50
|
+
zmsg_test (verbose);
|
51
|
+
zmutex_test (verbose);
|
52
|
+
zsocket_test (verbose);
|
53
|
+
zsockopt_test (verbose);
|
54
|
+
zstr_test (verbose);
|
55
|
+
zsys_test (verbose);
|
56
|
+
zthread_test (verbose);
|
57
|
+
zbeacon_test (verbose);
|
58
|
+
printf ("Tests passed OK\n");
|
59
|
+
return 0;
|
60
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Run selftests and check memory
|
2
|
+
echo "Rebuilding czmq..."
|
3
|
+
gcc -g -o czmq_selftest czmq_selftest.c z*.c ${CFLAGS} ${LDFLAGS} -lzmq -lpthread
|
4
|
+
if [ $? -eq 0 ]; then
|
5
|
+
echo "Starting Valgrind memcheck..."
|
6
|
+
valgrind --tool=memcheck --leak-check=full --suppressions=valgrind.supp ./czmq_selftest
|
7
|
+
fi
|
data/ext/czmq/src/vg
ADDED
@@ -0,0 +1,787 @@
|
|
1
|
+
/* =========================================================================
|
2
|
+
zbeacon - LAN service announcement and discovery
|
3
|
+
|
4
|
+
-------------------------------------------------------------------------
|
5
|
+
Copyright (c) 1991-2013 iMatix Corporation <www.imatix.com>
|
6
|
+
Copyright other contributors as noted in the AUTHORS file.
|
7
|
+
|
8
|
+
This file is part of CZMQ, the high-level C binding for 0MQ:
|
9
|
+
http://czmq.zeromq.org.
|
10
|
+
|
11
|
+
This is free software; you can redistribute it and/or modify it under
|
12
|
+
the terms of the GNU Lesser General Public License as published by the
|
13
|
+
Free Software Foundation; either version 3 of the License, or (at your
|
14
|
+
option) any later version.
|
15
|
+
|
16
|
+
This software is distributed in the hope that it will be useful, but
|
17
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABIL-
|
18
|
+
ITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
19
|
+
Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public License
|
22
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
=========================================================================
|
24
|
+
*/
|
25
|
+
|
26
|
+
/*
|
27
|
+
@header
|
28
|
+
The zbeacon class implements a peer-to-peer discovery service for local
|
29
|
+
networks. A beacon can broadcast and/or capture service announcements
|
30
|
+
using UDP messages on the local area network. This implementation uses
|
31
|
+
IPv4 UDP broadcasts. You can define the format of your outgoing beacons,
|
32
|
+
and set a filter that validates incoming beacons. Beacons are sent and
|
33
|
+
received asynchronously in the background. The zbeacon API provides a
|
34
|
+
incoming beacons on a ZeroMQ socket (the pipe) that you can configure,
|
35
|
+
poll on, and receive messages on. Incoming beacons are always delivered
|
36
|
+
as two frames: the ipaddress of the sender (a string), and the beacon
|
37
|
+
data itself (binary, as published).
|
38
|
+
@discuss
|
39
|
+
@end
|
40
|
+
*/
|
41
|
+
|
42
|
+
#include "../include/czmq.h"
|
43
|
+
#if !defined (__WINDOWS__)
|
44
|
+
# include "platform.h"
|
45
|
+
#endif
|
46
|
+
|
47
|
+
#if defined (HAVE_LINUX_WIRELESS_H)
|
48
|
+
# include <linux/wireless.h>
|
49
|
+
#else
|
50
|
+
# if defined (HAVE_NET_IF_H)
|
51
|
+
# include <net/if.h>
|
52
|
+
# endif
|
53
|
+
# if defined (HAVE_NET_IF_MEDIA_H)
|
54
|
+
# include <net/if_media.h>
|
55
|
+
# endif
|
56
|
+
#endif
|
57
|
+
|
58
|
+
#if defined (__UTYPE_SUNSOLARIS) || defined (__UTYPE_SUNOS)
|
59
|
+
# include <ifaddrs.h>
|
60
|
+
# include <sys/sockio.h>
|
61
|
+
#endif
|
62
|
+
|
63
|
+
#if defined (__WINDOWS__)
|
64
|
+
# if (_WIN32_WINNT < 0x0501)
|
65
|
+
# undef _WIN32_WINNT
|
66
|
+
# define _WIN32_WINNT 0x0501
|
67
|
+
# endif
|
68
|
+
# include <ws2tcpip.h> // For getnameinfo ()
|
69
|
+
# include <iphlpapi.h> // For GetAdaptersAddresses ()
|
70
|
+
#endif
|
71
|
+
|
72
|
+
// Windows uses
|
73
|
+
#if !defined (__WINDOWS__)
|
74
|
+
typedef int SOCKET;
|
75
|
+
# define closesocket close
|
76
|
+
# define INVALID_SOCKET -1
|
77
|
+
# define SOCKET_ERROR -1
|
78
|
+
#endif
|
79
|
+
|
80
|
+
// Constants
|
81
|
+
#define BEACON_MAX 255 // Max size of beacon data
|
82
|
+
#define INTERVAL_DFLT 1000 // Default interval = 1 second
|
83
|
+
|
84
|
+
// Internet socket address structure
|
85
|
+
typedef struct sockaddr_in inaddr_t;
|
86
|
+
|
87
|
+
// Structure of our class
|
88
|
+
struct _zbeacon_t {
|
89
|
+
zctx_t *ctx; // Private 0MQ context
|
90
|
+
void *pipe; // Pipe through to backend agent
|
91
|
+
char *hostname; // Our own address as string
|
92
|
+
};
|
93
|
+
|
94
|
+
|
95
|
+
// Background task does the real I/O
|
96
|
+
static void
|
97
|
+
s_agent_task (void *args, zctx_t *ctx, void *pipe);
|
98
|
+
|
99
|
+
|
100
|
+
// --------------------------------------------------------------------------
|
101
|
+
// Create a new beacon
|
102
|
+
|
103
|
+
zbeacon_t *
|
104
|
+
zbeacon_new (int port_nbr)
|
105
|
+
{
|
106
|
+
zbeacon_t *self = (zbeacon_t *) zmalloc (sizeof (zbeacon_t));
|
107
|
+
|
108
|
+
// For now, we use a context per beacon instance
|
109
|
+
self->ctx = zctx_new ();
|
110
|
+
|
111
|
+
// Start beacon background agent
|
112
|
+
self->pipe = zthread_fork (self->ctx, s_agent_task, NULL);
|
113
|
+
|
114
|
+
// Configure agent with arguments
|
115
|
+
zstr_send (self->pipe, "%d", port_nbr);
|
116
|
+
|
117
|
+
// Agent replies with our host name
|
118
|
+
self->hostname = zstr_recv (self->pipe);
|
119
|
+
|
120
|
+
return self;
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
// --------------------------------------------------------------------------
|
125
|
+
// Destructor
|
126
|
+
|
127
|
+
void
|
128
|
+
zbeacon_destroy (zbeacon_t **self_p)
|
129
|
+
{
|
130
|
+
assert (self_p);
|
131
|
+
if (*self_p) {
|
132
|
+
zbeacon_t *self = *self_p;
|
133
|
+
zstr_send (self->pipe, "TERMINATE");
|
134
|
+
free (zstr_recv (self->pipe));
|
135
|
+
zctx_destroy (&self->ctx);
|
136
|
+
free (self->hostname);
|
137
|
+
free (self);
|
138
|
+
*self_p = NULL;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
// --------------------------------------------------------------------------
|
144
|
+
// Set broadcast interval in milliseconds
|
145
|
+
|
146
|
+
void
|
147
|
+
zbeacon_set_interval (zbeacon_t *self, int interval)
|
148
|
+
{
|
149
|
+
assert (self);
|
150
|
+
zstr_sendm (self->pipe, "INTERVAL");
|
151
|
+
zstr_send (self->pipe, "%d", interval);
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
// --------------------------------------------------------------------------
|
156
|
+
// Filter out any beacon that looks exactly like ours
|
157
|
+
|
158
|
+
void
|
159
|
+
zbeacon_noecho (zbeacon_t *self)
|
160
|
+
{
|
161
|
+
assert (self);
|
162
|
+
zstr_send (self->pipe, "NOECHO");
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
// --------------------------------------------------------------------------
|
167
|
+
// Start broadcasting beacon to peers at the specified interval
|
168
|
+
|
169
|
+
void
|
170
|
+
zbeacon_publish (zbeacon_t *self, byte *transmit, size_t size)
|
171
|
+
{
|
172
|
+
assert (self);
|
173
|
+
assert (transmit);
|
174
|
+
assert (size > 0 && size <= BEACON_MAX);
|
175
|
+
zmsg_t *msg = zmsg_new ();
|
176
|
+
zmsg_addstr (msg, "PUBLISH");
|
177
|
+
zmsg_addmem (msg, transmit, size);
|
178
|
+
zmsg_send (&msg, self->pipe);
|
179
|
+
}
|
180
|
+
|
181
|
+
|
182
|
+
// --------------------------------------------------------------------------
|
183
|
+
// Stop broadcasting beacons
|
184
|
+
|
185
|
+
void
|
186
|
+
zbeacon_silence (zbeacon_t *self)
|
187
|
+
{
|
188
|
+
assert (self);
|
189
|
+
zstr_send (self->pipe, "SILENCE");
|
190
|
+
}
|
191
|
+
|
192
|
+
|
193
|
+
// --------------------------------------------------------------------------
|
194
|
+
// Start listening to other peers; zero-sized filter means get everything
|
195
|
+
|
196
|
+
void
|
197
|
+
zbeacon_subscribe (zbeacon_t *self, byte *filter, size_t size)
|
198
|
+
{
|
199
|
+
assert (self);
|
200
|
+
assert (size <= BEACON_MAX);
|
201
|
+
zmsg_t *msg = zmsg_new ();
|
202
|
+
zmsg_addstr (msg, "SUBSCRIBE");
|
203
|
+
zmsg_addmem (msg, filter, size);
|
204
|
+
zmsg_send (&msg, self->pipe);
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
// --------------------------------------------------------------------------
|
209
|
+
// Stop listening to other peers
|
210
|
+
|
211
|
+
void
|
212
|
+
zbeacon_unsubscribe (zbeacon_t *self)
|
213
|
+
{
|
214
|
+
zstr_send (self->pipe, "UNSUBSCRIBE");
|
215
|
+
}
|
216
|
+
|
217
|
+
|
218
|
+
// --------------------------------------------------------------------------
|
219
|
+
// Get beacon ZeroMQ socket, for polling or receiving messages
|
220
|
+
|
221
|
+
void *
|
222
|
+
zbeacon_socket (zbeacon_t *self)
|
223
|
+
{
|
224
|
+
assert (self);
|
225
|
+
return self->pipe;
|
226
|
+
}
|
227
|
+
|
228
|
+
|
229
|
+
// --------------------------------------------------------------------------
|
230
|
+
// Get beacon socket handle, for polling - DEPRECATED
|
231
|
+
|
232
|
+
void *
|
233
|
+
zbeacon_pipe (zbeacon_t *self)
|
234
|
+
{
|
235
|
+
assert (self);
|
236
|
+
return self->pipe;
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
// --------------------------------------------------------------------------
|
241
|
+
// Return our own IP address as printable string
|
242
|
+
|
243
|
+
char *
|
244
|
+
zbeacon_hostname (zbeacon_t *self)
|
245
|
+
{
|
246
|
+
assert (self);
|
247
|
+
return self->hostname;
|
248
|
+
}
|
249
|
+
|
250
|
+
|
251
|
+
// --------------------------------------------------------------------------
|
252
|
+
// Self test of this class
|
253
|
+
|
254
|
+
void
|
255
|
+
zbeacon_test (bool verbose)
|
256
|
+
{
|
257
|
+
printf (" * zbeacon: ");
|
258
|
+
|
259
|
+
// @selftest
|
260
|
+
// Basic test: create a service and announce it
|
261
|
+
zctx_t *ctx = zctx_new ();
|
262
|
+
|
263
|
+
// Create a service socket and bind to an ephemeral port
|
264
|
+
void *service = zsocket_new (ctx, ZMQ_PUB);
|
265
|
+
int port_nbr = zsocket_bind (service, "tcp://*:*");
|
266
|
+
|
267
|
+
// Create beacon to broadcast our service
|
268
|
+
byte announcement [2] = { (port_nbr >> 8) & 0xFF, port_nbr & 0xFF };
|
269
|
+
zbeacon_t *service_beacon = zbeacon_new (9999);
|
270
|
+
zbeacon_set_interval (service_beacon, 100);
|
271
|
+
zbeacon_publish (service_beacon, announcement, 2);
|
272
|
+
|
273
|
+
// Create beacon to lookup service
|
274
|
+
zbeacon_t *client_beacon = zbeacon_new (9999);
|
275
|
+
zbeacon_subscribe (client_beacon, NULL, 0);
|
276
|
+
|
277
|
+
// Wait for at most 1/2 second if there's no broadcast networking
|
278
|
+
zsocket_set_rcvtimeo (zbeacon_socket (client_beacon), 500);
|
279
|
+
|
280
|
+
char *ipaddress = zstr_recv (zbeacon_socket (client_beacon));
|
281
|
+
if (ipaddress) {
|
282
|
+
zframe_t *content = zframe_recv (zbeacon_socket (client_beacon));
|
283
|
+
int received_port = (zframe_data (content) [0] << 8)
|
284
|
+
+ zframe_data (content) [1];
|
285
|
+
assert (received_port == port_nbr);
|
286
|
+
zframe_destroy (&content);
|
287
|
+
free (ipaddress);
|
288
|
+
}
|
289
|
+
zbeacon_destroy (&client_beacon);
|
290
|
+
zbeacon_destroy (&service_beacon);
|
291
|
+
zctx_destroy (&ctx);
|
292
|
+
|
293
|
+
zbeacon_t *node1 = zbeacon_new (5670);
|
294
|
+
zbeacon_t *node2 = zbeacon_new (5670);
|
295
|
+
zbeacon_t *node3 = zbeacon_new (5670);
|
296
|
+
|
297
|
+
assert (*zbeacon_hostname (node1));
|
298
|
+
assert (*zbeacon_hostname (node2));
|
299
|
+
assert (*zbeacon_hostname (node3));
|
300
|
+
|
301
|
+
zbeacon_set_interval (node1, 250);
|
302
|
+
zbeacon_set_interval (node2, 250);
|
303
|
+
zbeacon_set_interval (node3, 250);
|
304
|
+
zbeacon_noecho (node1);
|
305
|
+
zbeacon_publish (node1, (byte *) "NODE/1", 6);
|
306
|
+
zbeacon_publish (node2, (byte *) "NODE/2", 6);
|
307
|
+
zbeacon_publish (node3, (byte *) "GARBAGE", 7);
|
308
|
+
zbeacon_subscribe (node1, (byte *) "NODE", 4);
|
309
|
+
|
310
|
+
// Poll on API pipe and on UDP socket
|
311
|
+
zmq_pollitem_t pollitems [] = {
|
312
|
+
{ zbeacon_socket (node1), 0, ZMQ_POLLIN, 0 },
|
313
|
+
{ zbeacon_socket (node2), 0, ZMQ_POLLIN, 0 },
|
314
|
+
{ zbeacon_socket (node3), 0, ZMQ_POLLIN, 0 }
|
315
|
+
};
|
316
|
+
uint64_t stop_at = zclock_time () + 1000;
|
317
|
+
while (zclock_time () < stop_at) {
|
318
|
+
long timeout = (long) (stop_at - zclock_time ());
|
319
|
+
if (timeout < 0)
|
320
|
+
timeout = 0;
|
321
|
+
if (zmq_poll (pollitems, 3, timeout * ZMQ_POLL_MSEC) == -1)
|
322
|
+
break; // Interrupted
|
323
|
+
|
324
|
+
// We cannot get messages on nodes 2 and 3
|
325
|
+
assert ((pollitems [1].revents & ZMQ_POLLIN) == 0);
|
326
|
+
assert ((pollitems [2].revents & ZMQ_POLLIN) == 0);
|
327
|
+
|
328
|
+
// If we get a message on node 1, it must be NODE/2
|
329
|
+
if (pollitems [0].revents & ZMQ_POLLIN) {
|
330
|
+
char *ipaddress = zstr_recv (zbeacon_socket (node1));
|
331
|
+
char *beacon = zstr_recv (zbeacon_socket (node1));
|
332
|
+
assert (streq (beacon, "NODE/2"));
|
333
|
+
free (ipaddress);
|
334
|
+
free (beacon);
|
335
|
+
}
|
336
|
+
}
|
337
|
+
// Stop listening
|
338
|
+
zbeacon_unsubscribe (node1);
|
339
|
+
|
340
|
+
// Stop all node broadcasts
|
341
|
+
zbeacon_silence (node1);
|
342
|
+
zbeacon_silence (node2);
|
343
|
+
zbeacon_silence (node3);
|
344
|
+
|
345
|
+
// Destroy the test nodes
|
346
|
+
zbeacon_destroy (&node1);
|
347
|
+
zbeacon_destroy (&node2);
|
348
|
+
zbeacon_destroy (&node3);
|
349
|
+
// @end
|
350
|
+
printf ("OK\n");
|
351
|
+
}
|
352
|
+
|
353
|
+
|
354
|
+
// --------------------------------------------------------------------------
|
355
|
+
// Backend agent implementation
|
356
|
+
|
357
|
+
// Agent instance
|
358
|
+
|
359
|
+
typedef struct {
|
360
|
+
void *pipe; // Socket to talk back to application
|
361
|
+
SOCKET udpsock; // UDP socket for send/recv
|
362
|
+
int port_nbr; // UDP port number we work on
|
363
|
+
int interval; // Beacon broadcast interval
|
364
|
+
bool enabled; // Are we broadcasting?
|
365
|
+
bool noecho; // Ignore own (unique) beacons?
|
366
|
+
bool terminated; // API shut us down
|
367
|
+
uint64_t ping_at; // Next broadcast time
|
368
|
+
zframe_t *transmit; // Beacon transmit data
|
369
|
+
zframe_t *filter; // Beacon filter data
|
370
|
+
inaddr_t address; // Our own address
|
371
|
+
inaddr_t broadcast; // Our broadcast address
|
372
|
+
} agent_t;
|
373
|
+
|
374
|
+
// Prototypes for local functions we use in the agent
|
375
|
+
|
376
|
+
static agent_t *
|
377
|
+
s_agent_new (void *pipe, int port_nbr);
|
378
|
+
static void
|
379
|
+
s_agent_destroy (agent_t **self_p);
|
380
|
+
static void
|
381
|
+
s_handle_io_error (char *reason);
|
382
|
+
static void
|
383
|
+
s_get_interface (agent_t *self);
|
384
|
+
static bool
|
385
|
+
s_wireless_nic (const char* name);
|
386
|
+
static void
|
387
|
+
s_api_command (agent_t *self);
|
388
|
+
static void
|
389
|
+
s_beacon_send (agent_t *self);
|
390
|
+
static void
|
391
|
+
s_beacon_recv (agent_t *self);
|
392
|
+
|
393
|
+
|
394
|
+
// This is the background task
|
395
|
+
|
396
|
+
static void
|
397
|
+
s_agent_task (void *args, zctx_t *ctx, void *pipe)
|
398
|
+
{
|
399
|
+
// Get port argument from caller
|
400
|
+
char *port_str = zstr_recv (pipe);
|
401
|
+
assert (port_str);
|
402
|
+
|
403
|
+
// Create agent instance
|
404
|
+
agent_t *self = s_agent_new (pipe, atoi (port_str));
|
405
|
+
free (port_str);
|
406
|
+
|
407
|
+
while (!zctx_interrupted) {
|
408
|
+
// Poll on API pipe and on UDP socket
|
409
|
+
zmq_pollitem_t pollitems [] = {
|
410
|
+
{ self->pipe, 0, ZMQ_POLLIN, 0 },
|
411
|
+
{ NULL, self->udpsock, ZMQ_POLLIN, 0 }
|
412
|
+
};
|
413
|
+
long timeout = -1;
|
414
|
+
if (self->transmit) {
|
415
|
+
timeout = (long) (self->ping_at - zclock_time ());
|
416
|
+
if (timeout < 0)
|
417
|
+
timeout = 0;
|
418
|
+
}
|
419
|
+
if (zmq_poll (pollitems, 2, timeout * ZMQ_POLL_MSEC) == -1)
|
420
|
+
break; // Interrupted
|
421
|
+
|
422
|
+
if (pollitems [0].revents & ZMQ_POLLIN)
|
423
|
+
s_api_command (self);
|
424
|
+
if (pollitems [1].revents & ZMQ_POLLIN)
|
425
|
+
s_beacon_recv (self);
|
426
|
+
|
427
|
+
if (self->transmit
|
428
|
+
&& zclock_time () >= self->ping_at) {
|
429
|
+
s_beacon_send (self);
|
430
|
+
self->ping_at = zclock_time () + self->interval;
|
431
|
+
}
|
432
|
+
if (self->terminated)
|
433
|
+
break;
|
434
|
+
}
|
435
|
+
s_agent_destroy (&self);
|
436
|
+
}
|
437
|
+
|
438
|
+
|
439
|
+
// Create and initialize new agent instance
|
440
|
+
|
441
|
+
static agent_t *
|
442
|
+
s_agent_new (void *pipe, int port_nbr)
|
443
|
+
{
|
444
|
+
agent_t *self = (agent_t *) zmalloc (sizeof (agent_t));
|
445
|
+
assert (self);
|
446
|
+
|
447
|
+
self->pipe = pipe;
|
448
|
+
self->port_nbr = port_nbr;
|
449
|
+
self->interval = INTERVAL_DFLT;
|
450
|
+
|
451
|
+
// Create our UDP socket
|
452
|
+
self->udpsock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
453
|
+
if (self->udpsock == INVALID_SOCKET)
|
454
|
+
s_handle_io_error ("socket");
|
455
|
+
|
456
|
+
// Ask operating system to let us do broadcasts from socket
|
457
|
+
int on = 1;
|
458
|
+
if (setsockopt (self->udpsock, SOL_SOCKET, SO_BROADCAST,
|
459
|
+
(char *) &on, sizeof (on)) == SOCKET_ERROR)
|
460
|
+
s_handle_io_error ("setsockopt (SO_BROADCAST)");
|
461
|
+
|
462
|
+
// Allow multiple owners to bind to socket; incoming
|
463
|
+
// messages will replicate to each owner
|
464
|
+
if (setsockopt (self->udpsock, SOL_SOCKET, SO_REUSEADDR,
|
465
|
+
(char *) &on, sizeof (on)) == SOCKET_ERROR)
|
466
|
+
s_handle_io_error ("setsockopt (SO_REUSEADDR)");
|
467
|
+
|
468
|
+
#if defined (SO_REUSEPORT)
|
469
|
+
// On some platforms we have to ask to reuse the port
|
470
|
+
if (setsockopt (self->udpsock, SOL_SOCKET, SO_REUSEPORT,
|
471
|
+
(char *) &on, sizeof (on)) == SOCKET_ERROR)
|
472
|
+
s_handle_io_error ("setsockopt (SO_REUSEPORT)");
|
473
|
+
#endif
|
474
|
+
// PROBLEM: this design will not survive the network interface
|
475
|
+
// being killed and restarted while the program is running
|
476
|
+
|
477
|
+
// Bind to the port on all interfaces
|
478
|
+
inaddr_t sockaddr = { 0 };
|
479
|
+
sockaddr.sin_family = AF_INET;
|
480
|
+
sockaddr.sin_port = htons (self->port_nbr);
|
481
|
+
sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
|
482
|
+
if (bind (self->udpsock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) == SOCKET_ERROR)
|
483
|
+
s_handle_io_error ("bind");
|
484
|
+
|
485
|
+
// Get the network interface
|
486
|
+
s_get_interface (self);
|
487
|
+
|
488
|
+
// Send our hostname back to API
|
489
|
+
char hostname [INET_ADDRSTRLEN];
|
490
|
+
getnameinfo ((struct sockaddr *) &self->address, sizeof (self->address),
|
491
|
+
hostname, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
|
492
|
+
zstr_send (pipe, hostname);
|
493
|
+
|
494
|
+
return self;
|
495
|
+
}
|
496
|
+
|
497
|
+
|
498
|
+
// Handle error from I/O operation
|
499
|
+
|
500
|
+
static void
|
501
|
+
s_handle_io_error (char *reason)
|
502
|
+
{
|
503
|
+
#if defined (__WINDOWS__)
|
504
|
+
switch (WSAGetLastError ()) {
|
505
|
+
case WSAEINTR: errno = EINTR; break;
|
506
|
+
case WSAEBADF: errno = EBADF; break;
|
507
|
+
case WSAEWOULDBLOCK: errno = EAGAIN; break;
|
508
|
+
case WSAEINPROGRESS: errno = EAGAIN; break;
|
509
|
+
case WSAENETDOWN: errno = ENETDOWN; break;
|
510
|
+
case WSAECONNRESET: errno = ECONNRESET; break;
|
511
|
+
case WSAECONNABORTED: errno = EPIPE; break;
|
512
|
+
case WSAESHUTDOWN: errno = ECONNRESET; break;
|
513
|
+
case WSAEINVAL: errno = EPIPE; break;
|
514
|
+
default: errno = GetLastError ();
|
515
|
+
}
|
516
|
+
#endif
|
517
|
+
if (errno == EAGAIN
|
518
|
+
|| errno == ENETDOWN
|
519
|
+
|| errno == EHOSTUNREACH
|
520
|
+
|| errno == ENETUNREACH
|
521
|
+
|| errno == EINTR
|
522
|
+
|| errno == EPIPE
|
523
|
+
|| errno == ECONNRESET
|
524
|
+
#if !defined (__WINDOWS__)
|
525
|
+
|| errno == EPROTO
|
526
|
+
|| errno == ENOPROTOOPT
|
527
|
+
|| errno == EHOSTDOWN
|
528
|
+
|| errno == EOPNOTSUPP
|
529
|
+
|| errno == EWOULDBLOCK
|
530
|
+
#endif
|
531
|
+
#if defined (ENONET)
|
532
|
+
|| errno == ENONET
|
533
|
+
#endif
|
534
|
+
)
|
535
|
+
return; // Ignore error and try again
|
536
|
+
else {
|
537
|
+
zclock_log ("E: (UDP) error '%s' on %s", strerror (errno), reason);
|
538
|
+
assert (false);
|
539
|
+
}
|
540
|
+
}
|
541
|
+
|
542
|
+
|
543
|
+
// Get the actual network interface we're working on
|
544
|
+
// Currently implemented for POSIX and for Windows
|
545
|
+
|
546
|
+
static void
|
547
|
+
s_get_interface (agent_t *self)
|
548
|
+
{
|
549
|
+
#if defined (__UNIX__)
|
550
|
+
# if defined (HAVE_GETIFADDRS) && defined (HAVE_FREEIFADDRS)
|
551
|
+
struct ifaddrs *interfaces;
|
552
|
+
if (getifaddrs (&interfaces) == 0) {
|
553
|
+
struct ifaddrs *interface = interfaces;
|
554
|
+
while (interface) {
|
555
|
+
// Hopefully the last interface will be WiFi or Ethernet
|
556
|
+
if (interface->ifa_addr &&
|
557
|
+
interface->ifa_broadaddr && // on Solaris, loopback interfaces have a NULL in ifa_broadaddr
|
558
|
+
(interface->ifa_addr->sa_family == AF_INET)) {
|
559
|
+
self->address = *(inaddr_t *) interface->ifa_addr;
|
560
|
+
self->broadcast = *(inaddr_t *) interface->ifa_broadaddr;
|
561
|
+
self->broadcast.sin_port = htons (self->port_nbr);
|
562
|
+
if (streq (interface->ifa_name, zsys_interface ())
|
563
|
+
|| s_wireless_nic (interface->ifa_name))
|
564
|
+
break;
|
565
|
+
}
|
566
|
+
interface = interface->ifa_next;
|
567
|
+
}
|
568
|
+
}
|
569
|
+
freeifaddrs (interfaces);
|
570
|
+
# else
|
571
|
+
struct ifreq ifr;
|
572
|
+
memset (&ifr, 0, sizeof (ifr));
|
573
|
+
|
574
|
+
int sock = 0;
|
575
|
+
if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
|
576
|
+
s_handle_io_error ("socket");
|
577
|
+
|
578
|
+
// Get interface address
|
579
|
+
ifr.ifr_addr.sa_family = AF_INET;
|
580
|
+
strncpy (ifr.ifr_name, zsys_interface (), sizeof (ifr.ifr_name));
|
581
|
+
int rc = ioctl (sock, SIOCGIFADDR, (caddr_t) &ifr, sizeof (struct ifreq));
|
582
|
+
if (rc == -1)
|
583
|
+
s_handle_io_error ("siocgifaddr");
|
584
|
+
|
585
|
+
// Get interface broadcast address
|
586
|
+
memcpy (&self->address, ((inaddr_t *) &ifr.ifr_addr),
|
587
|
+
sizeof (inaddr_t));
|
588
|
+
rc = ioctl (sock, SIOCGIFBRDADDR, (caddr_t) &ifr, sizeof (struct ifreq));
|
589
|
+
if (rc == -1)
|
590
|
+
s_handle_io_error ("siocgifbrdaddr");
|
591
|
+
|
592
|
+
memcpy (&self->broadcast, ((inaddr_t *) &ifr.ifr_broadaddr), sizeof (inaddr_t));
|
593
|
+
close (sock);
|
594
|
+
# endif
|
595
|
+
|
596
|
+
# elif defined (__WINDOWS__)
|
597
|
+
ULONG addr_size = 0;
|
598
|
+
DWORD rc = GetAdaptersAddresses (AF_INET,
|
599
|
+
GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &addr_size);
|
600
|
+
assert (rc == ERROR_BUFFER_OVERFLOW);
|
601
|
+
|
602
|
+
PIP_ADAPTER_ADDRESSES pip_addresses = (PIP_ADAPTER_ADDRESSES) malloc (addr_size);
|
603
|
+
rc = GetAdaptersAddresses (AF_INET,
|
604
|
+
GAA_FLAG_INCLUDE_PREFIX, NULL, pip_addresses, &addr_size);
|
605
|
+
assert (rc == NO_ERROR);
|
606
|
+
|
607
|
+
PIP_ADAPTER_ADDRESSES cur_address = pip_addresses;
|
608
|
+
while (cur_address) {
|
609
|
+
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = cur_address->FirstUnicastAddress;
|
610
|
+
PIP_ADAPTER_PREFIX pPrefix = cur_address->FirstPrefix;
|
611
|
+
|
612
|
+
if (pUnicast && pPrefix) {
|
613
|
+
self->address = *(inaddr_t *)(pUnicast->Address.lpSockaddr);
|
614
|
+
self->broadcast = *(inaddr_t *)(pPrefix->Address.lpSockaddr);
|
615
|
+
self->broadcast.sin_addr.s_addr |= htonl ((1 << (32 - pPrefix->PrefixLength)) - 1);
|
616
|
+
}
|
617
|
+
cur_address = cur_address->Next;
|
618
|
+
}
|
619
|
+
free (pip_addresses);
|
620
|
+
# else
|
621
|
+
# error "Interface detection TBD on this operating system"
|
622
|
+
# endif
|
623
|
+
|
624
|
+
// Set broadcast address and port
|
625
|
+
self->broadcast.sin_addr.s_addr = INADDR_BROADCAST;
|
626
|
+
self->broadcast.sin_port = htons (self->port_nbr);
|
627
|
+
}
|
628
|
+
|
629
|
+
// Check if a given NIC name is wireless
|
630
|
+
|
631
|
+
static bool
|
632
|
+
s_wireless_nic (const char *name)
|
633
|
+
{
|
634
|
+
SOCKET udpsock = socket (AF_INET, SOCK_DGRAM, 0);
|
635
|
+
if (udpsock == INVALID_SOCKET)
|
636
|
+
s_handle_io_error ("socket");
|
637
|
+
|
638
|
+
bool is_nic = false;
|
639
|
+
#if defined (SIOCGIFMEDIA)
|
640
|
+
struct ifmediareq ifmr;
|
641
|
+
memset (&ifmr, 0, sizeof (struct ifmediareq));
|
642
|
+
strncpy(ifmr.ifm_name, name, sizeof (ifmr.ifm_name));
|
643
|
+
int res = ioctl (udpsock, SIOCGIFMEDIA, (caddr_t) &ifmr);
|
644
|
+
if (res != -1)
|
645
|
+
is_nic = (IFM_TYPE (ifmr.ifm_current) == IFM_IEEE80211);
|
646
|
+
|
647
|
+
#elif defined (SIOCGIWNAME)
|
648
|
+
struct iwreq wrq;
|
649
|
+
memset (&wrq, 0, sizeof (struct iwreq));
|
650
|
+
strncpy (wrq.ifr_name, name, sizeof (wrq.ifr_name));
|
651
|
+
int res = ioctl (udpsock, SIOCGIWNAME, (caddr_t) &wrq);
|
652
|
+
if (res != -1)
|
653
|
+
is_nic = true;
|
654
|
+
#endif
|
655
|
+
closesocket (udpsock);
|
656
|
+
return is_nic;
|
657
|
+
}
|
658
|
+
|
659
|
+
// Handle command from API
|
660
|
+
|
661
|
+
static void
|
662
|
+
s_api_command (agent_t *self)
|
663
|
+
{
|
664
|
+
char *command = zstr_recv (self->pipe);
|
665
|
+
if (streq (command, "INTERVAL")) {
|
666
|
+
char *interval = zstr_recv (self->pipe);
|
667
|
+
self->interval = atoi (interval);
|
668
|
+
free (interval);
|
669
|
+
}
|
670
|
+
else
|
671
|
+
if (streq (command, "NOECHO"))
|
672
|
+
self->noecho = true;
|
673
|
+
else
|
674
|
+
if (streq (command, "PUBLISH")) {
|
675
|
+
zframe_destroy (&self->transmit);
|
676
|
+
self->transmit = zframe_recv (self->pipe);
|
677
|
+
assert (self->transmit);
|
678
|
+
// Start broadcasting immediately
|
679
|
+
self->ping_at = zclock_time ();
|
680
|
+
}
|
681
|
+
else
|
682
|
+
if (streq (command, "SILENCE"))
|
683
|
+
zframe_destroy (&self->transmit);
|
684
|
+
else
|
685
|
+
if (streq (command, "SUBSCRIBE")) {
|
686
|
+
zframe_destroy (&self->filter);
|
687
|
+
self->filter = zframe_recv (self->pipe);
|
688
|
+
}
|
689
|
+
else
|
690
|
+
if (streq (command, "UNSUBSCRIBE"))
|
691
|
+
zframe_destroy (&self->filter);
|
692
|
+
else
|
693
|
+
if (streq (command, "TERMINATE")) {
|
694
|
+
self->terminated = true;
|
695
|
+
zstr_send (self->pipe, "OK");
|
696
|
+
}
|
697
|
+
else
|
698
|
+
printf ("E: unexpected API command '%s'\n", command);
|
699
|
+
|
700
|
+
free (command);
|
701
|
+
}
|
702
|
+
|
703
|
+
// Receive and filter the waiting beacon
|
704
|
+
|
705
|
+
static void
|
706
|
+
s_beacon_recv (agent_t *self)
|
707
|
+
{
|
708
|
+
assert (self);
|
709
|
+
|
710
|
+
socklen_t si_len = sizeof (inaddr_t);
|
711
|
+
inaddr_t sender;
|
712
|
+
byte buffer [BEACON_MAX];
|
713
|
+
ssize_t size = recvfrom (
|
714
|
+
self->udpsock,
|
715
|
+
(char *) buffer, BEACON_MAX,
|
716
|
+
0, // Flags
|
717
|
+
(struct sockaddr *) &sender, &si_len);
|
718
|
+
if (size == SOCKET_ERROR)
|
719
|
+
s_handle_io_error ("recvfrom");
|
720
|
+
|
721
|
+
// Get sender address as printable string
|
722
|
+
char peername [INET_ADDRSTRLEN];
|
723
|
+
#if (defined (__WINDOWS__))
|
724
|
+
getnameinfo ((struct sockaddr *) &sender, si_len,
|
725
|
+
peername, INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
|
726
|
+
#else
|
727
|
+
inet_ntop (AF_INET, &sender.sin_addr, peername, si_len);
|
728
|
+
#endif
|
729
|
+
|
730
|
+
// If filter is set, check that beacon matches it
|
731
|
+
bool is_valid = false;
|
732
|
+
if (self->filter) {
|
733
|
+
byte *filter_data = zframe_data (self->filter);
|
734
|
+
size_t filter_size = zframe_size (self->filter);
|
735
|
+
if (size >= filter_size && memcmp (buffer, filter_data, filter_size) == 0)
|
736
|
+
is_valid = true;
|
737
|
+
}
|
738
|
+
// If valid, check for echoed beacons (i.e. our own broadcast)
|
739
|
+
if (is_valid && self->noecho) {
|
740
|
+
byte *transmit_data = zframe_data (self->transmit);
|
741
|
+
size_t transmit_size = zframe_size (self->transmit);
|
742
|
+
if (size == transmit_size && memcmp (buffer, transmit_data, transmit_size) == 0)
|
743
|
+
is_valid = false;
|
744
|
+
}
|
745
|
+
// If still a valid beacon, send on to the API
|
746
|
+
if (is_valid) {
|
747
|
+
zmsg_t *msg = zmsg_new ();
|
748
|
+
zmsg_addstr (msg, peername);
|
749
|
+
zmsg_addmem (msg, buffer, size);
|
750
|
+
zmsg_send (&msg, self->pipe);
|
751
|
+
}
|
752
|
+
}
|
753
|
+
|
754
|
+
// Send beacon to any listening peers
|
755
|
+
|
756
|
+
static void
|
757
|
+
s_beacon_send (agent_t *self)
|
758
|
+
{
|
759
|
+
// Send UDP broadcast packet now
|
760
|
+
assert (self->transmit);
|
761
|
+
ssize_t size = sendto (
|
762
|
+
self->udpsock,
|
763
|
+
(char *) zframe_data (self->transmit), zframe_size (self->transmit),
|
764
|
+
0, // Flags
|
765
|
+
(struct sockaddr *) &self->broadcast, sizeof (inaddr_t));
|
766
|
+
// Sending can fail if the OS is blocking multicast. In such cases we
|
767
|
+
// don't try to report the error. We might log this or send to an error
|
768
|
+
// console at some point.
|
769
|
+
if (size == SOCKET_ERROR)
|
770
|
+
; // s_handle_io_error ("sendto");
|
771
|
+
}
|
772
|
+
|
773
|
+
// Destroy agent instance
|
774
|
+
|
775
|
+
static void
|
776
|
+
s_agent_destroy (agent_t **self_p)
|
777
|
+
{
|
778
|
+
assert (self_p);
|
779
|
+
if (*self_p) {
|
780
|
+
agent_t *self = *self_p;
|
781
|
+
closesocket (self->udpsock);
|
782
|
+
zframe_destroy (&self->transmit);
|
783
|
+
zframe_destroy (&self->filter);
|
784
|
+
free (self);
|
785
|
+
*self_p = NULL;
|
786
|
+
}
|
787
|
+
}
|