From 33c6ff68a8f4636af737bcb8835b246628ce327a Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 9 Oct 2013 12:32:19 +0000 Subject: main/lua-zmq: upgrade to git 20130709 and build for both lua 5.1 and 5.2 --- main/lua-zmq/APKBUILD | 64 +- main/lua-zmq/git-20121231.patch | 13813 ------------------------------------ main/lua-zmq/git-20130709.patch | 14529 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 14577 insertions(+), 13829 deletions(-) delete mode 100644 main/lua-zmq/git-20121231.patch create mode 100644 main/lua-zmq/git-20130709.patch (limited to 'main/lua-zmq') diff --git a/main/lua-zmq/APKBUILD b/main/lua-zmq/APKBUILD index bf80a51b8..4eb764808 100644 --- a/main/lua-zmq/APKBUILD +++ b/main/lua-zmq/APKBUILD @@ -1,48 +1,80 @@ # Contributor: Natanael Copa # Maintainer: Natanael Copa + +_luaversions="5.1 5.2" + pkgname=lua-zmq -pkgver=1.1_git20121231 +pkgver=1.1_git20130709 _ver=${pkgver%_git*} pkgrel=0 pkgdesc="Lua zeromq2 binding" url="https://github.com/Neopallium/lua-zmq" arch="all" license="MIT" -depends="lua-llthreads" -makedepends="zeromq-dev cmake lua-dev" +depends="lua-llthreads lua5.1-zmq" +makedepends="zeromq-dev cmake" +for _i in $_luaversions; do + makedepends="$makedepends lua$_i-dev" + subpackages="$subpackages lua$_i-zmq:split_${_i/./_}" +done install="" -subpackages= source="$pkgname-$_ver.tar.gz::https://github.com/Neopallium/lua-zmq/archive/v$_ver.tar.gz git-${pkgver##*_git}.patch" -_builddir="$srcdir"/lua-zmq-$_ver +_sdir="$srcdir"/lua-zmq-$_ver prepare() { local i - cd "$_builddir" + cd "$_sdir" for i in $source; do case $i in *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;; esac done + for _i in $_luaversions; do + mkdir -p "$srcdir"/build-$_i || return 1 + done } build() { - cd "$_builddir" - cmake \ - -DCMAKE_INSTALL_PREFIX=/usr \ - . || return 1 - make || return 1 + for _i in $_luaversions; do + cd "$srcdir"/build-$_i + msg "build for Lua $_i" + CFLAGS="$CFLAGS $(pkg-config --cflags lua$_i)" cmake \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DINSTALL_CMOD=/usr/lib/lua/$_i \ + -DINSTALL_LMOD=/usr/share/lua/$_i \ + "$_sdir" || return 1 + make || return 1 + done } package() { - cd "$_builddir" - make install DESTDIR="$pkgdir" || return 1 + for _i in $_luaversions; do + cd "$srcdir"/build-$_i + make install DESTDIR="$pkgdir" || return 1 + done } +_split() { + local d= _ver=$1 + pkgdesc="Filesystem functions for Lua $_ver" + replaces="$pkgname" + for d in usr/lib/lua usr/share/lua; do + if [ -d "$pkgdir"/$d/$_ver ]; then + mkdir -p "$subpkgdir"/$d + mv "$pkgdir"/$d/$_ver "$subpkgdir"/$d/ || return 1 + fi + done +} + +for _i in $_luaversions; do + eval "split_${_i/./_}() { _split $_i; }" +done + md5sums="cb4df81b4c884bf97bf6add88fcfa58d lua-zmq-1.1.tar.gz -e568cb33eef6230454a70dddfd5d3978 git-20121231.patch" +e68a07c32d77fbea78165d6ae49027cb git-20130709.patch" sha256sums="f2bdf3142b744971da4eb8bdb12020a34b62f8ba384be44d8448b4ef05ec3dcc lua-zmq-1.1.tar.gz -9f3b2ddd87c0fd7064a317e5ed63c16c4d1999b020f3d98970f1c5962ed34354 git-20121231.patch" +f0266865ac2ebc10e74877686e8536caec88db286408170b22543243235fa608 git-20130709.patch" sha512sums="35d7da6215a96b80ea59b52591082473d2c54bcb9577ae95ead1235de894d5ef226b6c4e3030c327b2b146e07af6b3998d91c5b520dfb35e87c85e958069362d lua-zmq-1.1.tar.gz -12ff90d9b01ca03f8c9f8e02e1392de839c19242570acb77d5078e4358a89dabe3df6f6b701a30b95121b35ed09a72eedd0259c34b2663e5193a963c588be64c git-20121231.patch" +c9080a53b3f6f63a03bc105fc2d49bdf664fccfdcd35414f21972cee30db466744024727418491dbff6ac845186e1b77f684832ccbbf0c209759303ede8150bb git-20130709.patch" diff --git a/main/lua-zmq/git-20121231.patch b/main/lua-zmq/git-20121231.patch deleted file mode 100644 index cfeaaebc3..000000000 --- a/main/lua-zmq/git-20121231.patch +++ /dev/null @@ -1,13813 +0,0 @@ -diff --git a/API.md b/API.md -index f15da79..9cdcb8e 100644 ---- a/API.md -+++ b/API.md -@@ -147,6 +147,14 @@ See [zmq_msg_copy(3)](http://api.zeromq.org/zmq_msg_copy.html). - - msg1:copy(msg2) -- copy contents from msg2 -> msg1 - -+## set_size(size) -+ -+Re-initialize the message with a new size. The current contents will be lost. -+See [zmq_msg_init_size(3)](http://api.zeromq.org/zmq_msg_init_size.html). -+ -+ msg:set_size(size) -- re-initialize message if size is different from current size. -+ local buf = msg:data() -- get buffer to fill message with new contents. -+ - ## set_data(data) - - Change the message contents. -@@ -156,7 +164,7 @@ See [zmq_msg_data(3)](http://api.zeromq.org/zmq_msg_data.html). - - ## data() - --Get the message contents. -+Get a lightuserdata pointer to the message contents. - See [zmq_msg_data(3)](http://api.zeromq.org/zmq_msg_data.html). - - local data = msg:data() -- get the message contents -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 6c3ed78..6471a17 100755 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -9,12 +9,10 @@ set(BUILD_SHARED_LIBS TRUE) - - set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) - --set(INSTALL_LMOD share/lua/5.1 CACHE PATH "Directory to install Lua source modules (configure lua via LUA_PATH)") --set(INSTALL_CMOD lib/lua/5.1 CACHE PATH "Directory to install Lua binary modules (configure lua via LUA_CPATH)") --set(LUA_NATIVE_OBJECTS_PATH ../LuaNativeObjects CACHE PATH -- "Directory to LuaNativeObjects bindings generator.") --set(USE_PRE_GENERATED_BINDINGS TRUE CACHE BOOL -- "Set this to FALSE to re-generate bindings using LuaNativeObjects") -+set(INSTALL_LMOD ${CMAKE_INSTALL_PREFIX}/share/lua/5.1 CACHE PATH -+ "Directory to install Lua source modules (configure lua via LUA_PATH)") -+set(INSTALL_CMOD ${CMAKE_INSTALL_PREFIX}/lib/lua/5.1 CACHE PATH -+ "Directory to install Lua binary modules (configure lua via LUA_CPATH)") - set(ZMQ_PATH "" CACHE PATH - "Directory to libzmq. (by default use pkg-config to detect path)") - -@@ -27,6 +25,17 @@ include(FindLua51) - if(NOT ${LUA51_FOUND}) - message(FATAL_ERROR "The FindLua51 module could not find lua :-(") - endif() -+if(WIN32) -+ set(COMMON_CFLAGS "${COMMON_CFLAGS} -I${LUA_INCLUDE_DIR}") -+ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} ${LUA_LIBRARY}") -+ if(NOT MSVC) -+ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -Wl,--export-all-symbols") -+ endif() -+endif() -+## MAC OSX needs extra linker flags -+if(APPLE) -+ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -undefined dynamic_lookup") -+endif() - - ## LibZMQ - if(WIN32) -@@ -38,8 +47,13 @@ if(WIN32) - endif() - if(IS_DIRECTORY ${ZMQ_PATH}) - set(COMMON_CFLAGS "${COMMON_CFLAGS} -I${ZMQ_PATH}/include") -- set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -L${ZMQ_PATH}/lib") -- set(COMMON_LIBS "${COMMON_LIBS};zmq") -+ if(MSVC) -+ set(COMMON_LIBS "${COMMON_LIBS};libzmq") -+ else() -+ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -L${ZMQ_PATH}/lib") -+ set(COMMON_LIBS "${COMMON_LIBS};zmq") -+ endif() -+ link_directories(${ZMQ_PATH}/lib) - else() - ## fallback to using pkg-config - include(FindPkgConfig) -@@ -51,13 +65,12 @@ endif() - - ## LuaNativeObjects - include(LuaNativeObjects) -+include(CustomMacros) - - include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${LUA_INCLUDE_DIR}) - --link_directories(${ZMQ_LIBRARY_DIRS}) -- - ## LuaZMQ - set(LUA_ZMQ_SRC - zmq.nobj.lua -@@ -79,8 +92,8 @@ endif() - add_library(lua-zmq MODULE ${LUA_ZMQ_SRC}) - target_link_libraries(lua-zmq ${COMMON_LIBS}) - set_target_properties(lua-zmq PROPERTIES PREFIX "") --set_target_properties(lua-zmq PROPERTIES COMPILE_FLAGS "${COMMON_CFLAGS}") --set_target_properties(lua-zmq PROPERTIES LINK_FLAGS "${COMMON_LDFLAGS}") -+add_target_properties(lua-zmq COMPILE_FLAGS "${COMMON_CFLAGS}") -+add_target_properties(lua-zmq LINK_FLAGS "${LD_FLAGS} ${COMMON_LDFLAGS}") - set_target_properties(lua-zmq PROPERTIES OUTPUT_NAME zmq) - - install(TARGETS lua-zmq -diff --git a/COPYRIGHT b/COPYRIGHT -new file mode 100644 -index 0000000..9840d93 ---- /dev/null -+++ b/COPYRIGHT -@@ -0,0 +1,19 @@ -+Copyright (c) 2011 by Robert G. Jakabosky -+ -+Permission is hereby granted, free of charge, to any person obtaining a copy -+of this software and associated documentation files (the "Software"), to deal -+in the Software without restriction, including without limitation the rights -+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+copies of the Software, and to permit persons to whom the Software is -+furnished to do so, subject to the following conditions: -+ -+The above copyright notice and this permission notice shall be included in -+all copies or substantial portions of the Software. -+ -+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+THE SOFTWARE. -diff --git a/README.md b/README.md -index eac5f5f..830e350 100644 ---- a/README.md -+++ b/README.md -@@ -3,6 +3,11 @@ About - - Lua bindings to zeromq2. Check out the [ZeroMQ Guide with Lua examples](http://zguide.zeromq.org/lua:all). - -+Windows -+======= -+ -+Download a compiled version of [LuaJIT 2.0.0-beta11 + lua-zmq + zeromq2.2.0](https://github.com/downloads/Neopallium/lua-zmq/luajit2.0_beta11_zmq2.2_llthreads.zip) 32bit & 64bit. -+ - API - === - -@@ -12,7 +17,7 @@ See [API.md](https://github.com/Neopallium/lua-zmq/blob/master/API.md) and - Requirements - ============ - --* ZeroMQ version 2.1.x. -+* ZeroMQ version 2.1, 2.2 or 3.2. - * Might work with some 2.0.x versions (2.0.6 and lower are not supported). - - For Ubuntu 10.10 users: -@@ -22,7 +27,7 @@ For Ubuntu 10.10 users: - Installation - ============ - --It is recommended to either compile Lua with the "-pthread" flag or preload libpthread.so on Linux when using this module ([See this glibc bug report](http://sourceware.org/bugzilla/show_bug.cgi?id=10652): -+It is recommended to either compile Lua with the "-pthread" flag or preload libpthread.so on Linux when using this module ([see this glibc bug report](http://sourceware.org/bugzilla/show_bug.cgi?id=10652)): - - $ LD_PRELOAD=/lib/libpthread.so lua - -@@ -45,12 +50,12 @@ Latest Git revision - - With LuaRocks 2.0.4.1: - -- $ sudo luarocks install https://github.com/Neopallium/lua-zmq/raw/master/rockspecs/lua-zmq-scm-1.rockspec -+ $ sudo luarocks install https://raw.github.com/Neopallium/lua-zmq/master/rockspecs/lua-zmq-scm-1.rockspec - - For threads support: - -- $ sudo luarocks install https://github.com/Neopallium/lua-llthreads/raw/master/rockspecs/lua-llthreads-scm-0.rockspec -- $ sudo luarocks install https://github.com/Neopallium/lua-zmq/raw/master/rockspecs/lua-zmq-threads-scm-0.rockspec -+ $ sudo luarocks install https://raw.github.com/Neopallium/lua-llthreads/master/rockspecs/lua-llthreads-scm-0.rockspec -+ $ sudo luarocks install https://raw.github.com/Neopallium/lua-zmq/master/rockspecs/lua-zmq-threads-scm-0.rockspec - - With CMake: - -diff --git a/cmake/CustomMacros.cmake b/cmake/CustomMacros.cmake -new file mode 100644 -index 0000000..312eeff ---- /dev/null -+++ b/cmake/CustomMacros.cmake -@@ -0,0 +1,61 @@ -+## Orignal Macros copied from lighttpd 2.0 -+ -+## modules are without the "lib" prefix -+ -+macro(setup_static_modules TARGET) -+ file(WRITE ${TARGET}_builtins.h "/* auto-generated by CMake build do not edit */\n\n") -+endmacro(setup_static_modules) -+ -+macro(add_module TARGET MODNAME) -+ set(_static_mod ${BUILD_STATIC}) -+ -+ ## create list of module source files. -+ set(_srcfiles) -+ set(_def_module_src ${CMAKE_CURRENT_SOURCE_DIR}/modules/${MODNAME}.c) -+ if(EXISTS ${_def_module_src}) -+ set(_srcfiles ${_def_module_src}) -+ endif(EXISTS ${_def_module_src}) -+ foreach(_srcfile ${ARGN}) -+ if(_srcfile STREQUAL "STATIC") -+ set(_static_mod TRUE) -+ else(_srcfile STREQUAL "STATIC") -+ set(_srcfiles ${_srcfiles} ${_srcfile}) -+ endif(_srcfile STREQUAL "STATIC") -+ endforeach(_srcfile) -+ -+ if(_static_mod) -+ set(STATIC_MODULE_SRC ${STATIC_MODULE_SRC} ${_srcfiles}) -+ file(APPEND ${TARGET}_builtins.h "STATIC_MOD(${MODNAME})\n") -+ else(_static_mod) -+ add_library(${MODNAME} MODULE ${_srcfiles}) -+ set(MODULE_TARGETS ${MODULE_TARGETS} ${MODNAME}) -+ -+ add_target_properties(${MODNAME} LINK_FLAGS ${COMMON_LDFLAGS}) -+ add_target_properties(${MODNAME} COMPILE_FLAGS ${COMMON_CFLAGS}) -+ set_target_properties(${MODNAME} PROPERTIES CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) -+ -+ ## Windows likes to link it this way back to app! -+ if(WIN32) -+ set_target_properties(${MODNAME} PROPERTIES LINK_FLAGS ${TARGET}.lib) -+ endif(WIN32) -+ -+ if(APPLE) -+ set_target_properties(${MODNAME} PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress") -+ endif(APPLE) -+ endif(_static_mod) -+endmacro(add_module) -+ -+macro(add_target_properties _target _name) -+ set(_properties) -+ foreach(_prop ${ARGN}) -+ set(_properties "${_properties} ${_prop}") -+ endforeach(_prop) -+ get_target_property(_old_properties ${_target} ${_name}) -+ ##message(STATUS "adding property to ${_target} ${_name}:" ${_properties}) -+ if(NOT _old_properties) -+ # in case it's NOTFOUND -+ set(_old_properties) -+ endif(NOT _old_properties) -+ set_target_properties(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}") -+endmacro(add_target_properties) -+ -diff --git a/cmake/LuaNativeObjects.cmake b/cmake/LuaNativeObjects.cmake -index a1b0e2d..e9e47de 100644 ---- a/cmake/LuaNativeObjects.cmake -+++ b/cmake/LuaNativeObjects.cmake -@@ -1,19 +1,39 @@ - # - # Lua Native Objects - # -+ -+set(LUA_NATIVE_OBJECTS_PATH ${CMAKE_SOURCE_DIR}/../LuaNativeObjects CACHE PATH -+ "Directory to LuaNativeObjects bindings generator.") -+set(USE_PRE_GENERATED_BINDINGS TRUE CACHE BOOL -+ "Set this to FALSE to re-generate bindings using LuaNativeObjects") -+ -+set(GENERATE_LUADOCS TRUE CACHE BOOL -+ "Set this to FALSE to avoid generation of docs using LuaDoc") -+ - macro(GenLuaNativeObjects _src_files_var) - set(_new_src_files) - foreach(_src_file ${${_src_files_var}}) - if(_src_file MATCHES ".nobj.lua") - string(REGEX REPLACE ".nobj.lua" ".nobj.c" _src_file_out ${_src_file}) -- string(REGEX REPLACE ".nobj.lua" ".nobj.h" _header_file_out ${_src_file}) -- add_custom_command(OUTPUT ${_src_file_out} ${_header_file_out} -+ string(REGEX REPLACE ".nobj.lua" ".nobj.ffi.lua" _ffi_file_out ${_src_file}) -+ add_custom_command(OUTPUT ${_src_file_out} ${_ffi_file_out} - COMMAND lua ${LUA_NATIVE_OBJECTS_PATH}/native_objects.lua -outpath ${CMAKE_CURRENT_BINARY_DIR} -gen lua ${_src_file} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${_src_file} - ) - set_source_files_properties(${_src_file_out} PROPERTIES GENERATED TRUE) -- set_source_files_properties(${_header_file_out} PROPERTIES GENERATED TRUE) -+ set_source_files_properties(${_ffi_file_out} PROPERTIES GENERATED TRUE) -+ if (${GENERATE_LUADOCS}) -+ string(REGEX REPLACE ".nobj.lua" "" _doc_base ${_src_file}) -+ string(REGEX REPLACE ".nobj.lua" ".luadoc" _doc_file_out ${_src_file}) -+ add_custom_target(${_doc_file_out} ALL -+ COMMAND lua ${LUA_NATIVE_OBJECTS_PATH}/native_objects.lua -outpath docs -gen luadoc ${_src_file} -+ COMMAND luadoc -nofiles -d docs docs -+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -+ DEPENDS ${_src_file} -+ ) -+ endif() -+ set_source_files_properties(${_doc_file_out} PROPERTIES GENERATED TRUE) - set(_new_src_files ${_new_src_files} ${_src_file_out}) - else(_src_file MATCHES ".nobj.lua") - set(_new_src_files ${_new_src_files} ${_src_file}) -diff --git a/examples/client.lua b/examples/client.lua -index 682a549..5e9849c 100644 ---- a/examples/client.lua -+++ b/examples/client.lua -@@ -18,15 +18,24 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - --require("zmq") -+local zmq = require"zmq" - --local ctx = zmq.init(1) -+local N=tonumber(arg[1] or 100) -+ -+local ctx = zmq.init() - local s = ctx:socket(zmq.REQ) - - s:connect("tcp://localhost:5555") - --s:send("SELECT * FROM mytable") --print(s:recv()) -+for i=1,N do -+ s:send("SELECT * FROM mytable") -+ local data, err = s:recv() -+ if data then -+ print(data) -+ else -+ print("s:recv() error:", err) -+ end -+end - - s:close() - ctx:term() -diff --git a/examples/client_multipart.lua b/examples/client_multipart.lua -index e82ca26..4f10c58 100644 ---- a/examples/client_multipart.lua -+++ b/examples/client_multipart.lua -@@ -18,17 +18,26 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - --require("zmq") -+local zmq = require"zmq" - --local ctx = zmq.init(1) -+local N=tonumber(arg[1] or 100) -+ -+local ctx = zmq.init() - local s = ctx:socket(zmq.REQ) - - s:connect("tcp://localhost:5555") - --s:send("SELECT * FROM mytable ", zmq.SNDMORE) --s:send("WHERE library = 'zmq'") -+for i=1,N do -+ s:send("SELECT * FROM mytable ", zmq.SNDMORE) -+ s:send("WHERE library = 'zmq'") - --print(s:recv()) -+ local data, err = s:recv() -+ if data then -+ print(data) -+ else -+ print("s:recv() error:", err) -+ end -+end - - s:close() - ctx:term() -diff --git a/examples/client_poll.lua b/examples/client_poll.lua -new file mode 100644 -index 0000000..c49af9b ---- /dev/null -+++ b/examples/client_poll.lua -@@ -0,0 +1,108 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local poller = require"examples.poller" -+local poll = poller.new() -+ -+local zmq = require"zmq" -+local z_NOBLOCK = zmq.NOBLOCK -+local z_EVENTS = zmq.EVENTS -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+ -+local N=tonumber(arg[1] or 100) -+ -+local ctx = zmq.init() -+local s = ctx:socket(zmq.REQ) -+local s_FD = s:getopt(zmq.FD) -+ -+s:connect("tcp://localhost:5555") -+ -+-- current socket state -+local blocked_state -+local blocked_event -+local on_sock_recv -+local on_sock_send -+ -+-- IO event callback when socket was blocked -+local function on_sock_io() -+ local events = s:getopt(z_EVENTS) -+ local unblocked = false -+ if events == blocked_event then -+ -- got the event the socket was blocked on. -+ unblocked = true -+ elseif events == z_POLLIN_OUT then -+ -- got both in & out events -+ unblocked = true -+ end -+ if unblocked then -+ -- got the event we are blocked on resume. -+ blocked_event = nil -+ blocked_state() -+ -- check if blocked event was processed. -+ if not blocked_event then -+ poll:remove_read(s_FD) -+ end -+ end -+end -+local function sock_blocked(state, event) -+ if not blocked_event then -+ -- need to register socket's fd with event loop -+ poll:add_read(s_FD, on_sock_io) -+ end -+ blocked_state = state -+ blocked_event = event -+end -+ -+-- sock state functions -+function on_sock_send() -+ N = N - 1 -+ if N == 0 then -+ return poll:stop() -+ end -+ local sent, err = s:send("SELECT * FROM mytable", z_NOBLOCK) -+ if not sent then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_send, z_POLLOUT) -+ end -+ -- yield back to event loop -+ poll:add_work(on_sock_recv) -+end -+ -+function on_sock_recv() -+ local data, err = s:recv(z_NOBLOCK) -+ if not data then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_recv, z_POLLIN) -+ end -+ print(data) -+ return on_sock_send() -+end -+ -+-- start processing of the socket. -+poll:add_work(on_sock_send) -+ -+-- start event loop -+poll:start() -+ -+s:close() -+ctx:term() -+ -diff --git a/examples/ev_subscriber.lua b/examples/ev_subscriber.lua -deleted file mode 100644 -index 876a0ea..0000000 ---- a/examples/ev_subscriber.lua -+++ /dev/null -@@ -1,92 +0,0 @@ ---- Copyright (c) 2010 Aleksey Yeschenko ---- ---- Permission is hereby granted, free of charge, to any person obtaining a copy ---- of this software and associated documentation files (the "Software"), to deal ---- in the Software without restriction, including without limitation the rights ---- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ---- copies of the Software, and to permit persons to whom the Software is ---- furnished to do so, subject to the following conditions: ---- ---- The above copyright notice and this permission notice shall be included in ---- all copies or substantial portions of the Software. ---- ---- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ---- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ---- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ---- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ---- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ---- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ---- THE SOFTWARE. -- --require("zmq") --local ev = require'ev' --local loop = ev.Loop.default -- ---- define a sub_worker class --local sub_worker_mt = {} --function sub_worker_mt:close(...) -- self.s_io_idle:stop(self.loop) -- self.s_io_read:stop(self.loop) -- return self.socket:close(...) --end --function sub_worker_mt:bind(...) -- return self.socket:bind(...) --end --function sub_worker_mt:connect(...) -- return self.socket:connect(...) --end --function sub_worker_mt:sub(topic) -- return self.socket:setopt(zmq.SUBSCRIBE, topic) --end --function sub_worker_mt:unsub(topic) -- return self.socket:setopt(zmq.UNSUBSCRIBE, topic) --end --sub_worker_mt.__index = sub_worker_mt -- --local function sub_worker(loop, ctx, msg_cb) -- local s = ctx:socket(zmq.SUB) -- local self = { loop = loop, socket = s, msg_cb = msg_cb } -- setmetatable(self, sub_worker_mt) -- -- create ev callbacks for recving data. -- -- need idle watcher since ZeroMQ sockets are edge-triggered instead of level-triggered -- local s_io_idle -- local s_io_read -- s_io_idle = ev.Idle.new(function() -- local msg, err = s:recv(zmq.NOBLOCK) -- if err == 'timeout' then -- -- need to block on read IO -- s_io_idle:stop(loop) -- s_io_read:start(loop) -- return -- end -- self:msg_cb(msg) -- end) -- s_io_idle:start(loop) -- s_io_read = ev.IO.new(function() -- s_io_idle:start(loop) -- s_io_read:stop(loop) -- end, s:getopt(zmq.FD), ev.READ) -- self.s_io_idle = s_io_idle -- self.s_io_read = s_io_read -- return self --end -- --local ctx = zmq.init(1) -- ---- message handling function. --local function handle_msg(worker, msg) -- local msg_id = tonumber(msg) -- if math.mod(msg_id, 10000) == 0 then print(worker.id, msg_id) end --end -- --local sub1 = sub_worker(loop, ctx, handle_msg) --sub1.id = 'sub1' --sub1:sub('') --sub1:connect("tcp://localhost:5555") --local sub2 = sub_worker(loop, ctx, handle_msg) --sub2.id = 'sub2' --sub2:sub('') --sub2:connect("tcp://localhost:5555") -- --loop:loop() -- -diff --git a/examples/forward_poll.lua b/examples/forward_poll.lua -new file mode 100644 -index 0000000..25e1e4f ---- /dev/null -+++ b/examples/forward_poll.lua -@@ -0,0 +1,39 @@ -+local zmq = require'zmq' -+local poller = require"examples.poller" -+local poll_zsock = require"examples.poll_zsock" -+ -+local poll = poller.new() -+poll_zsock.set_poller(poll) -+ -+local c = zmq.init(1) -+local xreq = poll_zsock(c:socket(zmq.XREQ)) -+xreq:bind('tcp://127.0.0.1:13333') -+local xrep = poll_zsock(c:socket(zmq.XREP)) -+xrep:bind('tcp://127.0.0.1:13334') -+ -+local max_recv = 10 -+ -+local function forward_io(src,dst) -+ src.on_data = function() -+ for i=1,max_recv do -+ repeat -+ local data, err = src:recv(zmq.NOBLOCK) -+ if not data then -+ if err == 'timeout' then -+ return -+ else -+ error("socket recv error:" .. err) -+ end -+ end -+ local more = src:getopt(zmq.RCVMORE) > 0 -+ dst:send(data,more and zmq.SNDMORE or 0) -+ until not more -+ end -+ end -+end -+ -+forward_io(xrep,xreq) -+forward_io(xreq,xrep) -+ -+poll:start() -+ -diff --git a/examples/poll_zsock.lua b/examples/poll_zsock.lua -new file mode 100644 -index 0000000..5d2ca04 ---- /dev/null -+++ b/examples/poll_zsock.lua -@@ -0,0 +1,177 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local zmq = require"zmq" -+ -+local z_EVENTS = zmq.EVENTS -+ -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+ -+local poll -+ -+local meths = {} -+local zsock_mt = { __index=meths } -+ -+local function zsock_check_events(self) -+ if not self.check_enabled then -+ -- enable 'on_work' callback to handle checking for socket events. -+ self.check_enabled = true -+ poll:add_work(self.on_work) -+ end -+end -+ -+function meths:events() -+ zsock_check_events(self) -+ return self.sock:events() -+end -+ -+function meths:getopt(opt) -+ if (opt == z_EVENTS) then -+ zsock_check_events(self) -+ end -+ return self.sock:getopt(opt) -+end -+ -+function meths:setopt(opt,val) -+ return self.sock:setopt(opt,val) -+end -+ -+function meths:sub(topic) -+ return self.sock:sub(topic) -+end -+ -+function meths:unsub(topic) -+ return self.sock:unsub(topic) -+end -+ -+function meths:identity(id) -+ return self.sock:identity(id) -+end -+ -+function meths:bind(addr) -+ return self.sock:bind(addr) -+end -+ -+function meths:connect(addr) -+ return self.sock:connect(addr) -+end -+ -+function meths:close() -+ return self.sock:close() -+end -+ -+function meths:send(msg, flags) -+ zsock_check_events(self) -+ local sent, err = self.sock:send(msg, flags) -+ if not sent and err == 'timeout' then -+ self.send_blocked = true -+ end -+ return sent, err -+end -+ -+function meths:send_msg(msg, flags) -+ zsock_check_events(self) -+ local sent, err = self.sock:send_msg(msg, flags) -+ if not sent and err == 'timeout' then -+ self.send_blocked = true -+ end -+ return sent, err -+end -+ -+function meths:recv(flags) -+ zsock_check_events(self) -+ local msg, err = self.sock:recv(flags) -+ if not msg and err == 'timeout' then -+ self.recv_blocked = true -+ end -+ return msg, err -+end -+ -+function meths:recv_msg(msg, flags) -+ zsock_check_events(self) -+ local stat, err = self.sock:recv_msg(msg, flags) -+ if not stat and err == 'timeout' then -+ self.recv_blocked = true -+ end -+ return stat, err -+end -+ -+local function nil_cb() -+end -+ -+local function wrap_zsock(sock, on_data, on_drain) -+ local self = setmetatable({ -+ sock = sock, -+ on_data = on_data or nil_cb, -+ on_drain = on_drain or nil_cb, -+ recv_blocked = false, -+ send_blocked = false, -+ check_enabled = false, -+ }, zsock_mt) -+ -+ local function on_work() -+ self.check_enabled = false -+ local events = sock:events() -+ local read = false -+ local write = false -+ if events == z_POLLIN_OUT then -+ read = true -+ write = true -+ elseif events == z_POLLIN then -+ read = true -+ elseif events == z_POLLOUT then -+ write = true -+ else -+ return -+ end -+ if read then -+ self.recv_blocked = false -+ self:on_data(sock) -+ -- there might be more messages to read. -+ if not self.recv_blocked then -+ zsock_check_events(self) -+ end -+ end -+ if write and self.send_blocked then -+ self:on_drain(sock) -+ end -+ end -+ self.on_work = on_work -+ -+ -- listen for read events to enable socket. -+ poll:add_read(sock:fd(), function() -+ on_work() -+ end) -+ -+ zsock_check_events(self) -+ return self -+end -+ -+return setmetatable({ -+set_poller = function(poller) -+ local old = poll -+ poll = poller -+ return old -+end, -+wrap_zsock = wrap_zsock, -+}, { __call = function(tab, ...) return wrap_zsock(...) end}) -+ -diff --git a/examples/poller.lua b/examples/poller.lua -new file mode 100644 -index 0000000..90bee0a ---- /dev/null -+++ b/examples/poller.lua -@@ -0,0 +1,45 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+-- safe require. -+local require = require -+local function safe_require(...) -+ return pcall(require, ...) -+end -+ -+local mod_name = ... -+ -+local backends = { -+ "epoll", -+ "ev", -+} -+ -+for i=1,#backends do -+ local backend = backends[i] -+ local name = mod_name .. '.' .. backend -+ local status, mod = safe_require(name) -+ if status then -+ --print("Loaded backend:", name) -+ return mod -+ end -+end -+ -+error("Failed to load backend for: " .. mod_name) -+ -diff --git a/examples/poller/epoll.lua b/examples/poller/epoll.lua -new file mode 100644 -index 0000000..d79597c ---- /dev/null -+++ b/examples/poller/epoll.lua -@@ -0,0 +1,121 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local epoll = require"epoll" -+local EPOLLIN = epoll.EPOLLIN -+local EPOLLOUT = epoll.EPOLLOUT -+ -+local poller_meths = {} -+local poller_mt = {__index = poller_meths} -+ -+local function poller_new() -+ local reads = {} -+ -- create closure for epoll io_event callback. -+ local function do_io_event(fd, ev) -+ local cb = reads[fd] -+ return cb(fd, ev) -+ end -+ -+ return setmetatable({ -+ work_cur = {}, -+ work_last = {}, -+ reads = reads, -+ io_events = 0, -+ do_io_event = do_io_event, -+ poller = epoll.new(), -+ }, poller_mt) -+end -+ -+function poller_meths:add_work(task) -+ -- add task to current work queue. -+ self.work_cur[#self.work_cur + 1] = task -+end -+ -+function poller_meths:add_read(fd, cb) -+ -- make sure read event hasn't been registered yet. -+ if not self.reads[fd] then -+ self.io_events = self.io_events + 1 -+ self.reads[fd] = cb -+ return self.poller:add(fd, EPOLLIN, fd) -+ else -+ -- update read callback? -+ self.reads[fd] = cb -+ end -+end -+ -+function poller_meths:remove_read(fd) -+ -- make sure there was a read event registered. -+ if self.reads[fd] then -+ self.io_events = self.io_events - 1 -+ self.reads[fd] = nil -+ return self.poller:del(fd) -+ end -+end -+ -+local function poller_do_work(self) -+ local tasks = #self.work_cur -+ -- check if there is any work -+ if tasks > 0 then -+ -- swap work queues. -+ local last, cur = self.work_cur, self.work_last -+ self.work_cur, self.work_last = cur, last -+ for i=1,tasks do -+ local task = last[i] -+ last[i] = nil -+ task() -+ end -+ -- return new work queue length. -+ return #cur -+ end -+ return tasks -+end -+ -+function poller_meths:start() -+ local do_io_event = self.do_io_event -+ local poller = self.poller -+ self.is_running = true -+ while self.is_running do -+ -- run work task -+ local new_work = poller_do_work(self) -+ -- wait == 0, if there is work to do, else wait == -1 -+ local wait = (new_work > 0) and 0 or -1 -+ -- poll for fd events, if there are events to poll for. -+--print("poller:step()", new_work, self.io_events) -+ if self.io_events > 0 then -+ assert(poller:wait_callback(do_io_event, wait)) -+ else -+ -- no io events to poll, do we still have work? -+ if #self.work_cur == 0 then -+ -- nothing to do, exit event loop -+ self.is_running = false -+ return -+ end -+ end -+ end -+end -+ -+function poller_meths:stop() -+ self.is_running = false -+end -+ -+-- module only exports a 'new' function. -+return { -+new = poller_new, -+} -diff --git a/examples/poller/ev.lua b/examples/poller/ev.lua -new file mode 100644 -index 0000000..f8b1733 ---- /dev/null -+++ b/examples/poller/ev.lua -@@ -0,0 +1,119 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local ev = require'ev' -+local ev_READ = ev.READ -+local ev_WRITE = ev.WRITE -+local loop = ev.Loop.default -+ -+assert(ev.Idle,"Need version > 1.3 of lua-ev that supports Idle watchers.") -+ -+local poller_meths = {} -+local poller_mt = {__index = poller_meths} -+ -+local function poller_new() -+ local self = { -+ work_cur = {}, -+ work_last = {}, -+ io_events = 0, -+ reads = {}, -+ idle_enabled = false, -+ } -+ -+ self.idle = ev.Idle.new(function() -+ local tasks = #self.work_cur -+ -- check if there is any work -+ if tasks > 0 then -+ -- swap work queues. -+ local last, cur = self.work_cur, self.work_last -+ self.work_cur, self.work_last = cur, last -+ for i=1,tasks do -+ local task = last[i] -+ last[i] = nil -+ task() -+ end -+ -- check if there is more work. -+ if #cur > 0 then -+ return -- don't disable idle watcher, when we have work. -+ end -+ end -+--print("STOP IDLE:", #self.work_cur, #self.work_last) -+ -- stop idle watcher, no work. -+ self.idle_enabled = false -+ self.idle:stop(loop) -+ end) -+ -- set priority to max, to make sure the work queue is processed on each loop. -+ self.idle:priority(ev.MAXPRI) -+ -+ return setmetatable(self, poller_mt) -+end -+ -+function poller_meths:add_work(task) -+ local idx = #self.work_cur + 1 -+ -- add task to current work queue. -+ self.work_cur[idx] = task -+ -- make sure the idle watcher is enabled. -+ if not self.idle_enabled then -+ self.idle_enabled = true -+ self.idle:start(loop) -+ end -+end -+ -+function poller_meths:add_read(fd, cb) -+ local io_read = self.reads[fd] -+ -- make sure read event hasn't been registered yet. -+ if not io_read then -+ self.io_events = self.io_events + 1 -+ io_read = ev.IO.new(function() -+ cb(fd) -+ end, fd, ev_READ) -+ self.reads[fd] = io_read -+ io_read:start(loop) -+ else -+ -- update read callback? -+ io_read:callback(cb) -+ -- need to re-start watcher? -+ if not io_read:is_active() then -+ io_read:start(loop) -+ end -+ end -+end -+ -+function poller_meths:remove_read(fd) -+ local io_read = self.reads[fd] -+ -- make sure there was a read event registered. -+ if io_read then -+ self.io_events = self.io_events - 1 -+ io_read:stop(loop) -+ end -+end -+ -+function poller_meths:start() -+ return loop:loop() -+end -+ -+function poller_meths:stop() -+ return loop:unloop() -+end -+ -+-- module only exports a 'new' function. -+return { -+new = poller_new, -+} -diff --git a/examples/publiser.lua b/examples/publiser.lua -deleted file mode 100644 -index 12e240e..0000000 ---- a/examples/publiser.lua -+++ /dev/null -@@ -1,32 +0,0 @@ ---- Copyright (c) 2010 Aleksey Yeschenko ---- ---- Permission is hereby granted, free of charge, to any person obtaining a copy ---- of this software and associated documentation files (the "Software"), to deal ---- in the Software without restriction, including without limitation the rights ---- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ---- copies of the Software, and to permit persons to whom the Software is ---- furnished to do so, subject to the following conditions: ---- ---- The above copyright notice and this permission notice shall be included in ---- all copies or substantial portions of the Software. ---- ---- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ---- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ---- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ---- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ---- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ---- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ---- THE SOFTWARE. -- --require("zmq") -- --local ctx = zmq.init(1) --local s = ctx:socket(zmq.PUB) -- --s:bind("tcp://lo:5555") -- --local msg_id = 1 --while true do -- s:send(tostring(msg_id)) -- msg_id = msg_id + 1 --end -diff --git a/examples/publisher.lua b/examples/publisher.lua -new file mode 100644 -index 0000000..a5f943e ---- /dev/null -+++ b/examples/publisher.lua -@@ -0,0 +1,32 @@ -+-- Copyright (c) 2010 Aleksey Yeschenko -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local zmq = require"zmq" -+ -+local ctx = zmq.init() -+local s = ctx:socket(zmq.PUB) -+ -+s:bind("tcp://lo:5555") -+ -+local msg_id = 1 -+while true do -+ s:send(tostring(msg_id)) -+ msg_id = msg_id + 1 -+end -diff --git a/examples/publisher_poll.lua b/examples/publisher_poll.lua -new file mode 100644 -index 0000000..0cfbe79 ---- /dev/null -+++ b/examples/publisher_poll.lua -@@ -0,0 +1,95 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local poller = require"examples.poller" -+local poll = poller.new() -+ -+local zmq = require"zmq" -+local z_NOBLOCK = zmq.NOBLOCK -+local z_EVENTS = zmq.EVENTS -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+ -+local ctx = zmq.init() -+local s = ctx:socket(zmq.PUB) -+local s_FD = s:getopt(zmq.FD) -+ -+s:bind("tcp://lo:5555") -+ -+-- current socket state -+local blocked_state -+local blocked_event -+local on_sock_recv -+local on_sock_send -+ -+-- IO event callback when socket was blocked -+local function on_sock_io() -+ local events = s:getopt(z_EVENTS) -+ local unblocked = false -+ if events == blocked_event then -+ -- got the event the socket was blocked on. -+ unblocked = true -+ elseif events == z_POLLIN_OUT then -+ -- got both in & out events -+ unblocked = true -+ end -+ if unblocked then -+ -- got the event we are blocked on resume. -+ blocked_event = nil -+ blocked_state() -+ -- check if blocked event was processed. -+ if not blocked_event then -+ poll:remove_read(s_FD) -+ end -+ end -+end -+local function sock_blocked(state, event) -+ if not blocked_event then -+ -- need to register socket's fd with event loop -+ poll:add_read(s_FD, on_sock_io) -+ end -+ blocked_state = state -+ blocked_event = event -+end -+ -+-- sock state functions -+local msg_id = 1 -+function on_sock_send() -+ local sent, err = s:send(tostring(msg_id), z_NOBLOCK) -+ if not sent then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_send, z_POLLOUT) -+ end -+ -- message sent, inc. id -+ msg_id = msg_id + 1 -+ -- yield back to event loop -+ poll:add_work(on_sock_send) -+end -+ -+-- start processing of the socket. -+poll:add_work(on_sock_send) -+ -+-- start event loop -+poll:start() -+ -+s:close() -+ctx:term() -+ -diff --git a/examples/server.lua b/examples/server.lua -index 57bb278..3423c4e 100644 ---- a/examples/server.lua -+++ b/examples/server.lua -@@ -18,14 +18,14 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - --require("zmq") -+local zmq = require"zmq" - --local ctx = zmq.init(1) -+local ctx = zmq.init() - local s = ctx:socket(zmq.REP) - - s:bind("tcp://lo:5555") - - while true do -- print(string.format("Received query: '%s'", s:recv())) -- s:send("OK") -+ print(string.format("Received query: '%s'", s:recv())) -+ s:send("OK") - end -diff --git a/examples/server_multipart.lua b/examples/server_multipart.lua -index 663c3f7..c26e3e0 100644 ---- a/examples/server_multipart.lua -+++ b/examples/server_multipart.lua -@@ -18,18 +18,18 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - --require("zmq") -+local zmq = require"zmq" - --local ctx = zmq.init(1) -+local ctx = zmq.init() - local s = ctx:socket(zmq.REP) - - s:bind("tcp://lo:5555") - - while true do -- local query = s:recv() -- while s:getopt(zmq.RCVMORE) == 1 do -- query = query .. s:recv() -- end -- print(string.format("Received query: '%s'", query)) -- s:send("OK") -+ local query = s:recv() -+ while s:getopt(zmq.RCVMORE) == 1 do -+ query = query .. s:recv() -+ end -+ print(string.format("Received query: '%s'", query)) -+ s:send("OK") - end -diff --git a/examples/server_poll.lua b/examples/server_poll.lua -new file mode 100644 -index 0000000..42c8862 ---- /dev/null -+++ b/examples/server_poll.lua -@@ -0,0 +1,102 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local poller = require"examples.poller" -+local poll = poller.new() -+ -+local zmq = require"zmq" -+local z_NOBLOCK = zmq.NOBLOCK -+local z_EVENTS = zmq.EVENTS -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+ -+local ctx = zmq.init() -+local s = ctx:socket(zmq.REP) -+local s_FD = s:getopt(zmq.FD) -+ -+s:bind("tcp://lo:5555") -+ -+-- current socket state -+local blocked_state -+local blocked_event -+local on_sock_recv -+local on_sock_send -+ -+-- IO event callback when socket was blocked -+local function on_sock_io() -+ local events = s:getopt(z_EVENTS) -+ local unblocked = false -+ if events == blocked_event then -+ -- got the event the socket was blocked on. -+ unblocked = true -+ elseif events == z_POLLIN_OUT then -+ -- got both in & out events -+ unblocked = true -+ end -+ if unblocked then -+ -- got the event we are blocked on resume. -+ blocked_event = nil -+ blocked_state() -+ -- check if blocked event was processed. -+ if not blocked_event then -+ poll:remove_read(s_FD) -+ end -+ end -+end -+local function sock_blocked(state, event) -+ if not blocked_event then -+ -- need to register socket's fd with event loop -+ poll:add_read(s_FD, on_sock_io) -+ end -+ blocked_state = state -+ blocked_event = event -+end -+ -+-- sock state functions -+function on_sock_recv() -+ local data, err = s:recv(z_NOBLOCK) -+ if not data then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_recv, z_POLLIN) -+ end -+ print(string.format("Received query: '%s'", data)) -+ return on_sock_send() -+end -+ -+function on_sock_send() -+ local sent, err = s:send("OK", z_NOBLOCK) -+ if not sent then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_send, z_POLLOUT) -+ end -+ -- yield back to event loop -+ poll:add_work(on_sock_recv) -+end -+ -+-- start processing of the socket. -+poll:add_work(on_sock_recv) -+ -+-- start event loop -+poll:start() -+ -+s:close() -+ctx:term() -+ -diff --git a/examples/subscriber.lua b/examples/subscriber.lua -index 370b7dc..41434c7 100644 ---- a/examples/subscriber.lua -+++ b/examples/subscriber.lua -@@ -18,14 +18,14 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - --require("zmq") -+local zmq = require"zmq" - --local ctx = zmq.init(1) -+local ctx = zmq.init() - local s = ctx:socket(zmq.SUB) - s:setopt(zmq.SUBSCRIBE, "") - s:connect("tcp://localhost:5555") - while true do -- local msg = s:recv() -- local msg_id = tonumber(msg) -- if math.mod(msg_id, 10000) == 0 then print(msg_id) end -+ local msg = s:recv() -+ local msg_id = tonumber(msg) -+ if math.mod(msg_id, 10000) == 0 then print(msg_id) end - end -diff --git a/examples/subscriber_ev.lua b/examples/subscriber_ev.lua -new file mode 100644 -index 0000000..ae8506c ---- /dev/null -+++ b/examples/subscriber_ev.lua -@@ -0,0 +1,113 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local zmq = require"zmq" -+local z_NOBLOCK = zmq.NOBLOCK -+local z_EVENTS = zmq.EVENTS -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+local ev = require'ev' -+local loop = ev.Loop.default -+ -+-- define a sub_worker class -+local sub_worker_mt = {} -+function sub_worker_mt:close(...) -+ self.s_io_idle:stop(self.loop) -+ self.s_io_read:stop(self.loop) -+ return self.socket:close(...) -+end -+function sub_worker_mt:bind(...) -+ return self.socket:bind(...) -+end -+function sub_worker_mt:connect(...) -+ return self.socket:connect(...) -+end -+function sub_worker_mt:sub(topic) -+ return self.socket:setopt(zmq.SUBSCRIBE, topic) -+end -+function sub_worker_mt:unsub(topic) -+ return self.socket:setopt(zmq.UNSUBSCRIBE, topic) -+end -+sub_worker_mt.__index = sub_worker_mt -+ -+local function sub_worker(loop, ctx, msg_cb) -+ local s = ctx:socket(zmq.SUB) -+ local self = { loop = loop, socket = s, msg_cb = msg_cb } -+ setmetatable(self, sub_worker_mt) -+ -- create ev callbacks for recving data. -+ -- need idle watcher since ZeroMQ sockets are edge-triggered instead of level-triggered -+ local s_io_idle -+ local s_io_read -+ local max_recvs = 10 -+ local function s_recv(recv_cnt) -+ local msg, err = s:recv(z_NOBLOCK) -+ if err == 'timeout' then -+ -- need to block on read IO -+ return false -+ end -+ self:msg_cb(msg) -+ if recv_cnt > 1 then -+ return s_recv(recv_cnt - 1) -+ end -+ return true -+ end -+ s_io_idle = ev.Idle.new(function() -+ if not s_recv(max_recvs) then -+ -- need to block on read IO -+ s_io_idle:stop(loop) -+ s_io_read:start(loop) -+ end -+ end) -+ s_io_idle:start(loop) -+ s_io_read = ev.IO.new(function() -+ local events = s:getopt(z_EVENTS) -+ if events == z_POLLIN or events == z_POLLIN_OUT then -+ if s_recv(max_recvs) then -+ -- read IO is not block, enable idle watcher to handle reads. -+ s_io_idle:start(loop) -+ s_io_read:stop(loop) -+ end -+ end -+ end, s:getopt(zmq.FD), ev.READ) -+ self.s_io_idle = s_io_idle -+ self.s_io_read = s_io_read -+ return self -+end -+ -+local ctx = zmq.init() -+ -+-- message handling function. -+local function handle_msg(worker, msg) -+ local msg_id = tonumber(msg) -+ if math.mod(msg_id, 10000) == 0 then print(worker.id, msg_id) end -+end -+ -+local sub1 = sub_worker(loop, ctx, handle_msg) -+sub1.id = 'sub1' -+sub1:sub('') -+sub1:connect("tcp://localhost:5555") -+local sub2 = sub_worker(loop, ctx, handle_msg) -+sub2.id = 'sub2' -+sub2:sub('') -+sub2:connect("tcp://localhost:5555") -+ -+loop:loop() -+ -diff --git a/examples/subscriber_poll.lua b/examples/subscriber_poll.lua -new file mode 100644 -index 0000000..1be24b2 ---- /dev/null -+++ b/examples/subscriber_poll.lua -@@ -0,0 +1,96 @@ -+-- Copyright (c) 2012 Robert G. Jakabosky -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+local poller = require"examples.poller" -+local poll = poller.new() -+ -+local zmq = require"zmq" -+local z_NOBLOCK = zmq.NOBLOCK -+local z_EVENTS = zmq.EVENTS -+local z_POLLIN = zmq.POLLIN -+local z_POLLOUT = zmq.POLLOUT -+local z_POLLIN_OUT = z_POLLIN + z_POLLOUT -+ -+local N=tonumber(arg[1] or 100) -+ -+local ctx = zmq.init() -+local s = ctx:socket(zmq.SUB) -+local s_FD = s:getopt(zmq.FD) -+ -+s:setopt(zmq.SUBSCRIBE, "") -+s:connect("tcp://localhost:5555") -+ -+-- current socket state -+local blocked_state -+local blocked_event -+local on_sock_recv -+local on_sock_send -+ -+-- IO event callback when socket was blocked -+local function on_sock_io() -+ local events = s:getopt(z_EVENTS) -+ local unblocked = false -+ if events == blocked_event then -+ -- got the event the socket was blocked on. -+ unblocked = true -+ elseif events == z_POLLIN_OUT then -+ -- got both in & out events -+ unblocked = true -+ end -+ if unblocked then -+ -- got the event we are blocked on resume. -+ blocked_event = nil -+ blocked_state() -+ -- check if blocked event was processed. -+ if not blocked_event then -+ poll:remove_read(s_FD) -+ end -+ end -+end -+local function sock_blocked(state, event) -+ if not blocked_event then -+ -- need to register socket's fd with event loop -+ poll:add_read(s_FD, on_sock_io) -+ end -+ blocked_state = state -+ blocked_event = event -+end -+ -+-- sock state functions -+function on_sock_recv() -+ local data, err = s:recv(z_NOBLOCK) -+ if not data then -+ assert(err == 'timeout', "Bad error on zmq socket.") -+ return sock_blocked(on_sock_recv, z_POLLIN) -+ end -+ local msg_id = tonumber(data) -+ if (msg_id % 10000) == 0 then print(data) end -+ return on_sock_recv() -+end -+ -+-- start processing of the socket. -+poll:add_work(on_sock_recv) -+ -+-- start event loop -+poll:start() -+ -+s:close() -+ctx:term() -+ -diff --git a/perf/local_lat.lua b/perf/local_lat.lua -index d6a4ec1..027c583 100644 ---- a/perf/local_lat.lua -+++ b/perf/local_lat.lua -@@ -35,11 +35,26 @@ s:bind(bind_to) - - local msg = zmq.zmq_msg_t() - -+local timer -+ - for i = 1, roundtrip_count do - assert(s:recv_msg(msg)) -+ if not timer then -+ timer = zmq.stopwatch_start() -+ end - assert(msg:size() == message_size, "Invalid message size") - assert(s:send_msg(msg)) - end - -+local elapsed = timer:stop() -+ - s:close() - ctx:term() -+ -+local latency = elapsed / roundtrip_count / 2 -+ -+print(string.format("mean latency: %.3f [us]", latency)) -+local secs = elapsed / (1000 * 1000) -+print(string.format("elapsed = %f", secs)) -+print(string.format("msg/sec = %f", roundtrip_count / secs)) -+ -diff --git a/perf/local_thr_poll.lua b/perf/local_thr_poll.lua -new file mode 100644 -index 0000000..bfe0d33 ---- /dev/null -+++ b/perf/local_thr_poll.lua -@@ -0,0 +1,77 @@ -+-- Copyright (c) 2010 Aleksey Yeschenko -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+if not arg[3] then -+ print("usage: lua local_thr.lua ") -+ os.exit() -+end -+ -+local bind_to = arg[1] -+local message_size = tonumber(arg[2]) -+local message_count = tonumber(arg[3]) -+ -+local zmq = require"zmq" -+local z_poller = require"zmq.poller" -+local z_NOBLOCK = zmq.NOBLOCK -+ -+local poller = z_poller(64) -+ -+local ctx = zmq.init(1) -+local s = ctx:socket(zmq.SUB) -+s:setopt(zmq.SUBSCRIBE, ""); -+s:bind(bind_to) -+ -+print(string.format("message size: %i [B]", message_size)) -+print(string.format("message count: %i", message_count)) -+ -+local msg -+msg = zmq.zmq_msg_t() -+ -+local cnt = 0 -+ -+poller:add(s, zmq.POLLIN, function(sock) -+ while s:recv_msg(msg, z_NOBLOCK) do -+ --assert(msg:size() == message_size, "Invalid message size") -+ cnt = cnt + 1 -+ if cnt == message_count then -+ poller:stop() -+ end -+ end -+end) -+ -+-- wait for first message -+assert(s:recv_msg(msg)) -+cnt = 1 -+ -+local timer = zmq.stopwatch_start() -+poller:start() -+local elapsed = timer:stop() -+ -+s:close() -+ctx:term() -+ -+if elapsed == 0 then elapsed = 1 end -+ -+local throughput = message_count / (elapsed / 1000000) -+local megabits = throughput * message_size * 8 / 1000000 -+ -+print(string.format("mean throughput: %i [msg/s]", throughput)) -+print(string.format("mean throughput: %.3f [Mb/s]", megabits)) -+ -diff --git a/perf/local_thr_push_pull.lua b/perf/local_thr_push_pull.lua -new file mode 100644 -index 0000000..9b2dee2 ---- /dev/null -+++ b/perf/local_thr_push_pull.lua -@@ -0,0 +1,62 @@ -+-- Copyright (c) 2010 Aleksey Yeschenko -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+if not arg[3] then -+ print("usage: lua local_thr.lua ") -+ os.exit() -+end -+ -+local bind_to = arg[1] -+local message_size = tonumber(arg[2]) -+local message_count = tonumber(arg[3]) -+ -+local zmq = require"zmq" -+ -+local ctx = zmq.init(1) -+local s = ctx:socket(zmq.PULL) -+s:bind(bind_to) -+ -+print(string.format("message size: %i [B]", message_size)) -+print(string.format("message count: %i", message_count)) -+ -+local msg -+msg = zmq.zmq_msg_t() -+assert(s:recv_msg(msg)) -+ -+local timer = zmq.stopwatch_start() -+ -+for i = 1, message_count - 1 do -+ assert(s:recv_msg(msg)) -+ assert(msg:size() == message_size, "Invalid message size") -+end -+ -+local elapsed = timer:stop() -+ -+s:close() -+ctx:term() -+ -+if elapsed == 0 then elapsed = 1 end -+ -+local throughput = message_count / (elapsed / 1000000) -+local megabits = throughput * message_size * 8 / 1000000 -+ -+print(string.format("mean throughput: %i [msg/s]", throughput)) -+print(string.format("mean throughput: %.3f [Mb/s]", megabits)) -+ -diff --git a/perf/remote_lat.lua b/perf/remote_lat.lua -index 4376f60..ebcc680 100644 ---- a/perf/remote_lat.lua -+++ b/perf/remote_lat.lua -@@ -54,3 +54,4 @@ local latency = elapsed / roundtrip_count / 2 - print(string.format("message size: %i [B]", message_size)) - print(string.format("roundtrip count: %i", roundtrip_count)) - print(string.format("mean latency: %.3f [us]", latency)) -+ -diff --git a/perf/remote_thr.lua b/perf/remote_thr.lua -index 967e08b..5890508 100644 ---- a/perf/remote_thr.lua -+++ b/perf/remote_thr.lua -@@ -31,8 +31,12 @@ local zmq = require"zmq" - - local ctx = zmq.init(1) - local s = ctx:socket(zmq.PUB) -+-- for ZeroMQ 3.x need to change HWM option. -+s:set_hwm(0) - s:connect(connect_to) - -+zmq.sleep(1) -+ - local data = ("0"):rep(message_size) - local msg_data = zmq.zmq_msg_t.init_data(data) - local msg = zmq.zmq_msg_t.init() -@@ -42,7 +46,6 @@ for i = 1, message_count do - assert(s:send_msg(msg)) - end - ----os.execute("sleep " .. 10) -- - s:close() - ctx:term() -+ -diff --git a/perf/remote_thr_push_pull.lua b/perf/remote_thr_push_pull.lua -new file mode 100644 -index 0000000..11be905 ---- /dev/null -+++ b/perf/remote_thr_push_pull.lua -@@ -0,0 +1,49 @@ -+-- Copyright (c) 2010 Aleksey Yeschenko -+-- -+-- Permission is hereby granted, free of charge, to any person obtaining a copy -+-- of this software and associated documentation files (the "Software"), to deal -+-- in the Software without restriction, including without limitation the rights -+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+-- copies of the Software, and to permit persons to whom the Software is -+-- furnished to do so, subject to the following conditions: -+-- -+-- The above copyright notice and this permission notice shall be included in -+-- all copies or substantial portions of the Software. -+-- -+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+-- THE SOFTWARE. -+ -+if not arg[3] then -+ print("usage: lua remote_thr.lua ") -+ os.exit() -+end -+ -+local connect_to = arg[1] -+local message_size = tonumber(arg[2]) -+local message_count = tonumber(arg[3]) -+ -+local zmq = require"zmq" -+ -+local ctx = zmq.init(1) -+local s = ctx:socket(zmq.PUSH) -+s:connect(connect_to) -+ -+zmq.sleep(1) -+ -+local data = ("0"):rep(message_size) -+local msg_data = zmq.zmq_msg_t.init_data(data) -+local msg = zmq.zmq_msg_t.init() -+ -+for i = 1, message_count do -+ msg:copy(msg_data) -+ assert(s:send_msg(msg)) -+end -+ -+s:close() -+ctx:term() -+ -diff --git a/perf/thread_lat.lua b/perf/thread_lat.lua -index 93ed691..f781e55 100644 ---- a/perf/thread_lat.lua -+++ b/perf/thread_lat.lua -@@ -64,6 +64,8 @@ local msg = zmq.zmq_msg_t.init_size(message_size) - print(string.format("message size: %i [B]", message_size)) - print(string.format("roundtrip count: %i", roundtrip_count)) - -+zmq.sleep(2) -- wait for child thread to connect. -+ - local timer = zmq.stopwatch_start() - - for i = 1, roundtrip_count do -@@ -81,4 +83,7 @@ ctx:term() - local latency = elapsed / roundtrip_count / 2 - - print(string.format("mean latency: %.3f [us]", latency)) -+local secs = elapsed / (1000 * 1000) -+print(string.format("elapsed = %f", secs)) -+print(string.format("msg/sec = %f", roundtrip_count / secs)) - -diff --git a/perf/thread_push_pull.lua b/perf/thread_push_pull.lua -index f69ff48..b3d96cb 100644 ---- a/perf/thread_push_pull.lua -+++ b/perf/thread_push_pull.lua -@@ -42,12 +42,13 @@ local child_code = [[ - s:connect(connect_to) - - local data = ("0"):rep(message_size) -- local msg = zmq.zmq_msg_t.init_size(message_size) -+ local msg_data = zmq.zmq_msg_t.init_data(data) -+ local msg = zmq.zmq_msg_t.init() - - local timer = zmq.stopwatch_start() - - for i = 1, message_count do -- msg:set_data(data) -+ msg:copy(msg_data) - assert(s:send_msg(msg)) - end - -diff --git a/perf/thread_thr.lua b/perf/thread_thr.lua -index 7b9183a..d3958e8 100644 ---- a/perf/thread_thr.lua -+++ b/perf/thread_thr.lua -@@ -38,6 +38,8 @@ local child_code = [[ - - local ctx = zthreads.get_parent_ctx() - local s = ctx:socket(zmq.PUB) -+ -- for ZeroMQ 3.x need to change HWM option. -+ s:set_hwm(0) - s:connect(connect_to) - - local data = ("0"):rep(message_size) -diff --git a/rockspecs/lua-zmq-scm-1.rockspec b/rockspecs/lua-zmq-scm-1.rockspec -index 10737b7..b3cd3c6 100644 ---- a/rockspecs/lua-zmq-scm-1.rockspec -+++ b/rockspecs/lua-zmq-scm-1.rockspec -@@ -12,12 +12,28 @@ dependencies = { - "lua >= 5.1", - } - external_dependencies = { -+ platforms = { -+ windows = { -+ ZEROMQ = { -+ library = "libzmq", -+ } -+ }, -+ }, - ZEROMQ = { - header = "zmq.h", - library = "zmq", - } - } - build = { -+ platforms = { -+ windows = { -+ modules = { -+ zmq = { -+ libraries = {"libzmq"}, -+ } -+ } -+ }, -+ }, - type = "builtin", - modules = { - zmq = { -diff --git a/rockspecs/lua-zmq-wireshark-scm-0.rockspec b/rockspecs/lua-zmq-wireshark-scm-0.rockspec -new file mode 100644 -index 0000000..5e3e0e1 ---- /dev/null -+++ b/rockspecs/lua-zmq-wireshark-scm-0.rockspec -@@ -0,0 +1,22 @@ -+package = "lua-zmq-wireshark" -+version = "scm-0" -+source = { -+ url = "git://github.com/Neopallium/lua-zmq.git", -+} -+description = { -+ summary = "Lua Wireshark dissector for the ZeroMQ protocol.", -+ homepage = "http://github.com/Neopallium/lua-zmq", -+ -- Wireshark requires dissectors to be licensed under the GPL. -+ license = "GPL", -+} -+dependencies = {} -+build = { -+ type = "none", -+ install = { -+ lua = { -+ ['zmq.ws.dissector'] = "ws/dissector.lua", -+ ['zmq.ws.tap'] = "ws/tap.lua", -+ ['zmq.ws.stats_tap'] = "ws/stats_tap.lua", -+ }, -+ }, -+} -diff --git a/src/ctx.nobj.lua b/src/ctx.nobj.lua -index adc0c42..246b653 100644 ---- a/src/ctx.nobj.lua -+++ b/src/ctx.nobj.lua -@@ -19,6 +19,7 @@ - -- THE SOFTWARE. - - object "ZMQ_Ctx" { -+ sys_include"string.h", - error_on_null = "get_zmq_strerror()", - c_source [[ - typedef struct ZMQ_Ctx ZMQ_Ctx; -diff --git a/src/error.nobj.lua b/src/error.nobj.lua -index 4e353f3..b5559c7 100644 ---- a/src/error.nobj.lua -+++ b/src/error.nobj.lua -@@ -18,26 +18,295 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - -+-- E* error values. -+meta_object "ZErrors" { -+ export_definitions { -+ -- Native 0MQ error codes. -+ "EFSM", -+ "ENOCOMPATPROTO", -+ "ETERM", -+ "EMTHREAD", -+ -+ "EPERM", -- Operation not permitted -+ "ENOENT", -- No such file or directory -+ "ESRCH", -- No such process -+ "EINTR", -- Interrupted system call -+ "EIO", -- I/O error -+ "ENXIO", -- No such device or address -+ "E2BIG", -- Argument list too long -+ "ENOEXEC", -- Exec format error -+ "EBADF", -- Bad file number -+ "ECHILD", -- No child processes -+ "EAGAIN", -- Try again -+ "ENOMEM", -- Out of memory -+ "EACCES", -- Permission denied -+ "EFAULT", -- Bad address -+ "ENOTBLK", -- Block device required -+ "EBUSY", -- Device or resource busy -+ "EEXIST", -- File exists -+ "EXDEV", -- Cross-device link -+ "ENODEV", -- No such device -+ "ENOTDIR", -- Not a directory -+ "EISDIR", -- Is a directory -+ "EINVAL", -- Invalid argument -+ "ENFILE", -- File table overflow -+ "EMFILE", -- Too many open files -+ "ENOTTY", -- Not a typewriter -+ "ETXTBSY", -- Text file busy -+ "EFBIG", -- File too large -+ "ENOSPC", -- No space left on device -+ "ESPIPE", -- Illegal seek -+ "EROFS", -- Read-only file system -+ "EMLINK", -- Too many links -+ "EPIPE", -- Broken pipe -+ "EDOM", -- Math argument out of domain of func -+ "ERANGE", -- Math result not representable -+ -+ "EDEADLK", -- Resource deadlock would occur -+ "EDEADLOCK", -- EDEADLK -+ "ENAMETOOLONG", -- File name too long -+ "ENOLCK", -- No record locks available -+ "ENOSYS", -- Function not implemented -+ "ENOTEMPTY", -- Directory not empty -+ "ELOOP", -- Too many symbolic links encountered -+ "EWOULDBLOCK", -- Operation would block -+ "ENOMSG", -- No message of desired type -+ "EIDRM", -- Identifier removed -+ "ECHRNG", -- Channel number out of range -+ "EL2NSYNC", -- Level 2 not synchronized -+ "EL3HLT", -- Level 3 halted -+ "EL3RST", -- Level 3 reset -+ "ELNRNG", -- Link number out of range -+ "EUNATCH", -- Protocol driver not attached -+ "ENOCSI", -- No CSI structure available -+ "EL2HLT", -- Level 2 halted -+ "EBADE", -- Invalid exchange -+ "EBADR", -- Invalid request descriptor -+ "EXFULL", -- Exchange full -+ "ENOANO", -- No anode -+ "EBADRQC", -- Invalid request code -+ "EBADSLT", -- Invalid slot -+ -+ "EBFONT", -- Bad font file format -+ "ENOSTR", -- Device not a stream -+ "ENODATA", -- No data available -+ "ETIME", -- Timer expired -+ "ENOSR", -- Out of streams resources -+ "ENONET", -- Machine is not on the network -+ "ENOPKG", -- Package not installed -+ "EREMOTE", -- Object is remote -+ "ENOLINK", -- Link has been severed -+ "EADV", -- Advertise error -+ "ESRMNT", -- Srmount error -+ "ECOMM", -- Communication error on send -+ "EPROTO", -- Protocol error -+ "EMULTIHOP", -- Multihop attempted -+ "EDOTDOT", -- RFS specific error -+ "EBADMSG", -- Not a data message -+ "EOVERFLOW", -- Value too large for defined data type -+ "ENOTUNIQ", -- Name not unique on network -+ "EBADFD", -- File descriptor in bad state -+ "EREMCHG", -- Remote address changed -+ "ELIBACC", -- Can not access a needed shared library -+ "ELIBBAD", -- Accessing a corrupted shared library -+ "ELIBSCN", -- .lib section in a.out corrupted -+ "ELIBMAX", -- Attempting to link in too many shared libraries -+ "ELIBEXEC", -- Cannot exec a shared library directly -+ "EILSEQ", -- Illegal byte sequence -+ "ERESTART", -- Interrupted system call should be restarted -+ "ESTRPIPE", -- Streams pipe error -+ "EUSERS", -- Too many users -+ "ENOTSOCK", -- Socket operation on non-socket -+ "EDESTADDRREQ", -- Destination address required -+ "EMSGSIZE", -- Message too long -+ "EPROTOTYPE", -- Protocol wrong type for socket -+ "ENOPROTOOPT", -- Protocol not available -+ "EPROTONOSUPPORT", -- Protocol not supported -+ "ESOCKTNOSUPPORT", -- Socket type not supported -+ "EOPNOTSUPP", -- Operation not supported on transport endpoint -+ "EPFNOSUPPORT", -- Protocol family not supported -+ "EAFNOSUPPORT", -- Address family not supported by protocol -+ "EADDRINUSE", -- Address already in use -+ "EADDRNOTAVAIL", -- Cannot assign requested address -+ "ENETDOWN", -- Network is down -+ "ENETUNREACH", -- Network is unreachable -+ "ENETRESET", -- Network dropped connection because of reset -+ "ECONNABORTED", -- Software caused connection abort -+ "ECONNRESET", -- Connection reset by peer -+ "ENOBUFS", -- No buffer space available -+ "EISCONN", -- Transport endpoint is already connected -+ "ENOTCONN", -- Transport endpoint is not connected -+ "ESHUTDOWN", -- Cannot send after transport endpoint shutdown -+ "ETOOMANYREFS", -- Too many references: cannot splice -+ "ETIMEDOUT", -- Connection timed out -+ "ECONNREFUSED", -- Connection refused -+ "EHOSTDOWN", -- Host is down -+ "EHOSTUNREACH", -- No route to host -+ "EALREADY", -- Operation already in progress -+ "EINPROGRESS", -- Operation now in progress -+ "ESTALE", -- Stale NFS file handle -+ "EUCLEAN", -- Structure needs cleaning -+ "ENOTNAM", -- Not a XENIX named type file -+ "ENAVAIL", -- No XENIX semaphores available -+ "EISNAM", -- Is a named type file -+ "EREMOTEIO", -- Remote I/O error -+ "EDQUOT", -- Quota exceeded -+ -+ "ENOMEDIUM", -- No medium found -+ "EMEDIUMTYPE", -- Wrong medium type -+ "ECANCELED", -- Operation Canceled -+ "ENOKEY", -- Required key not available -+ "EKEYEXPIRED", -- Key has expired -+ "EKEYREVOKED", -- Key has been revoked -+ "EKEYREJECTED", -- Key was rejected by service -+ -+ -- for robust mutexes -+ "EOWNERDEAD", -- Owner died -+ "ENOTRECOVERABLE", -- State not recoverable -+ -+ "ERFKILL", -- Operation not possible due to RF-kill -+ }, -+ -+ method "description" { -+ var_in{ "", "err" }, -+ var_out{ "const char *", "msg" }, -+ c_source "pre" [[ -+ int err_type; -+ int err_num = -1; -+]], -+ c_source[[ -+ err_type = lua_type(L, ${err::idx}); -+ if(err_type == LUA_TSTRING) { -+ lua_pushvalue(L, ${err::idx}); -+ lua_rawget(L, ${this::idx}); -+ if(lua_isnumber(L, -1)) { -+ err_num = lua_tointeger(L, -1); -+ } -+ lua_pop(L, 1); -+ } else if(err_type == LUA_TNUMBER) { -+ err_num = lua_tointeger(L, ${err::idx}); -+ } else { -+ return luaL_argerror(L, ${err::idx}, "expected string/number"); -+ } -+ if(err_num < 0) { -+ lua_pushnil(L); -+ lua_pushliteral(L, "UNKNOWN ERROR"); -+ return 2; -+ } -+ ${msg} = strerror(err_num); -+]], -+ }, -+ -+ method "__index" { -+ var_in{ "int", "err" }, -+ var_out{ "const char *", "msg" }, -+ c_source[[ -+ switch(${err}) { -+ case EAGAIN: -+ ${msg} = "timeout"; -+ break; -+ case EINTR: -+ ${msg} = "interrupted"; -+ break; -+#if defined(ETERM) -+ case ETERM: -+ ${msg} = "closed"; -+ break; -+#endif -+ default: -+ ${msg} = zmq_strerror(${err}); -+ break; -+ } -+ lua_pushvalue(L, ${err::idx}); -+ lua_pushstring(L, ${msg}); -+ lua_rawset(L, ${this::idx}); -+]], -+ }, -+} -+ -+ffi_cdef[[ -+int zmq_errno (void); -+]] -+ -+ffi_source "ffi_src" [[ -+-- get ZErrors table to map errno to error name. -+local ZError_names = _M.ZErrors -+ -+local function get_zmq_strerror() -+ return ZError_names[C.zmq_errno()] -+end -+]] -+ -+c_source "extra_code" [[ -+static char *zmq_ZErrors_key = "zmq_ZErrors_key"; -+/* -+ * This wrapper function is to make the EAGAIN/ETERM error messages more like -+ * what is returned by LuaSocket. -+ */ -+static const char *get_zmq_strerror() { -+ int err = zmq_errno(); -+ switch(err) { -+ case EAGAIN: -+ return "timeout"; -+ break; -+ case EINTR: -+ return "interrupted"; -+ break; -+#if defined(ETERM) -+ case ETERM: -+ return "closed"; -+ break; -+#endif -+ default: -+ break; -+ } -+ return zmq_strerror(err); -+} -+ -+]] -+ -+c_source "module_init_src" [[ -+ /* Cache reference to zmq.ZErrors table for errno->string convertion. */ -+ lua_pushlightuserdata(L, zmq_ZErrors_key); -+ lua_getfield(L, -2, "ZErrors"); -+ lua_rawset(L, LUA_REGISTRYINDEX); -+]] -+ - -- Convert ZMQ Error codes into strings. - -- - -- This is an error code wrapper object, it converts C-style 'int' return error code - -- into Lua-style 'nil, "Error message"' return values. - -- - error_code "ZMQ_Error" "int" { -- ffi_cdef[[ --typedef int ZMQ_Error; --]], -+ ffi_type = "int", - is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end, - ffi_is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end, - default = "0", - c_source [[ -+ int num; - if(-1 == err) { -- err_str = get_zmq_strerror(); -+ /* get ZErrors table. */ -+ lua_pushlightuserdata(L, zmq_ZErrors_key); -+ lua_rawget(L, LUA_REGISTRYINDEX); -+ /* convert zmq_errno to string. */ -+ num = zmq_errno(); -+ lua_pushinteger(L, num); -+ lua_gettable(L, -2); -+ /* remove ZErrors table. */ -+ lua_remove(L, -2); -+ if(!lua_isnil(L, -1)) { -+ /* found error. */ -+ return; -+ } -+ /* Unknown error. */ -+ lua_pop(L, 1); -+ lua_pushfstring(L, "UNKNOWN ERROR(%d)", num); -+ return; - } - ]], - ffi_source [[ - if(-1 == err) then -- err_str = get_zmq_strerror(); -+ err_str = ZError_names[C.zmq_errno()] - end - ]], - } -diff --git a/src/msg.nobj.lua b/src/msg.nobj.lua -index 28e18ed..c46e189 100644 ---- a/src/msg.nobj.lua -+++ b/src/msg.nobj.lua -@@ -21,6 +21,22 @@ - object "zmq_msg_t" { - -- store the `zmq_msg_t` structure in Lua userdata object - userdata_type = "embed", -+ implements "Buffer" { -+ implement_method "const_data" { -+ c_function = "zmq_msg_data" -+ }, -+ implement_method "get_size" { -+ c_function = "zmq_msg_size" -+ }, -+ }, -+ implements "MutableBuffer" { -+ implement_method "data" { -+ c_function = "zmq_msg_data" -+ }, -+ implement_method "get_size" { -+ c_function = "zmq_msg_size" -+ }, -+ }, - -- - -- Define zmq_msq_t type & function API for FFI - -- -@@ -34,42 +50,31 @@ struct zmq_msg_t - unsigned char vsm_data [30]; /* that '30' is from 'MAX_VSM_SIZE' */ - }; - --typedef void (zmq_free_fn) (void *data, void *hint); -- - int zmq_msg_init (zmq_msg_t *msg); - int zmq_msg_init_size (zmq_msg_t *msg, size_t size); --int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint); - - ]], - constructor "init" { -- var_out{ "ZMQ_Error", "err" }, -- c_source[[ -- zmq_msg_t tmp; -- ${this} = &tmp; -- ${err} = zmq_msg_init(${this}); --]], -+ c_method_call "ZMQ_Error" "zmq_msg_init" {}, - }, - constructor "init_size" { -- var_in{ "size_t", "size" }, -- var_out{ "ZMQ_Error", "err" }, -- c_source[[ -- zmq_msg_t tmp; -- ${this} = &tmp; -- ${err} = zmq_msg_init_size(${this}, ${size}); --]], -+ c_method_call "ZMQ_Error" "zmq_msg_init_size" { "size_t", "size" }, - }, - constructor "init_data" { - var_in{ "const char *", "data" }, -- var_out{ "ZMQ_Error", "err" }, -+ c_method_call { "ZMQ_Error", "err" } "zmq_msg_init_size" { "size_t", "#data" }, - c_source[[ -- zmq_msg_t tmp; -- ${this} = &tmp; -- ${err} = zmq_msg_init_size(${this}, ${data_len}); - if(0 == ${err}) { - /* fill message */ - memcpy(zmq_msg_data(${this}), ${data}, ${data_len}); - } - ]], -+ ffi_source[[ -+ if(0 == ${err}) then -+ -- fill message -+ ffi.copy(C.zmq_msg_data(${this}), ${data}, ${data_len}) -+ end -+]], - }, - destructor { - c_method_call "ZMQ_Error" "zmq_msg_close" {} -@@ -143,7 +148,7 @@ int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn - ]], - }, - method "size" { -- c_method_call "size_t" "zmq_msg_size" {} -+ c_method_call { "size_t", "size", ffi_wrap = "tonumber"} "zmq_msg_size" {} - }, - method "__tostring" { - var_out{ "const char *", "data", has_length = true }, -diff --git a/src/poller.lua b/src/poller.lua -index 8c77337..2ca40ea 100644 ---- a/src/poller.lua -+++ b/src/poller.lua -@@ -34,43 +34,36 @@ local poller_mt = {} - poller_mt.__index = poller_mt - - function poller_mt:add(sock, events, cb) -- self.poller:add(sock, events) -- self.callbacks[sock] = cb -+ local id = self.poller:add(sock, events) -+ self.callbacks[id] = function(revents) return cb(sock, revents) end - end - - function poller_mt:modify(sock, events, cb) -+ local id - if events ~= 0 and cb then -- self.callbacks[sock] = cb -- self.poller:modify(sock, events) -+ id = self.poller:modify(sock, events) -+ self.callbacks[id] = function(revents) return cb(sock, revents) end - else -- self:remove(sock) -+ id = self:remove(sock) -+ self.callbacks[id] = nil - end - end - - function poller_mt:remove(sock) -- self.poller:remove(sock) -- self.callbacks[sock] = nil -+ local id = self.poller:remove(sock) -+ self.callbacks[id] = nil - end - - function poller_mt:poll(timeout) - local poller = self.poller -- local status, err = poller:poll(timeout) -- if not status then -+ local count, err = poller:poll(timeout) -+ if not count then - return nil, err - end - local callbacks = self.callbacks -- local count = 0 -- while true do -- local sock, revents = poller:next_revents() -- if not sock then -- break -- end -- local cb = callbacks[sock] -- if not cb then -- error("Missing callback for sock:" .. tostring(sock)) -- end -- cb(sock, revents) -- count = count + 1 -+ for i=1,count do -+ local id, revents = poller:next_revents_idx() -+ callbacks[id](revents) - end - return count - end -@@ -78,7 +71,7 @@ end - function poller_mt:start() - self.is_running = true - while self.is_running do -- local status, err = self:poll(-1) -+ status, err = self:poll(-1) - if not status then - return false, err - end -@@ -90,14 +83,15 @@ function poller_mt:stop() - self.is_running = false - end - --module(...) -+local M = {} - --function new(pre_alloc) -+function M.new(pre_alloc) - return setmetatable({ - poller = zmq.ZMQ_Poller(pre_alloc), -- callbacks = setmetatable({}, {__mode="k"}), -+ callbacks = {}, - }, poller_mt) - end - --setmetatable(_M, {__call = function(tab, ...) return new(...) end}) -+zmq.poller = M -+return setmetatable(M, {__call = function(tab, ...) return M.new(...) end}) - -diff --git a/src/poller.nobj.lua b/src/poller.nobj.lua -index 66594d2..39b4938 100644 ---- a/src/poller.nobj.lua -+++ b/src/poller.nobj.lua -@@ -58,7 +58,24 @@ static int poller_resize_items(ZMQ_Poller *poller, int len) { - return len; - } - --static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { -+void poller_init(ZMQ_Poller *poller, int length) { -+ poller->items = (zmq_pollitem_t *)calloc(length, sizeof(zmq_pollitem_t)); -+ poller->next = -1; -+ poller->count = 0; -+ poller->len = length; -+ poller->free_list = -1; -+} -+ -+void poller_cleanup(ZMQ_Poller *poller) { -+ free(poller->items); -+ poller->items = NULL; -+ poller->next = -1; -+ poller->count = 0; -+ poller->len = 0; -+ poller->free_list = -1; -+} -+ -+int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { - zmq_pollitem_t *items; - int count; - int n; -@@ -73,7 +90,7 @@ static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { - return -1; - } - --static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { -+int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { - zmq_pollitem_t *items; - int count; - int n; -@@ -88,7 +105,7 @@ static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { - return -1; - } - --static void poller_remove_item(ZMQ_Poller *poller, int idx) { -+void poller_remove_item(ZMQ_Poller *poller, int idx) { - zmq_pollitem_t *items; - int free_list; - int count; -@@ -115,7 +132,7 @@ static void poller_remove_item(ZMQ_Poller *poller, int idx) { - items[idx].revents = 0; - } - --static int poller_get_free_item(ZMQ_Poller *poller) { -+int poller_get_free_item(ZMQ_Poller *poller) { - zmq_pollitem_t *curr; - zmq_pollitem_t *next; - int count; -@@ -191,14 +208,46 @@ static int poller_compact_items(ZMQ_Poller *poller) { - return count; - } - --static int poller_poll(ZMQ_Poller *poller, long timeout) { -+int poller_poll(ZMQ_Poller *poller, long timeout) { - int count; - /* remove free slots from items list. */ -- count = poller_compact_items(poller); -+ if(poller->free_list >= 0) { -+ count = poller_compact_items(poller); -+ } else { -+ count = poller->count; -+ } - /* poll for events. */ - return zmq_poll(poller->items, count, timeout); - } - -+int poller_next_revents(ZMQ_Poller *poller, int *revents) { -+ zmq_pollitem_t *items; -+ int count; -+ int idx; -+ int next; -+ -+ idx = poller->next; -+ /* do we need to poll for more events? */ -+ if(idx < 0) { -+ return idx; -+ } -+ items = poller->items; -+ count = poller->count; -+ /* find next item with pending events. */ -+ for(;idx < count; ++idx) { -+ /* did we find a pending event? */ -+ if(items[idx].revents != 0) { -+ *revents = items[idx].revents; -+ poller->next = idx+1; -+ return idx; -+ } -+ } -+ /* processed all pending events. */ -+ poller->next = -1; -+ *revents = 0; -+ return -1; -+} -+ - ]], - -- - -- Define ZMQ_Poller type & function API for FFI -@@ -212,36 +261,21 @@ typedef struct zmq_pollitem_t { - short revents; - } zmq_pollitem_t; - --int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); -+int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock); -+int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd); -+int poller_get_free_item(ZMQ_Poller *poller); -+int poller_poll(ZMQ_Poller *poller, long timeout); -+void poller_remove_item(ZMQ_Poller *poller, int idx); -+ - ]], - ffi_cdef(ZMQ_Poller_type), -- ffi_export_function "int" "poller_find_sock_item" "(ZMQ_Poller *poller, ZMQ_Socket *sock)", -- ffi_export_function "int" "poller_find_fd_item" "(ZMQ_Poller *poller, socket_t fd)", -- ffi_export_function "int" "poller_get_free_item" "(ZMQ_Poller *poller)", -- ffi_export_function "int" "poller_poll" "(ZMQ_Poller *poller, long timeout)", -- ffi_export_function "void" "poller_remove_item" "(ZMQ_Poller *poller, int idx)", - - constructor "new" { - var_in{ "unsigned int", "length", is_optional = true, default = 10 }, -- c_source[[ -- ZMQ_Poller poller; -- ${this} = &poller; -- ${this}->items = (zmq_pollitem_t *)calloc(${length}, sizeof(zmq_pollitem_t)); -- ${this}->next = -1; -- ${this}->count = 0; -- ${this}->len = ${length}; -- ${this}->free_list = -1; --]], -+ c_export_method_call "void" "poller_init" { "unsigned int", "length" }, - }, - destructor "close" { -- c_source[[ -- free(${this}->items); -- ${this}->items = NULL; -- ${this}->next = -1; -- ${this}->count = 0; -- ${this}->len = 0; -- ${this}->free_list = -1; --]], -+ c_export_method_call "void" "poller_cleanup" {}, - }, - method "add" { - var_in{ "", "sock" }, -@@ -266,6 +300,22 @@ int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); - item->fd = fd; - item->events = ${events}; - ]], -+ ffi_source[[ -+ local fd = 0 -+ local sock_type = type(${sock}) -+ if sock_type == 'cdata' then -+ sock = obj_type_ZMQ_Socket_check(${sock}) -+ elseif sock_type == 'number' then -+ fd = ${sock} -+ else -+ error("expected number or ZMQ_Socket") -+ end -+ ${idx} = Cmod.poller_get_free_item(${this}) -+ local item = ${this}.items[${idx}] -+ item.socket = sock -+ item.fd = fd -+ item.events = ${events} -+]], - }, - method "modify" { - var_in{ "", "sock" }, -@@ -302,123 +352,99 @@ int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); - poller_remove_item(${this}, ${idx}); - } - ]], -+ ffi_source[[ -+ local fd = 0 -+ local sock_type = type(${sock}) -+ if sock_type == 'cdata' then -+ sock = obj_type_ZMQ_Socket_check(${sock}) -+ -- find sock in items list. -+ ${idx} = Cmod.poller_find_sock_item(${this}, sock) -+ elseif sock_type == 'number' then -+ fd = ${sock} -+ -- find fd in items list. -+ ${idx} = Cmod.poller_find_fd_item(${this}, fd); -+ else -+ error("expected number or ZMQ_Socket") -+ end -+ if ${events} ~= 0 then -+ local item = ${this}.items[${idx}] -+ item.socket = sock -+ item.fd = fd -+ item.events = ${events} -+ else -+ Cmod.poller_remove_item(${this}, ${idx}) -+ end -+]], - }, - method "remove" { - var_in{ "", "sock" }, -+ var_out{ "int", "idx" }, - c_source "pre" [[ - ZMQ_Socket *sock; - socket_t fd; -- int idx; - ]], - c_source[[ - /* ZMQ_Socket or fd */ - if(lua_isuserdata(L, ${sock::idx})) { - sock = obj_type_ZMQ_Socket_check(L, ${sock::idx}); - /* find sock in items list. */ -- idx = poller_find_sock_item(${this}, sock); -+ ${idx} = poller_find_sock_item(${this}, sock); - } else if(lua_isnumber(L, ${sock::idx})) { - fd = lua_tonumber(L, ${sock::idx}); - /* find fd in items list. */ -- idx = poller_find_fd_item(${this}, fd); -+ ${idx} = poller_find_fd_item(${this}, fd); - } else { - return luaL_typerror(L, ${sock::idx}, "number or ZMQ_Socket"); - } - /* if sock/fd was found. */ -- if(idx >= 0) { -- poller_remove_item(${this}, idx); -+ if(${idx} >= 0) { -+ poller_remove_item(${this}, ${idx}); - } - ]], -+ ffi_source[[ -+ local fd = 0 -+ local sock_type = type(${sock}) -+ if sock_type == 'cdata' then -+ sock = obj_type_ZMQ_Socket_check(${sock}) -+ -- find sock in items list. -+ ${idx} = Cmod.poller_find_sock_item(${this}, sock) -+ elseif sock_type == 'number' then -+ fd = ${sock} -+ -- find fd in items list. -+ ${idx} = Cmod.poller_find_fd_item(${this}, fd); -+ else -+ error("expected number or ZMQ_Socket") -+ end -+ if ${idx} >= 0 then -+ Cmod.poller_remove_item(${this}, ${idx}) -+ end -+]], - }, - method "poll" { -- var_in{ "long", "timeout" }, -- var_out{ "ZMQ_Error", "err" }, -+ var_out{ "int", "count" }, -+ -- poll for events -+ c_export_method_call { "ZMQ_Error", "err>2" } "poller_poll" { "long", "timeout" }, - c_source[[ -- /* poll for events */ -- ${err} = poller_poll(${this}, ${timeout}); - if(${err} > 0) { - ${this}->next = 0; -+ ${count} = ${err}; - } else { - ${this}->next = -1; -+ ${count} = 0; - } - ]], - ffi_source[[ -- -- poll for events -- ${err} = poller_poll(${this}, ${timeout}) - if(${err} > 0) then - ${this}.next = 0 -+ ${count} = ${err} - else - ${this}.next = -1 -+ ${count} = 0 - end - ]], - }, -- method "next_revents" { -- var_out{ "", "sock" }, -- var_out{ "short", "revents" }, -- c_source "pre" [[ -- zmq_pollitem_t *items; -- int count; -- int idx; --]], -- c_source[[ -- ${revents} = -1; -- idx = ${this}->next; -- if(idx >= 0) { -- count = ${this}->count; -- items = ${this}->items; -- /* find next item with pending events. */ -- while(idx < count && items[idx].revents == 0) ++idx; -- /* did we find a pending event? */ -- if(idx < count) { -- /* push the event's sock/fd. */ -- if(items[idx].socket != NULL) { -- obj_type_ZMQ_Socket_push(L, items[idx].socket, 0); -- } else { -- lua_pushnumber(L, items[idx].fd); -- } -- ${revents} = items[idx].revents; -- /* is this the last event. */ -- ++idx; -- ${this}->next = (idx < count) ? idx : -1; -- } -- } -- if(${revents} < 0) { -- /* no more pending events. */ -- lua_pushnil(L); -- ${this}->next = -1; -- } --]], -- ffi_source[[ -- local sock -- local idx = ${this}.next -- if (idx < 0) then return nil, -1 end -- local count = ${this}.count -- -- find next item with pending events. -- while (idx < count and ${this}.items[idx].revents == 0) do -- idx = idx + 1 -- if (idx >= count) then -- idx = -1 -- break -- end -- end -- -- did we find a pending event? -- if(idx >= 0) then -- -- push the event's sock/fd. -- if(${this}.items[idx].socket ~= nil) then -- sock = obj_type_ZMQ_Socket_push(${this}.items[idx].socket, 0) -- else -- sock = tonumber(${this}.items[idx].fd) -- end -- ${revents} = ${this}.items[idx].revents -- -- is this the last event. -- idx = idx + 1 -- if (idx >= count) then -- idx = -1 -- end -- ${this}.next = idx -- return sock, ${revents} -- end -- ${this}.next = idx --]], -+ method "next_revents_idx" { -+ c_export_method_call { "int", "idx>1" } "poller_next_revents" { "int", "&revents>2" }, - }, - method "count" { - var_out{ "int", "count" }, -diff --git a/src/pre_generated-zmq.nobj.c b/src/pre_generated-zmq.nobj.c -index a6d739d..7442736 100644 ---- a/src/pre_generated-zmq.nobj.c -+++ b/src/pre_generated-zmq.nobj.c -@@ -10,16 +10,65 @@ - #include "lauxlib.h" - #include "lualib.h" - --#include --#include "zmq.h" --#include "zmq_utils.h" -+/* some Lua 5.0 compatibility support. */ -+#if !defined(lua_pushliteral) -+#define lua_pushliteral(L, s) lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1) -+#endif -+ -+#if !defined(LUA_VERSION_NUM) -+#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)n) -+#define luaL_Reg luaL_reg -+#endif -+ -+/* some Lua 5.1 compatibility support. */ -+#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) -+/* -+** Adapted from Lua 5.2.0 -+*/ -+static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { -+ luaL_checkstack(L, nup, "too many upvalues"); -+ for (; l->name != NULL; l++) { /* fill the table with given functions */ -+ int i; -+ for (i = 0; i < nup; i++) /* copy upvalues to the top */ -+ lua_pushvalue(L, -nup); -+ lua_pushstring(L, l->name); -+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ -+ lua_settable(L, -(nup + 3)); -+ } -+ lua_pop(L, nup); /* remove upvalues */ -+} -+ -+#define lua_load_no_mode(L, reader, data, source) \ -+ lua_load(L, reader, data, source) -+ -+#define lua_rawlen(L, idx) lua_objlen(L, idx) -+ -+#endif -+ -+#if LUA_VERSION_NUM == 502 -+ -+#define lua_load_no_mode(L, reader, data, source) \ -+ lua_load(L, reader, data, source, NULL) - -+static int luaL_typerror (lua_State *L, int narg, const char *tname) { -+ const char *msg = lua_pushfstring(L, "%s expected, got %s", -+ tname, luaL_typename(L, narg)); -+ return luaL_argerror(L, narg, msg); -+} -+ -+#endif - - #define REG_PACKAGE_IS_CONSTRUCTOR 0 -+#define REG_MODULES_AS_GLOBALS 1 - #define REG_OBJECTS_AS_GLOBALS 0 - #define OBJ_DATA_HIDDEN_METATABLE 1 --#define LUAJIT_FFI 1 - #define USE_FIELD_GET_SET_METHODS 0 -+#define LUAJIT_FFI 1 -+ -+ -+#include -+#include "zmq.h" -+#include "zmq_utils.h" - - - -@@ -41,6 +90,7 @@ - /* for MinGW32 compiler need to include */ - #ifdef __GNUC__ - #include -+#include - #else - - /* define some standard types missing on Windows. */ -@@ -57,7 +107,7 @@ typedef int bool; - #define true 1 - #endif - #ifndef false --#define false 1 -+#define false 0 - #endif - - #endif -@@ -98,19 +148,26 @@ typedef int bool; - #define assert_obj_type(type, obj) - #endif - --#ifndef obj_type_free -+void *nobj_realloc(void *ptr, size_t osize, size_t nsize); -+ -+void *nobj_realloc(void *ptr, size_t osize, size_t nsize) { -+ (void)osize; -+ if(0 == nsize) { -+ free(ptr); -+ return NULL; -+ } -+ return realloc(ptr, nsize); -+} -+ - #define obj_type_free(type, obj) do { \ - assert_obj_type(type, obj); \ -- free((obj)); \ -+ nobj_realloc((obj), sizeof(type), 0); \ - } while(0) --#endif - --#ifndef obj_type_new - #define obj_type_new(type, obj) do { \ - assert_obj_type(type, obj); \ -- (obj) = malloc(sizeof(type)); \ -+ (obj) = nobj_realloc(NULL, 0, sizeof(type)); \ - } while(0) --#endif - - typedef struct obj_type obj_type; - -@@ -120,6 +177,7 @@ typedef void (*dyn_caster_t)(void **obj, obj_type **type); - - #define OBJ_TYPE_FLAG_WEAK_REF (1<<0) - #define OBJ_TYPE_SIMPLE (1<<1) -+#define OBJ_TYPE_IMPORT (1<<2) - struct obj_type { - dyn_caster_t dcaster; /**< caster to support casting to sub-objects. */ - int32_t id; /**< type's id. */ -@@ -168,15 +226,28 @@ typedef struct obj_field { - uint32_t flags; /**< is_writable:1bit */ - } obj_field; - -+typedef enum { -+ REG_OBJECT, -+ REG_PACKAGE, -+ REG_META, -+} module_reg_type; -+ -+typedef struct reg_impl { -+ const char *if_name; -+ const void *impl; -+} reg_impl; -+ - typedef struct reg_sub_module { - obj_type *type; -- int is_package; -- const luaL_reg *pub_funcs; -- const luaL_reg *methods; -- const luaL_reg *metas; -+ module_reg_type req_type; -+ const luaL_Reg *pub_funcs; -+ const luaL_Reg *methods; -+ const luaL_Reg *metas; - const obj_base *bases; - const obj_field *fields; - const obj_const *constants; -+ const reg_impl *implements; -+ int bidirectional_consts; - } reg_sub_module; - - #define OBJ_UDATA_FLAG_OWN (1<<0) -@@ -188,15 +259,78 @@ typedef struct obj_udata { - } obj_udata; - - /* use static pointer as key to weak userdata table. */ --static char *obj_udata_weak_ref_key = "obj_udata_weak_ref_key"; -+static char obj_udata_weak_ref_key[] = "obj_udata_weak_ref_key"; -+ -+/* use static pointer as key to module's private table. */ -+static char obj_udata_private_key[] = "obj_udata_private_key"; - - #if LUAJIT_FFI -+typedef int (*ffi_export_func_t)(void); - typedef struct ffi_export_symbol { - const char *name; -- void *sym; -+ union { -+ void *data; -+ ffi_export_func_t func; -+ } sym; - } ffi_export_symbol; - #endif - -+/* detect zmq version */ -+#define VERSION_2_0 1 -+#define VERSION_2_1 0 -+#define VERSION_2_2 0 -+#define VERSION_3_0 0 -+#if defined(ZMQ_VERSION_MAJOR) -+# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 2) -+# undef VERSION_2_2 -+# define VERSION_2_2 1 -+# undef VERSION_2_1 -+# define VERSION_2_1 1 -+# endif -+# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 1) -+# undef VERSION_2_1 -+# define VERSION_2_1 1 -+# endif -+# if (ZMQ_VERSION_MAJOR == 3) -+# undef VERSION_2_0 -+# define VERSION_2_0 0 -+# undef VERSION_3_0 -+# define VERSION_3_0 1 -+# endif -+#endif -+ -+/* make sure ZMQ_DONTWAIT & ZMQ_NOBLOCK are both defined. */ -+#ifndef ZMQ_DONTWAIT -+# define ZMQ_DONTWAIT ZMQ_NOBLOCK -+#endif -+#ifndef ZMQ_NOBLOCK -+# define ZMQ_NOBLOCK ZMQ_DONTWAIT -+#endif -+ -+/* make sure DEALER/ROUTER & XREQ/XREP are all defined. */ -+#ifndef ZMQ_DEALER -+# define ZMQ_DEALER ZMQ_XREQ -+#endif -+#ifndef ZMQ_ROUTER -+# define ZMQ_ROUTER ZMQ_XREP -+#endif -+#ifndef ZMQ_XREQ -+# define ZMQ_XREQ ZMQ_DEALER -+#endif -+#ifndef ZMQ_XREP -+# define ZMQ_XREP ZMQ_ROUTER -+#endif -+ -+#if VERSION_2_0 -+# define ZMQ_POLL_MSEC 1000 // zmq_poll is usec -+#elif VERSION_3_0 -+# define ZMQ_POLL_MSEC 1 // zmq_poll is msec -+# ifndef ZMQ_HWM -+# define ZMQ_HWM 1 // backwards compatibility -+# endif -+#endif -+ -+ - - typedef int ZMQ_Error; - -@@ -204,29 +338,329 @@ static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err); - - - static obj_type obj_types[] = { --#define obj_type_id_zmq_msg_t 0 -+#define obj_type_id_ZErrors 0 -+#define obj_type_ZErrors (obj_types[obj_type_id_ZErrors]) -+ { NULL, 0, OBJ_TYPE_FLAG_WEAK_REF, "ZErrors" }, -+#define obj_type_id_zmq_msg_t 1 - #define obj_type_zmq_msg_t (obj_types[obj_type_id_zmq_msg_t]) -- { NULL, 0, OBJ_TYPE_SIMPLE, "zmq_msg_t" }, --#define obj_type_id_ZMQ_Socket 1 -+ { NULL, 1, OBJ_TYPE_SIMPLE, "zmq_msg_t" }, -+#define obj_type_id_ZMQ_Socket 2 - #define obj_type_ZMQ_Socket (obj_types[obj_type_id_ZMQ_Socket]) -- { NULL, 1, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Socket" }, --#define obj_type_id_ZMQ_Poller 2 -+ { NULL, 2, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Socket" }, -+#define obj_type_id_ZMQ_Poller 3 - #define obj_type_ZMQ_Poller (obj_types[obj_type_id_ZMQ_Poller]) -- { NULL, 2, OBJ_TYPE_SIMPLE, "ZMQ_Poller" }, --#define obj_type_id_ZMQ_Ctx 3 -+ { NULL, 3, OBJ_TYPE_SIMPLE, "ZMQ_Poller" }, -+#define obj_type_id_ZMQ_Ctx 4 - #define obj_type_ZMQ_Ctx (obj_types[obj_type_id_ZMQ_Ctx]) -- { NULL, 3, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Ctx" }, --#define obj_type_id_ZMQ_StopWatch 4 -+ { NULL, 4, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Ctx" }, -+#define obj_type_id_ZMQ_StopWatch 5 - #define obj_type_ZMQ_StopWatch (obj_types[obj_type_id_ZMQ_StopWatch]) -- { NULL, 4, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_StopWatch" }, -+ { NULL, 5, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_StopWatch" }, - {NULL, -1, 0, NULL}, - }; - - -+#if LUAJIT_FFI -+ -+/* nobj_ffi_support_enabled_hint should be set to 1 when FFI support is enabled in at-least one -+ * instance of a LuaJIT state. It should never be set back to 0. */ -+static int nobj_ffi_support_enabled_hint = 0; -+static const char nobj_ffi_support_key[] = "LuaNativeObject_FFI_SUPPORT"; -+static const char nobj_check_ffi_support_code[] = -+"local stat, ffi=pcall(require,\"ffi\")\n" /* try loading LuaJIT`s FFI module. */ -+"if not stat then return false end\n" -+"return true\n"; -+ -+static int nobj_check_ffi_support(lua_State *L) { -+ int rc; -+ int err; -+ -+ /* check if ffi test has already been done. */ -+ lua_pushstring(L, nobj_ffi_support_key); -+ lua_rawget(L, LUA_REGISTRYINDEX); -+ if(!lua_isnil(L, -1)) { -+ rc = lua_toboolean(L, -1); -+ lua_pop(L, 1); -+ /* use results of previous check. */ -+ goto finished; -+ } -+ lua_pop(L, 1); /* pop nil. */ -+ -+ err = luaL_loadbuffer(L, nobj_check_ffi_support_code, -+ sizeof(nobj_check_ffi_support_code) - 1, nobj_ffi_support_key); -+ if(0 == err) { -+ err = lua_pcall(L, 0, 1, 0); -+ } -+ if(err) { -+ const char *msg = ""; -+ if(lua_isstring(L, -1)) { -+ msg = lua_tostring(L, -1); -+ } -+ printf("Error when checking for FFI-support: %s\n", msg); -+ lua_pop(L, 1); /* pop error message. */ -+ return 0; -+ } -+ /* check results of test. */ -+ rc = lua_toboolean(L, -1); -+ lua_pop(L, 1); /* pop results. */ -+ /* cache results. */ -+ lua_pushstring(L, nobj_ffi_support_key); -+ lua_pushboolean(L, rc); -+ lua_rawset(L, LUA_REGISTRYINDEX); -+ -+finished: -+ /* turn-on hint that there is FFI code enabled. */ -+ if(rc) { -+ nobj_ffi_support_enabled_hint = 1; -+ } -+ -+ return rc; -+} -+ -+typedef struct { -+ const char **ffi_init_code; -+ int offset; -+} nobj_reader_state; -+ -+static const char *nobj_lua_Reader(lua_State *L, void *data, size_t *size) { -+ nobj_reader_state *state = (nobj_reader_state *)data; -+ const char *ptr; -+ -+ (void)L; -+ ptr = state->ffi_init_code[state->offset]; -+ if(ptr != NULL) { -+ *size = strlen(ptr); -+ state->offset++; -+ } else { -+ *size = 0; -+ } -+ return ptr; -+} -+ -+static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, -+ const char *ffi_init_code[], const ffi_export_symbol *ffi_exports, int priv_table) -+{ -+ nobj_reader_state state = { ffi_init_code, 0 }; -+ int err; -+ -+ /* export symbols to priv_table. */ -+ while(ffi_exports->name != NULL) { -+ lua_pushstring(L, ffi_exports->name); -+ lua_pushlightuserdata(L, ffi_exports->sym.data); -+ lua_settable(L, priv_table); -+ ffi_exports++; -+ } -+ err = lua_load_no_mode(L, nobj_lua_Reader, &state, ffi_mod_name); -+ if(0 == err) { -+ lua_pushvalue(L, -2); /* dup C module's table. */ -+ lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ -+ lua_remove(L, priv_table); -+ lua_pushvalue(L, LUA_REGISTRYINDEX); -+ err = lua_pcall(L, 3, 0, 0); -+ } -+ if(err) { -+ const char *msg = ""; -+ if(lua_isstring(L, -1)) { -+ msg = lua_tostring(L, -1); -+ } -+ printf("Failed to install FFI-based bindings: %s\n", msg); -+ lua_pop(L, 1); /* pop error message. */ -+ } -+ return err; -+} -+#endif -+ -+ -+typedef struct { -+ void *impl; -+ void *obj; -+} obj_implement; -+ -+static FUNC_UNUSED void *obj_implement_luaoptional(lua_State *L, int _index, void **impl, char *if_name) { -+ void *ud; -+ if(lua_isnoneornil(L, _index)) { -+ return NULL; -+ } -+ /* get the implements table for this interface. */ -+ lua_pushlightuserdata(L, if_name); -+ lua_rawget(L, LUA_REGISTRYINDEX); -+ -+ /* get pointer to userdata value & check if it is a userdata value. */ -+ ud = (obj_implement *)lua_touserdata(L, _index); -+ if(ud != NULL) { -+ /* get the userdata's metatable */ -+ if(lua_getmetatable(L, _index)) { -+ /* lookup metatable in interface table for this object's implementation of the interface. */ -+ lua_gettable(L, -2); -+ } else { -+ /* no metatable. */ -+ goto no_interface; -+ } -+#if LUAJIT_FFI -+ } else if(nobj_ffi_support_enabled_hint) { /* handle cdata. */ -+ /* get cdata interface check function from interface table. */ -+ lua_getfield(L, -1, "cdata"); -+ if(lua_isfunction(L, -1)) { -+ /* pass cdata to function, return value should be an implmentation. */ -+ lua_pushvalue(L, _index); -+ lua_call(L, 1, 1); -+ /* get pointer to cdata. */ -+ ud = (void *)lua_topointer(L, _index); -+ } else { -+ lua_pop(L, 1); /* pop non-function. */ -+ goto no_interface; -+ } -+#endif -+ } else { -+ goto no_interface; -+ } -+ -+ if(!lua_isnil(L, -1)) { -+ *impl = lua_touserdata(L, -1); -+ lua_pop(L, 2); /* pop interface table & implementation. */ -+ /* object implements interface. */ -+ return ud; -+ } else { -+ lua_pop(L, 1); /* pop nil. */ -+ } -+no_interface: -+ lua_pop(L, 1); /* pop interface table. */ -+ return NULL; -+} -+ -+static FUNC_UNUSED void *obj_implement_luacheck(lua_State *L, int _index, void **impl, char *type) { -+ void *ud = obj_implement_luaoptional(L, _index, impl, type); -+ if(ud == NULL) { -+#define ERROR_BUFFER_SIZE 256 -+ char buf[ERROR_BUFFER_SIZE]; -+ snprintf(buf, ERROR_BUFFER_SIZE-1,"Expected object with %s interface", type); -+ /* value doesn't implement this interface. */ -+ luaL_argerror(L, _index, buf); -+ } -+ return ud; -+} -+ -+/* use static pointer as key to interfaces table. (version 1.0) */ -+static char obj_interfaces_table_key[] = "obj_interfaces<1.0>_table_key"; -+ -+static void obj_get_global_interfaces_table(lua_State *L) { -+ /* get global interfaces table. */ -+ lua_getfield(L, LUA_REGISTRYINDEX, obj_interfaces_table_key); -+ if(lua_isnil(L, -1)) { -+ /* Need to create global interfaces table. */ -+ lua_pop(L, 1); /* pop nil */ -+ lua_createtable(L, 0, 4); /* 0 size array part, small hash part. */ -+ lua_pushvalue(L, -1); /* dup table. */ -+ /* store interfaces table in Lua registery. */ -+ lua_setfield(L, LUA_REGISTRYINDEX, obj_interfaces_table_key); -+ } -+} -+ -+static void obj_get_interface(lua_State *L, const char *name, int global_if_tab) { -+ /* get a interface's implementation table */ -+ lua_getfield(L, global_if_tab, name); -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil */ -+ /* new interface. (i.e. no object implement it yet.) -+ * -+ * create an empty table for this interface that will be used when an -+ * implementation is registered for this interface. -+ */ -+ lua_createtable(L, 0, 2); /* 0 size array part, small hash part. */ -+ lua_pushvalue(L, -1); /* dup table. */ -+ lua_setfield(L, global_if_tab, name); /* store interface in global interfaces table. */ -+ } -+} -+ -+static int obj_get_userdata_interface(lua_State *L) { -+ /* get the userdata's metatable */ -+ if(lua_getmetatable(L, 2)) { -+ /* lookup metatable in interface table for the userdata's implementation of the interface. */ -+ lua_gettable(L, 1); -+ if(!lua_isnil(L, -1)) { -+ /* return the implementation. */ -+ return 1; -+ } -+ } -+ /* no metatable or no implementation. */ -+ return 0; -+} -+ -+static void obj_interface_register(lua_State *L, char *name, int global_if_tab) { -+ /* get the table of implementations for this interface. */ -+ obj_get_interface(L, name, global_if_tab); -+ -+ /* check for 'userdata' function. */ -+ lua_getfield(L, -1, "userdata"); -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. */ -+ /* add C function for getting a userdata's implementation. */ -+ lua_pushcfunction(L, obj_get_userdata_interface); -+ lua_setfield(L, -2, "userdata"); -+ } else { -+ /* already have function. */ -+ lua_pop(L, 1); /* pop C function. */ -+ } -+ /* we are going to use a lightuserdata pointer for fast lookup of the interface's impl. table. */ -+ lua_pushlightuserdata(L, name); -+ lua_insert(L, -2); -+ lua_settable(L, LUA_REGISTRYINDEX); -+} -+ -+static void obj_register_interfaces(lua_State *L, char *interfaces[]) { -+ int i; -+ int if_tab; -+ /* get global interfaces table. */ -+ obj_get_global_interfaces_table(L); -+ if_tab = lua_gettop(L); -+ -+ for(i = 0; interfaces[i] != NULL ; i++) { -+ obj_interface_register(L, interfaces[i], if_tab); -+ } -+ lua_pop(L, 1); /* pop global interfaces table. */ -+} -+ -+static void obj_type_register_implement(lua_State *L, const reg_impl *impl, int global_if_tab, int mt_tab) { -+ /* get the table of implementations for this interface. */ -+ obj_get_interface(L, impl->if_name, global_if_tab); -+ -+ /* register object's implement in the interface table. */ -+ lua_pushvalue(L, mt_tab); -+ lua_pushlightuserdata(L, (void *)impl->impl); -+ lua_settable(L, -3); -+ -+ lua_pop(L, 1); /* pop inteface table. */ -+} -+ -+static void obj_type_register_implements(lua_State *L, const reg_impl *impls) { -+ int if_tab; -+ int mt_tab; -+ /* get absolute position of object's metatable. */ -+ mt_tab = lua_gettop(L); -+ /* get global interfaces table. */ -+ obj_get_global_interfaces_table(L); -+ if_tab = lua_gettop(L); -+ -+ for(; impls->if_name != NULL ; impls++) { -+ obj_type_register_implement(L, impls, if_tab, mt_tab); -+ } -+ lua_pop(L, 1); /* pop global interfaces table. */ -+} -+ - #ifndef REG_PACKAGE_IS_CONSTRUCTOR - #define REG_PACKAGE_IS_CONSTRUCTOR 1 - #endif - -+#ifndef REG_MODULES_AS_GLOBALS -+#define REG_MODULES_AS_GLOBALS 0 -+#endif -+ -+/* For Lua 5.2 don't register modules as globals. */ -+#if LUA_VERSION_NUM == 502 -+#undef REG_MODULES_AS_GLOBALS -+#define REG_MODULES_AS_GLOBALS 0 -+#endif -+ - #ifndef REG_OBJECTS_AS_GLOBALS - #define REG_OBJECTS_AS_GLOBALS 0 - #endif -@@ -235,6 +669,48 @@ static obj_type obj_types[] = { - #define OBJ_DATA_HIDDEN_METATABLE 1 - #endif - -+static FUNC_UNUSED int obj_import_external_type(lua_State *L, obj_type *type) { -+ /* find the external type's metatable using it's name. */ -+ lua_pushstring(L, type->name); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* external type's metatable. */ -+ if(!lua_isnil(L, -1)) { -+ /* found it. Now we will map our 'type' pointer to the metatable. */ -+ /* REGISTERY[lightuserdata] = REGISTERY[type->name] */ -+ lua_pushlightuserdata(L, type); /* use our 'type' pointer as lookup key. */ -+ lua_pushvalue(L, -2); /* dup. type's metatable. */ -+ lua_rawset(L, LUA_REGISTRYINDEX); /* save external type's metatable. */ -+ /* NOTE: top of Lua stack still has the type's metatable. */ -+ return 1; -+ } else { -+ lua_pop(L, 1); /* pop nil. */ -+ } -+ return 0; -+} -+ -+static FUNC_UNUSED int obj_import_external_ffi_type(lua_State *L, obj_type *type) { -+ /* find the external type's metatable using it's name. */ -+ lua_pushstring(L, type->name); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* external type's metatable. */ -+ if(!lua_isnil(L, -1)) { -+ /* found it. Now we will map our 'type' pointer to the C check function. */ -+ /* _priv_table[lightuserdata] = REGISTERY[type->name].c_check */ -+ lua_getfield(L, -1, "c_check"); -+ lua_remove(L, -2); /* remove metatable. */ -+ if(lua_isfunction(L, -1)) { -+ lua_pushlightuserdata(L, type); /* use our 'type' pointer as lookup key. */ -+ lua_pushvalue(L, -2); /* dup. check function */ -+ lua_rawset(L, -4); /* save check function to module's private table. */ -+ /* NOTE: top of Lua stack still has the type's C check function. */ -+ return 1; -+ } else { -+ lua_pop(L, 1); /* pop non function value. */ -+ } -+ } else { -+ lua_pop(L, 1); /* pop nil. */ -+ } -+ return 0; -+} -+ - static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) { - obj_udata *ud; - size_t len; -@@ -245,7 +721,7 @@ static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) { - luaL_typerror(L, _index, "userdata"); /* is not a userdata value. */ - } - /* verify userdata size. */ -- len = lua_objlen(L, _index); -+ len = lua_rawlen(L, _index); - if(len != sizeof(obj_udata)) { - /* This shouldn't be possible */ - luaL_error(L, "invalid userdata size: size=%d, expected=%d", len, sizeof(obj_udata)); -@@ -258,10 +734,23 @@ static FUNC_UNUSED int obj_udata_is_compatible(lua_State *L, obj_udata *ud, void - obj_type *ud_type; - lua_pushlightuserdata(L, type); - lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+recheck_metatable: - if(lua_rawequal(L, -1, -2)) { - *obj = ud->obj; - /* same type no casting needed. */ - return 1; -+ } else if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. */ -+ if((type->flags & OBJ_TYPE_IMPORT) == 0) { -+ /* can't resolve internal type. */ -+ luaL_error(L, "Unknown object type(id=%d, name=%s)", type->id, type->name); -+ } -+ /* try to import external type. */ -+ if(obj_import_external_type(L, type)) { -+ /* imported type, re-try metatable check. */ -+ goto recheck_metatable; -+ } -+ /* External type not yet available, so the object can't be compatible. */ - } else { - /* Different types see if we can cast to the required type. */ - lua_rawgeti(L, -2, type->id); -@@ -314,6 +803,39 @@ static FUNC_UNUSED obj_udata *obj_udata_luacheck_internal(lua_State *L, int _ind - return ud; - } - } -+ } else if(!lua_isnoneornil(L, _index)) { -+ /* handle cdata. */ -+ /* get private table. */ -+ lua_pushlightuserdata(L, obj_udata_private_key); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ -+ /* get cdata type check function from private table. */ -+ lua_pushlightuserdata(L, type); -+ lua_rawget(L, -2); -+ -+ /* check for function. */ -+ if(!lua_isnil(L, -1)) { -+got_check_func: -+ /* pass cdata value to type checking function. */ -+ lua_pushvalue(L, _index); -+ lua_call(L, 1, 1); -+ if(!lua_isnil(L, -1)) { -+ /* valid type get pointer from cdata. */ -+ lua_pop(L, 2); -+ *obj = *(void **)lua_topointer(L, _index); -+ return ud; -+ } -+ lua_pop(L, 2); -+ } else { -+ lua_pop(L, 1); /* pop nil. */ -+ if(type->flags & OBJ_TYPE_IMPORT) { -+ /* try to import external ffi type. */ -+ if(obj_import_external_ffi_type(L, type)) { -+ /* imported type. */ -+ goto got_check_func; -+ } -+ /* External type not yet available, so the object can't be compatible. */ -+ } -+ } - } - if(not_delete) { - luaL_typerror(L, _index, type->name); /* is not a userdata value. */ -@@ -327,6 +849,15 @@ static FUNC_UNUSED void *obj_udata_luacheck(lua_State *L, int _index, obj_type * - return obj; - } - -+static FUNC_UNUSED void *obj_udata_luaoptional(lua_State *L, int _index, obj_type *type) { -+ void *obj = NULL; -+ if(lua_isnoneornil(L, _index)) { -+ return obj; -+ } -+ obj_udata_luacheck_internal(L, _index, &(obj), type, 1); -+ return obj; -+} -+ - static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { - void *obj; - obj_udata *ud = obj_udata_luacheck_internal(L, _index, &(obj), type, 0); -@@ -335,6 +866,9 @@ static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type - /* null userdata. */ - ud->obj = NULL; - ud->flags = 0; -+ /* clear the metatable in invalidate userdata. */ -+ lua_pushnil(L); -+ lua_setmetatable(L, _index); - return obj; - } - -@@ -345,6 +879,17 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ - lua_pushnil(L); - return; - } -+#if LUAJIT_FFI -+ lua_pushlightuserdata(L, type); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { -+ /* call special FFI "void *" to FFI object convertion function. */ -+ lua_pushlightuserdata(L, obj); -+ lua_pushinteger(L, flags); -+ lua_call(L, 2, 1); -+ return; -+ } -+#endif - /* check for type caster. */ - if(type->dcaster) { - (type->dcaster)(&obj, &type); -@@ -354,8 +899,12 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ - ud->obj = obj; - ud->flags = flags; - /* get obj_type metatable. */ -+#if LUAJIT_FFI -+ lua_insert(L, -2); /* move userdata below metatable. */ -+#else - lua_pushlightuserdata(L, type); - lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+#endif - lua_setmetatable(L, -2); - } - -@@ -367,6 +916,9 @@ static FUNC_UNUSED void *obj_udata_luadelete_weak(lua_State *L, int _index, obj_ - /* null userdata. */ - ud->obj = NULL; - ud->flags = 0; -+ /* clear the metatable in invalidate userdata. */ -+ lua_pushnil(L); -+ lua_setmetatable(L, _index); - /* get objects weak table. */ - lua_pushlightuserdata(L, obj_udata_weak_ref_key); - lua_rawget(L, LUA_REGISTRYINDEX); /* weak ref table. */ -@@ -401,6 +953,18 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type - } - lua_pop(L, 1); /* pop nil. */ - -+#if LUAJIT_FFI -+ lua_pushlightuserdata(L, type); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { -+ lua_remove(L, -2); -+ /* call special FFI "void *" to FFI object convertion function. */ -+ lua_pushlightuserdata(L, obj); -+ lua_pushinteger(L, flags); -+ lua_call(L, 2, 1); -+ return; -+ } -+#endif - /* create new userdata. */ - ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata)); - -@@ -408,8 +972,12 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type - ud->obj = obj; - ud->flags = flags; - /* get obj_type metatable. */ -+#if LUAJIT_FFI -+ lua_insert(L, -2); /* move userdata below metatable. */ -+#else - lua_pushlightuserdata(L, type); - lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+#endif - lua_setmetatable(L, -2); - - /* add weak reference to object. */ -@@ -468,9 +1036,53 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob - if(lua_getmetatable(L, _index)) { - lua_pushlightuserdata(L, type); - lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+recheck_metatable: - if(lua_rawequal(L, -1, -2)) { - lua_pop(L, 2); /* pop both metatables. */ - return ud; -+ } else if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. */ -+ if((type->flags & OBJ_TYPE_IMPORT) == 0) { -+ /* can't resolve internal type. */ -+ luaL_error(L, "Unknown object type(id=%d, name=%s)", type->id, type->name); -+ } -+ /* try to import external type. */ -+ if(obj_import_external_type(L, type)) { -+ /* imported type, re-try metatable check. */ -+ goto recheck_metatable; -+ } -+ /* External type not yet available, so the object can't be compatible. */ -+ return 0; -+ } -+ } -+ } else if(!lua_isnoneornil(L, _index)) { -+ /* handle cdata. */ -+ /* get private table. */ -+ lua_pushlightuserdata(L, obj_udata_private_key); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ -+ /* get cdata type check function from private table. */ -+ lua_pushlightuserdata(L, type); -+ lua_rawget(L, -2); -+ -+ /* check for function. */ -+ if(!lua_isnil(L, -1)) { -+got_check_func: -+ /* pass cdata value to type checking function. */ -+ lua_pushvalue(L, _index); -+ lua_call(L, 1, 1); -+ if(!lua_isnil(L, -1)) { -+ /* valid type get pointer from cdata. */ -+ lua_pop(L, 2); -+ return (void *)lua_topointer(L, _index); -+ } -+ } else { -+ if(type->flags & OBJ_TYPE_IMPORT) { -+ /* try to import external ffi type. */ -+ if(obj_import_external_ffi_type(L, type)) { -+ /* imported type. */ -+ goto got_check_func; -+ } -+ /* External type not yet available, so the object can't be compatible. */ - } - } - } -@@ -478,10 +1090,16 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob - return NULL; - } - --static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { -+static FUNC_UNUSED void * obj_simple_udata_luaoptional(lua_State *L, int _index, obj_type *type) { -+ if(lua_isnoneornil(L, _index)) { -+ return NULL; -+ } -+ return obj_simple_udata_luacheck(L, _index, type); -+} -+ -+static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type) { - void *obj; - obj = obj_simple_udata_luacheck(L, _index, type); -- *flags = OBJ_UDATA_FLAG_OWN; - /* clear the metatable to invalidate userdata. */ - lua_pushnil(L); - lua_setmetatable(L, _index); -@@ -490,12 +1108,27 @@ static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, o - - static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type) - { -+ void *ud; -+#if LUAJIT_FFI -+ lua_pushlightuserdata(L, type); -+ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { -+ /* call special FFI "void *" to FFI object convertion function. */ -+ lua_pushlightuserdata(L, obj); -+ lua_call(L, 1, 1); -+ return obj; -+ } -+#endif - /* create new userdata. */ -- void *ud = lua_newuserdata(L, size); -+ ud = lua_newuserdata(L, size); - memcpy(ud, obj, size); - /* get obj_type metatable. */ -+#if LUAJIT_FFI -+ lua_insert(L, -2); /* move userdata below metatable. */ -+#else - lua_pushlightuserdata(L, type); - lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ -+#endif - lua_setmetatable(L, -2); - - return ud; -@@ -504,9 +1137,9 @@ static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int s - /* default simple object equal method. */ - static FUNC_UNUSED int obj_simple_udata_default_equal(lua_State *L) { - void *ud1 = obj_simple_udata_toobj(L, 1); -- size_t len1 = lua_objlen(L, 1); -+ size_t len1 = lua_rawlen(L, 1); - void *ud2 = obj_simple_udata_toobj(L, 2); -- size_t len2 = lua_objlen(L, 2); -+ size_t len2 = lua_rawlen(L, 2); - - if(len1 == len2) { - lua_pushboolean(L, (memcmp(ud1, ud2, len1) == 0)); -@@ -544,7 +1177,8 @@ static int obj_constructor_call_wrapper(lua_State *L) { - return lua_gettop(L); - } - --static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx) { -+static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx, -+ int bidirectional) { - /* register constants. */ - while(constants->name != NULL) { - lua_pushstring(L, constants->name); -@@ -562,40 +1196,84 @@ static void obj_type_register_constants(lua_State *L, const obj_const *constants - lua_pushnil(L); - break; - } -+ /* map values back to keys. */ -+ if(bidirectional) { -+ /* check if value already exists. */ -+ lua_pushvalue(L, -1); -+ lua_rawget(L, tab_idx - 3); -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); -+ /* add value->key mapping. */ -+ lua_pushvalue(L, -1); -+ lua_pushvalue(L, -3); -+ lua_rawset(L, tab_idx - 4); -+ } else { -+ /* value already exists. */ -+ lua_pop(L, 1); -+ } -+ } - lua_rawset(L, tab_idx - 2); - constants++; - } - } - - static void obj_type_register_package(lua_State *L, const reg_sub_module *type_reg) { -- const luaL_reg *reg_list = type_reg->pub_funcs; -+ const luaL_Reg *reg_list = type_reg->pub_funcs; - - /* create public functions table. */ - if(reg_list != NULL && reg_list[0].name != NULL) { - /* register functions */ -- luaL_register(L, NULL, reg_list); -+ luaL_setfuncs(L, reg_list, 0); - } - -- obj_type_register_constants(L, type_reg->constants, -1); -+ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); - - lua_pop(L, 1); /* drop package table */ - } - -+static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) { -+ const luaL_Reg *reg_list; -+ -+ /* create public functions table. */ -+ reg_list = type_reg->pub_funcs; -+ if(reg_list != NULL && reg_list[0].name != NULL) { -+ /* register functions */ -+ luaL_setfuncs(L, reg_list, 0); -+ } -+ -+ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); -+ -+ /* register methods. */ -+ luaL_setfuncs(L, type_reg->methods, 0); -+ -+ /* create metatable table. */ -+ lua_newtable(L); -+ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ -+ /* setmetatable on meta-object. */ -+ lua_setmetatable(L, -2); -+ -+ lua_pop(L, 1); /* drop meta-object */ -+} -+ - static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) { -- const luaL_reg *reg_list; -+ const luaL_Reg *reg_list; - obj_type *type = type_reg->type; - const obj_base *base = type_reg->bases; - -- if(type_reg->is_package == 1) { -+ if(type_reg->req_type == REG_PACKAGE) { - obj_type_register_package(L, type_reg); - return; - } -+ if(type_reg->req_type == REG_META) { -+ obj_type_register_meta(L, type_reg); -+ return; -+ } - - /* create public functions table. */ - reg_list = type_reg->pub_funcs; - if(reg_list != NULL && reg_list[0].name != NULL) { - /* register "constructors" as to object's public API */ -- luaL_register(L, NULL, reg_list); /* fill public API table. */ -+ luaL_setfuncs(L, reg_list, 0); /* fill public API table. */ - - /* make public API table callable as the default constructor. */ - lua_newtable(L); /* create metatable */ -@@ -625,7 +1303,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int - #endif - } - -- luaL_register(L, NULL, type_reg->methods); /* fill methods table. */ -+ luaL_setfuncs(L, type_reg->methods, 0); /* fill methods table. */ - - luaL_newmetatable(L, type->name); /* create metatable */ - lua_pushliteral(L, ".name"); -@@ -638,16 +1316,12 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int - lua_pushvalue(L, -2); /* dup metatable. */ - lua_rawset(L, LUA_REGISTRYINDEX); /* REGISTRY[type] = metatable */ - --#if LUAJIT_FFI - /* add metatable to 'priv_table' */ - lua_pushstring(L, type->name); - lua_pushvalue(L, -2); /* dup metatable. */ - lua_rawset(L, priv_table); /* priv_table[""] = metatable */ --#else -- (void)priv_table; --#endif - -- luaL_register(L, NULL, type_reg->metas); /* fill metatable */ -+ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ - - /* add obj_bases to metatable. */ - while(base->id >= 0) { -@@ -656,7 +1330,9 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int - base++; - } - -- obj_type_register_constants(L, type_reg->constants, -2); -+ obj_type_register_constants(L, type_reg->constants, -2, type_reg->bidirectional_consts); -+ -+ obj_type_register_implements(L, type_reg->implements); - - lua_pushliteral(L, "__index"); - lua_pushvalue(L, -3); /* dup methods table */ -@@ -676,62 +1352,193 @@ static FUNC_UNUSED int lua_checktype_ref(lua_State *L, int _index, int _type) { - return luaL_ref(L, LUA_REGISTRYINDEX); - } - --#if LUAJIT_FFI --static int nobj_udata_new_ffi(lua_State *L) { -- size_t size = luaL_checkinteger(L, 1); -- void *ud; -- luaL_checktype(L, 2, LUA_TTABLE); -- lua_settop(L, 2); -- /* create userdata. */ -- ud = lua_newuserdata(L, size); -- lua_replace(L, 1); -- /* set userdata's metatable. */ -- lua_setmetatable(L, 1); -- return 1; --} -+/* use static pointer as key to weak callback_state table. */ -+static char obj_callback_state_weak_ref_key[] = "obj_callback_state_weak_ref_key"; - --static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, -- const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table) --{ -- int err; -+static FUNC_UNUSED void *nobj_get_callback_state(lua_State *L, int owner_idx, int size) { -+ void *cb_state; - -- /* export symbols to priv_table. */ -- while(ffi_exports->name != NULL) { -- lua_pushstring(L, ffi_exports->name); -- lua_pushlightuserdata(L, ffi_exports->sym); -- lua_settable(L, priv_table); -- ffi_exports++; -+ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ -+ lua_rawget(L, LUA_REGISTRYINDEX); /* check if weak table exists already. */ -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. */ -+ /* create weak table for callback_state */ -+ lua_newtable(L); /* weak table. */ -+ lua_newtable(L); /* metatable for weak table. */ -+ lua_pushliteral(L, "__mode"); -+ lua_pushliteral(L, "k"); -+ lua_rawset(L, -3); /* metatable.__mode = 'k' weak keys. */ -+ lua_setmetatable(L, -2); /* add metatable to weak table. */ -+ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ -+ lua_pushvalue(L, -2); /* dup weak table. */ -+ lua_rawset(L, LUA_REGISTRYINDEX); /* add weak table to registry. */ - } -- err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name); -- if(0 == err) { -- lua_pushvalue(L, -2); /* dup C module's table. */ -- lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ -- lua_remove(L, priv_table); -- lua_pushcfunction(L, nobj_udata_new_ffi); -- err = lua_pcall(L, 3, 0, 0); -+ -+ /* check weak table for callback_state. */ -+ lua_pushvalue(L, owner_idx); /* dup. owner as lookup key. */ -+ lua_rawget(L, -2); -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. */ -+ lua_pushvalue(L, owner_idx); /* dup. owner as lookup key. */ -+ /* create new callback state. */ -+ cb_state = lua_newuserdata(L, size); -+ lua_rawset(L, -3); -+ lua_pop(L, 1); /* pop */ -+ } else { -+ /* got existing callback state. */ -+ cb_state = lua_touserdata(L, -1); -+ lua_pop(L, 2); /* pop , */ - } -- if(err) { -- const char *msg = ""; -- if(lua_isstring(L, -1)) { -- msg = lua_tostring(L, -1); -- } -- printf("Failed to install FFI-based bindings: %s\n", msg); -- lua_pop(L, 1); /* pop error message. */ -+ -+ return cb_state; -+} -+ -+static FUNC_UNUSED void *nobj_delete_callback_state(lua_State *L, int owner_idx) { -+ void *cb_state = NULL; -+ -+ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ -+ lua_rawget(L, LUA_REGISTRYINDEX); /* check if weak table exists already. */ -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop nil. no weak table, so there is no callback state. */ -+ return NULL; - } -- return err; -+ /* get callback state. */ -+ lua_pushvalue(L, owner_idx); /* dup. owner */ -+ lua_rawget(L, -2); -+ if(lua_isnil(L, -1)) { -+ lua_pop(L, 2); /* pop , nil. No callback state for the owner. */ -+ } else { -+ cb_state = lua_touserdata(L, -1); -+ lua_pop(L, 1); /* pop */ -+ /* remove callback state. */ -+ lua_pushvalue(L, owner_idx); /* dup. owner */ -+ lua_pushnil(L); -+ lua_rawset(L, -3); -+ lua_pop(L, 1); /* pop */ -+ } -+ -+ return cb_state; - } --#endif -+ -+ -+ -+ -+ -+typedef struct MutableBuffer_if { -+ uint8_t * (* const data)(void *this_v); -+ size_t (* const get_size)(void *this_v); -+} MutableBufferIF; -+ -+/* a per-module unique pointer for fast lookup of an interface's implementation table. */ -+static char obj_interface_MutableBufferIF[] = "MutableBufferIF"; -+ -+#define MutableBufferIF_VAR(var_name) \ -+ MutableBufferIF *var_name ## _if; \ -+ void *var_name; -+ -+#define MutableBufferIF_LUA_OPTIONAL(L, _index, var_name) \ -+ var_name = obj_implement_luaoptional(L, _index, (void **)&(var_name ## _if), \ -+ obj_interface_MutableBufferIF) -+ -+#define MutableBufferIF_LUA_CHECK(L, _index, var_name) \ -+ var_name = obj_implement_luacheck(L, _index, (void **)&(var_name ## _if), \ -+ obj_interface_MutableBufferIF) -+ -+ -+ -+ -+ -+ -+typedef struct Buffer_if { -+ const uint8_t * (* const const_data)(void *this_v); -+ size_t (* const get_size)(void *this_v); -+} BufferIF; -+ -+/* a per-module unique pointer for fast lookup of an interface's implementation table. */ -+static char obj_interface_BufferIF[] = "BufferIF"; -+ -+#define BufferIF_VAR(var_name) \ -+ BufferIF *var_name ## _if; \ -+ void *var_name; -+ -+#define BufferIF_LUA_OPTIONAL(L, _index, var_name) \ -+ var_name = obj_implement_luaoptional(L, _index, (void **)&(var_name ## _if), \ -+ obj_interface_BufferIF) -+ -+#define BufferIF_LUA_CHECK(L, _index, var_name) \ -+ var_name = obj_implement_luacheck(L, _index, (void **)&(var_name ## _if), \ -+ obj_interface_BufferIF) -+ -+ -+ -+ -+static char *obj_interfaces[] = { -+ obj_interface_MutableBufferIF, -+ obj_interface_BufferIF, -+ NULL, -+}; -+ -+/** -+ * zmq_msg_t implements Buffer interface -+ */ -+/** -+ * Buffer interface method const_data -+ */ -+static const uint8_t * zmq_msg_t_Buffer_const_data(void *this_v) { -+ zmq_msg_t * this_p = this_v; -+ return zmq_msg_data(this_p); -+} -+/** -+ * Buffer interface method get_size -+ */ -+static size_t zmq_msg_t_Buffer_get_size(void *this_v) { -+ zmq_msg_t * this_p = this_v; -+ return zmq_msg_size(this_p); -+} -+ -+static const BufferIF zmq_msg_t_Buffer = { -+ zmq_msg_t_Buffer_const_data, -+ zmq_msg_t_Buffer_get_size -+}; -+ -+/** -+ * zmq_msg_t implements MutableBuffer interface -+ */ -+/** -+ * MutableBuffer interface method data -+ */ -+static uint8_t * zmq_msg_t_MutableBuffer_data(void *this_v) { -+ zmq_msg_t * this_p = this_v; -+ return zmq_msg_data(this_p); -+} -+/** -+ * MutableBuffer interface method get_size -+ */ -+static size_t zmq_msg_t_MutableBuffer_get_size(void *this_v) { -+ zmq_msg_t * this_p = this_v; -+ return zmq_msg_size(this_p); -+} -+ -+static const MutableBufferIF zmq_msg_t_MutableBuffer = { -+ zmq_msg_t_MutableBuffer_data, -+ zmq_msg_t_MutableBuffer_get_size -+}; -+ - - - #define obj_type_zmq_msg_t_check(L, _index) \ - (zmq_msg_t *)obj_simple_udata_luacheck(L, _index, &(obj_type_zmq_msg_t)) --#define obj_type_zmq_msg_t_delete(L, _index, flags) \ -- (zmq_msg_t *)obj_simple_udata_luadelete(L, _index, &(obj_type_zmq_msg_t), flags) --#define obj_type_zmq_msg_t_push(L, obj, flags) \ -+#define obj_type_zmq_msg_t_optional(L, _index) \ -+ (zmq_msg_t *)obj_simple_udata_luaoptional(L, _index, &(obj_type_zmq_msg_t)) -+#define obj_type_zmq_msg_t_delete(L, _index) \ -+ (zmq_msg_t *)obj_simple_udata_luadelete(L, _index, &(obj_type_zmq_msg_t)) -+#define obj_type_zmq_msg_t_push(L, obj) \ - obj_simple_udata_luapush(L, obj, sizeof(zmq_msg_t), &(obj_type_zmq_msg_t)) - - #define obj_type_ZMQ_Socket_check(L, _index) \ - obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Socket)) -+#define obj_type_ZMQ_Socket_optional(L, _index) \ -+ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_Socket)) - #define obj_type_ZMQ_Socket_delete(L, _index, flags) \ - obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_Socket), flags) - #define obj_type_ZMQ_Socket_push(L, obj, flags) \ -@@ -739,13 +1546,17 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, - - #define obj_type_ZMQ_Poller_check(L, _index) \ - (ZMQ_Poller *)obj_simple_udata_luacheck(L, _index, &(obj_type_ZMQ_Poller)) --#define obj_type_ZMQ_Poller_delete(L, _index, flags) \ -- (ZMQ_Poller *)obj_simple_udata_luadelete(L, _index, &(obj_type_ZMQ_Poller), flags) --#define obj_type_ZMQ_Poller_push(L, obj, flags) \ -+#define obj_type_ZMQ_Poller_optional(L, _index) \ -+ (ZMQ_Poller *)obj_simple_udata_luaoptional(L, _index, &(obj_type_ZMQ_Poller)) -+#define obj_type_ZMQ_Poller_delete(L, _index) \ -+ (ZMQ_Poller *)obj_simple_udata_luadelete(L, _index, &(obj_type_ZMQ_Poller)) -+#define obj_type_ZMQ_Poller_push(L, obj) \ - obj_simple_udata_luapush(L, obj, sizeof(ZMQ_Poller), &(obj_type_ZMQ_Poller)) - - #define obj_type_ZMQ_Ctx_check(L, _index) \ - obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Ctx)) -+#define obj_type_ZMQ_Ctx_optional(L, _index) \ -+ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_Ctx)) - #define obj_type_ZMQ_Ctx_delete(L, _index, flags) \ - obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_Ctx), flags) - #define obj_type_ZMQ_Ctx_push(L, obj, flags) \ -@@ -753,6 +1564,8 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, - - #define obj_type_ZMQ_StopWatch_check(L, _index) \ - obj_udata_luacheck(L, _index, &(obj_type_ZMQ_StopWatch)) -+#define obj_type_ZMQ_StopWatch_optional(L, _index) \ -+ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_StopWatch)) - #define obj_type_ZMQ_StopWatch_delete(L, _index, flags) \ - obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_StopWatch), flags) - #define obj_type_ZMQ_StopWatch_push(L, obj, flags) \ -@@ -761,30 +1574,83 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, - - - --static const char zmq_ffi_lua_code[] = "local error = error\n" -+static const char *zmq_ffi_lua_code[] = { "local ffi=require\"ffi\"\n" -+"local function ffi_safe_load(name, global)\n" -+" local stat, C = pcall(ffi.load, name, global)\n" -+" if not stat then return nil, C end\n" -+" if global then return ffi.C end\n" -+" return C\n" -+"end\n" -+"local function ffi_load(name, global)\n" -+" return assert(ffi_safe_load(name, global))\n" -+"end\n" -+"\n" -+"local function ffi_string(ptr)\n" -+" if ptr ~= nil then\n" -+" return ffi.string(ptr)\n" -+" end\n" -+" return nil\n" -+"end\n" -+"\n" -+"local function ffi_string_len(ptr, len)\n" -+" if ptr ~= nil then\n" -+" return ffi.string(ptr, len)\n" -+" end\n" -+" return nil\n" -+"end\n" -+"\n" -+"local f_cast = ffi.cast\n" -+"local pcall = pcall\n" -+"local error = error\n" - "local type = type\n" - "local tonumber = tonumber\n" - "local tostring = tostring\n" -+"local sformat = require\"string\".format\n" - "local rawset = rawset\n" --"\n" --"-- try loading luajit's ffi\n" --"local stat, ffi=pcall(require,\"ffi\")\n" --"if not stat then\n" --" return\n" -+"local setmetatable = setmetatable\n" -+"local package = (require\"package\") or {}\n" -+"local p_config = package.config\n" -+"local p_cpath = package.cpath\n" -+"\n" -+"\n" -+"local ffi_load_cmodule\n" -+"\n" -+"-- try to detect luvit.\n" -+"if p_config == nil and p_cpath == nil then\n" -+" ffi_load_cmodule = function(name, global)\n" -+" for path,module in pairs(package.loaded) do\n" -+" if module == name then\n" -+" local C, err = ffi_safe_load(path, global)\n" -+" -- return opened library\n" -+" if C then return C end\n" -+" end\n" -+" end\n" -+" error(\"Failed to find: \" .. name)\n" -+" end\n" -+"else\n" -+" ffi_load_cmodule = function(name, global)\n" -+" local dir_sep = p_config:sub(1,1)\n" -+" local path_sep = p_config:sub(3,3)\n" -+" local path_mark = p_config:sub(5,5)\n" -+" local path_match = \"([^\" .. path_sep .. \"]*)\" .. path_sep\n" -+" -- convert dotted name to directory path.\n" -+" name = name:gsub('%.', dir_sep)\n" -+" -- try each path in search path.\n" -+" for path in p_cpath:gmatch(path_match) do\n" -+" local fname = path:gsub(path_mark, name)\n" -+" local C, err = ffi_safe_load(fname, global)\n" -+" -- return opened library\n" -+" if C then return C end\n" -+" end\n" -+" error(\"Failed to find: \" .. name)\n" -+" end\n" - "end\n" - "\n" --"local _M, _priv, udata_new = ...\n" --"\n" --"local band = bit.band\n" --"local d_getmetatable = debug.getmetatable\n" --"local d_setmetatable = debug.setmetatable\n" -+"local _M, _priv, reg_table = ...\n" -+"local REG_OBJECTS_AS_GLOBALS = false\n" -+"local C = ffi.C\n" - "\n" - "local OBJ_UDATA_FLAG_OWN = 1\n" --"local OBJ_UDATA_FLAG_LOOKUP = 2\n" --"local OBJ_UDATA_LAST_FLAG = OBJ_UDATA_FLAG_LOOKUP\n" --"\n" --"local OBJ_TYPE_FLAG_WEAK_REF = 1\n" --"local OBJ_TYPE_SIMPLE = 2\n" - "\n" - "local function ffi_safe_cdef(block_name, cdefs)\n" - " local fake_type = \"struct sentinel_\" .. block_name .. \"_ty\"\n" -@@ -822,151 +1688,94 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - " uint32_t flags; /**< lua_own:1bit */\n" - "} obj_udata;\n" - "\n" --"]])\n" --"\n" --"-- cache mapping of cdata to userdata\n" --"local weak_objects = setmetatable({}, { __mode = \"v\" })\n" -+"int memcmp(const void *s1, const void *s2, size_t n);\n" - "\n" --"local function obj_udata_luacheck_internal(obj, type_mt, not_delete)\n" --" local obj_mt = d_getmetatable(obj)\n" --" if obj_mt == type_mt then\n" --" -- convert userdata to cdata.\n" --" return ffi.cast(\"obj_udata *\", obj)\n" --" end\n" --" if not_delete then\n" --" error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(obj) .. \")\", 3)\n" --" end\n" --"end\n" -+"]])\n" - "\n" --"local function obj_udata_luacheck(obj, type_mt)\n" --" local ud = obj_udata_luacheck_internal(obj, type_mt, true)\n" --" return ud.obj\n" --"end\n" -+"local nobj_callback_states = {}\n" -+"local nobj_weak_objects = setmetatable({}, {__mode = \"v\"})\n" -+"local nobj_obj_flags = {}\n" - "\n" --"local function obj_udata_to_cdata(objects, ud_obj, c_type, ud_mt)\n" --" -- convert userdata to cdata.\n" --" local c_obj = ffi.cast(c_type, obj_udata_luacheck(ud_obj, ud_mt))\n" --" -- cache converted cdata\n" --" rawset(objects, ud_obj, c_obj)\n" --" return c_obj\n" -+"local function obj_ptr_to_id(ptr)\n" -+" return tonumber(f_cast('uintptr_t', ptr))\n" - "end\n" - "\n" --"local function obj_udata_luadelete(ud_obj, type_mt)\n" --" local ud = obj_udata_luacheck_internal(ud_obj, type_mt, false)\n" --" if not ud then return nil, 0 end\n" --" local obj, flags = ud.obj, ud.flags\n" --" -- null userdata.\n" --" ud.obj = nil\n" --" ud.flags = 0\n" --" -- invalid userdata, by setting the metatable to nil.\n" --" d_setmetatable(ud_obj, nil)\n" --" return obj, flags\n" -+"local function obj_to_id(ptr)\n" -+" return tonumber(f_cast('uintptr_t', f_cast('void *', ptr)))\n" - "end\n" - "\n" --"local function obj_udata_luapush(obj, type_mt, obj_type, flags)\n" --" if obj == nil then return end\n" --"\n" --" -- apply type's dynamic caster.\n" --" if obj_type.dcaster ~= nil then\n" --" local obj_ptr = ffi.new(\"void *[1]\", obj)\n" --" local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n" --" obj_type.dcaster(obj_ptr, type_ptr)\n" --" obj = obj_ptr[1]\n" --" type = type_ptr[1]\n" -+"local function register_default_constructor(_pub, obj_name, constructor)\n" -+" local obj_pub = _pub[obj_name]\n" -+" if type(obj_pub) == 'table' then\n" -+" -- copy table since it might have a locked metatable\n" -+" local new_pub = {}\n" -+" for k,v in pairs(obj_pub) do\n" -+" new_pub[k] = v\n" -+" end\n" -+" setmetatable(new_pub, { __call = function(t,...)\n" -+" return constructor(...)\n" -+" end,\n" -+" __metatable = false,\n" -+" })\n" -+" obj_pub = new_pub\n" -+" else\n" -+" obj_pub = constructor\n" - " end\n" --"\n" --" -- create new userdata\n" --" local ud_obj = udata_new(ffi.sizeof\"obj_udata\", type_mt)\n" --" local ud = ffi.cast(\"obj_udata *\", ud_obj)\n" --" -- init. object\n" --" ud.obj = obj\n" --" ud.flags = flags\n" --"\n" --" return ud_obj\n" --"end\n" --"\n" --"local function obj_udata_luadelete_weak(ud_obj, type_mt)\n" --" local ud = obj_udata_luacheck_internal(ud_obj, type_mt, false)\n" --" if not ud then return nil, 0 end\n" --" local obj, flags = ud.obj, ud.flags\n" --" -- null userdata.\n" --" ud.obj = nil\n" --" ud.flags = 0\n" --" -- invalid userdata, by setting the metatable to nil.\n" --" d_setmetatable(ud_obj, nil)\n" --" -- remove object from weak ref. table.\n" --" local obj_key = tonumber(ffi.cast('uintptr_t', obj))\n" --" weak_objects[obj_key] = nil\n" --" return obj, flags\n" --"end\n" --"\n" --"local function obj_udata_luapush_weak(obj, type_mt, obj_type, flags)\n" --" if obj == nil then return end\n" --"\n" --" -- apply type's dynamic caster.\n" --" if obj_type.dcaster ~= nil then\n" --" local obj_ptr = ffi.new(\"void *[1]\", obj)\n" --" local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n" --" obj_type.dcaster(obj_ptr, type_ptr)\n" --" obj = obj_ptr[1]\n" --" type = type_ptr[1]\n" -+" _pub[obj_name] = obj_pub\n" -+" _M[obj_name] = obj_pub\n" -+" if REG_OBJECTS_AS_GLOBALS then\n" -+" _G[obj_name] = obj_pub\n" - " end\n" --"\n" --" -- lookup object in weak ref. table.\n" --" local obj_key = tonumber(ffi.cast('uintptr_t', obj))\n" --" local ud_obj = weak_objects[obj_key]\n" --" if ud_obj ~= nil then return ud_obj end\n" --"\n" --" -- create new userdata\n" --" ud_obj = udata_new(ffi.sizeof\"obj_udata\", type_mt)\n" --" local ud = ffi.cast(\"obj_udata *\", ud_obj)\n" --" -- init. object\n" --" ud.obj = obj\n" --" ud.flags = flags\n" --"\n" --" -- cache weak reference to object.\n" --" weak_objects[obj_key] = ud_obj\n" --"\n" --" return ud_obj\n" - "end\n" - "\n" --"local function obj_simple_udata_luacheck(ud_obj, type_mt)\n" --" local obj_mt = d_getmetatable(ud_obj)\n" --" if obj_mt == type_mt then\n" --" -- convert userdata to cdata.\n" --" return ffi.cast(\"void *\", ud_obj)\n" --" end\n" --" error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(ud_obj) .. \")\", 3)\n" --"end\n" - "\n" --"local function obj_simple_udata_to_cdata(objects, ud_obj, c_type, ud_mt)\n" --" -- convert userdata to cdata.\n" --" local c_obj = ffi.cast(c_type, obj_simple_udata_luacheck(ud_obj, ud_mt))\n" --" -- cache converted cdata\n" --" rawset(objects, ud_obj, c_obj)\n" --" return c_obj\n" -+"-- detect zmq version\n" -+"local VERSION_2_0 = true\n" -+"local VERSION_2_1 = false\n" -+"local VERSION_2_2 = false\n" -+"local VERSION_3_0 = false\n" -+"local zver = _M.version()\n" -+"if zver[1] == 3 then\n" -+" VERSION_2_0 = false\n" -+" VERSION_3_0 = true\n" -+"elseif zver[1] == 2 and zver[2] == 2 then\n" -+" VERSION_2_2 = true\n" -+" VERSION_2_1 = true\n" -+"elseif zver[1] == 2 and zver[2] == 1 then\n" -+" VERSION_2_1 = true\n" - "end\n" - "\n" --"local function obj_simple_udata_luadelete(ud_obj, type_mt)\n" --" local c_obj = obj_simple_udata_luacheck(ud_obj, type_mt)\n" --" -- invalid userdata, by setting the metatable to nil.\n" --" d_setmetatable(ud_obj, nil)\n" --" return c_obj, OBJ_UDATA_FLAG_OWN\n" -+"if VERSION_2_0 then\n" -+" ffi.cdef[==[\n" -+"typedef int ZMQ_Error;\n" -+"typedef struct ZMQ_Socket ZMQ_Socket;\n" -+"typedef struct zmq_msg_t zmq_msg_t;\n" -+"\n" -+"ZMQ_Error zmq_sendmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__(\"zmq_send\");\n" -+"ZMQ_Error zmq_recvmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__(\"zmq_recv\");\n" -+"]==]\n" - "end\n" - "\n" --"local function obj_simple_udata_luapush(c_obj, size, type_mt)\n" --" if c_obj == nil then return end\n" -+"ffi_safe_cdef(\"MutableBufferIF\", [[\n" -+"typedef struct MutableBuffer_if {\n" -+" uint8_t * (* const data)(void *this_v);\n" -+" size_t (* const get_size)(void *this_v);\n" -+"} MutableBufferIF;\n" -+"]])\n" - "\n" --" -- create new userdata\n" --" local ud_obj = udata_new(size, type_mt)\n" --" local cdata = ffi.cast(\"void *\", ud_obj)\n" --" -- init. object\n" --" ffi.copy(cdata, c_obj, size)\n" -+"ffi_safe_cdef(\"BufferIF\", [[\n" -+"typedef struct Buffer_if {\n" -+" const uint8_t * (* const const_data)(void *this_v);\n" -+" size_t (* const get_size)(void *this_v);\n" -+"} BufferIF;\n" -+"]])\n" - "\n" --" return ud_obj, cdata\n" --"end\n" -+"local Cmod = ffi_load_cmodule(\"zmq\", false)\n" -+"local C = Cmod\n" - "\n" - "ffi.cdef[[\n" -+"typedef int ZMQ_Error;\n" -+"\n" - "typedef struct zmq_msg_t zmq_msg_t;\n" - "typedef struct ZMQ_Socket ZMQ_Socket;\n" - "typedef struct ZMQ_Poller ZMQ_Poller;\n" -@@ -976,9 +1785,7 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - "]]\n" - "\n" - "ffi.cdef[[\n" --"typedef const char * (*get_zmq_strerror_func)();\n" --"\n" --"typedef int ZMQ_Error;\n" -+"int zmq_errno (void);\n" - "\n" - "\n" - "struct zmq_msg_t\n" -@@ -989,39 +1796,134 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - " unsigned char vsm_data [30]; /* that '30' is from 'MAX_VSM_SIZE' */\n" - "};\n" - "\n" --"typedef void (zmq_free_fn) (void *data, void *hint);\n" --"\n" - "int zmq_msg_init (zmq_msg_t *msg);\n" - "int zmq_msg_init_size (zmq_msg_t *msg, size_t size);\n" --"int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint);\n" - "\n" - "\n" --"ZMQ_Error zmq_msg_close(zmq_msg_t * this1);\n" -+"ZMQ_Error zmq_msg_init(zmq_msg_t *);\n" - "\n" --"ZMQ_Error zmq_msg_close(zmq_msg_t * this1);\n" -+"ZMQ_Error zmq_msg_init_size(zmq_msg_t *, size_t);\n" - "\n" --"ZMQ_Error zmq_msg_move(zmq_msg_t * this1, zmq_msg_t * src2);\n" -+"ZMQ_Error zmq_msg_close(zmq_msg_t *);\n" - "\n" --"ZMQ_Error zmq_msg_copy(zmq_msg_t * this1, zmq_msg_t * src2);\n" -+"ZMQ_Error zmq_msg_move(zmq_msg_t *, zmq_msg_t *);\n" - "\n" --"void * zmq_msg_data(zmq_msg_t * this1);\n" -+"ZMQ_Error zmq_msg_copy(zmq_msg_t *, zmq_msg_t *);\n" - "\n" --"size_t zmq_msg_size(zmq_msg_t * this1);\n" -+"void * zmq_msg_data(zmq_msg_t *);\n" - "\n" --"ZMQ_Error zmq_close(ZMQ_Socket * this1);\n" -+"size_t zmq_msg_size(zmq_msg_t *);\n" - "\n" --"ZMQ_Error zmq_bind(ZMQ_Socket * this1, const char * addr2);\n" -+"ZMQ_Error zmq_close(ZMQ_Socket *);\n" - "\n" --"ZMQ_Error zmq_connect(ZMQ_Socket * this1, const char * addr2);\n" -+"ZMQ_Error zmq_bind(ZMQ_Socket *, const char *);\n" -+"\n" -+"ZMQ_Error zmq_connect(ZMQ_Socket *, const char *);\n" - "\n" - "int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen);\n" - "int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen);\n" - "\n" --"ZMQ_Error zmq_send(ZMQ_Socket * this1, zmq_msg_t * msg2, int flags3);\n" -+"ZMQ_Error zmq_sendmsg(ZMQ_Socket *, zmq_msg_t *, int);\n" -+"\n" -+"ZMQ_Error simple_zmq_send(ZMQ_Socket *, const char *, size_t, int);\n" -+"\n" -+"ZMQ_Error zmq_recvmsg(ZMQ_Socket *, zmq_msg_t *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_swap(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_swap(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *, uint64_t*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *, uint64_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_identity(ZMQ_Socket *, char *, size_t*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *, const char *, size_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *, const char *, size_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *, const char *, size_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_rate(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_mcast_loop(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_mcast_loop(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_fd(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_events(ZMQ_Socket *, int*);\n" - "\n" --"typedef ZMQ_Error (*simple_zmq_send_func)(ZMQ_Socket *sock, const char *data, size_t data_len, int flags);\n" -+"ZMQ_Error lzmq_socket_type(ZMQ_Socket *, int*);\n" - "\n" --"ZMQ_Error zmq_recv(ZMQ_Socket * this1, zmq_msg_t * msg2, int flags3);\n" -+"ZMQ_Error lzmq_socket_linger(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_recovery_ivl_msec(ZMQ_Socket *, int64_t*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_recovery_ivl_msec(ZMQ_Socket *, int64_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_maxmsgsize(ZMQ_Socket *, int64_t*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_maxmsgsize(ZMQ_Socket *, int64_t);\n" -+"\n" -+"ZMQ_Error lzmq_socket_sndhwm(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_sndhwm(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_rcvhwm(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_rcvhwm(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_multicast_hops(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_multicast_hops(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *, int);\n" -+"\n" -+"ZMQ_Error lzmq_socket_ipv4only(ZMQ_Socket *, int*);\n" -+"\n" -+"ZMQ_Error lzmq_socket_set_ipv4only(ZMQ_Socket *, int);\n" - "\n" - "typedef int socket_t;\n" - "typedef struct zmq_pollitem_t {\n" -@@ -1031,7 +1933,12 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - " short revents;\n" - "} zmq_pollitem_t;\n" - "\n" --"int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout);\n" -+"int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock);\n" -+"int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd);\n" -+"int poller_get_free_item(ZMQ_Poller *poller);\n" -+"int poller_poll(ZMQ_Poller *poller, long timeout);\n" -+"void poller_remove_item(ZMQ_Poller *poller, int idx);\n" -+"\n" - "\n" - "struct ZMQ_Poller {\n" - " zmq_pollitem_t *items;\n" -@@ -1041,616 +1948,823 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - " int len;\n" - "};\n" - "\n" --"typedef int (*poller_find_sock_item_func)(ZMQ_Poller *poller, ZMQ_Socket *sock);\n" -+"void poller_init(ZMQ_Poller *, unsigned int);\n" - "\n" --"typedef int (*poller_find_fd_item_func)(ZMQ_Poller *poller, socket_t fd);\n" -+"void poller_cleanup(ZMQ_Poller *);\n" - "\n" --"typedef int (*poller_get_free_item_func)(ZMQ_Poller *poller);\n" -+"ZMQ_Error poller_poll(ZMQ_Poller *, long);\n" - "\n" --"typedef int (*poller_poll_func)(ZMQ_Poller *poller, long timeout);\n" -+"int poller_next_revents(ZMQ_Poller *, int*);\n" - "\n" --"typedef void (*poller_remove_item_func)(ZMQ_Poller *poller, int idx);\n" -+"ZMQ_Error zmq_term(ZMQ_Ctx *);\n" - "\n" --"ZMQ_Error zmq_term(ZMQ_Ctx * this1);\n" --"\n" --"ZMQ_Socket * zmq_socket(ZMQ_Ctx * this1, int type2);\n" -+"ZMQ_Socket * zmq_socket(ZMQ_Ctx *, int);\n" - "\n" - "ZMQ_StopWatch * zmq_stopwatch_start();\n" - "\n" --"unsigned long zmq_stopwatch_stop(ZMQ_StopWatch * this1);\n" --"\n" --"ZMQ_Ctx * zmq_init(int io_threads1);\n" -+"unsigned long zmq_stopwatch_stop(ZMQ_StopWatch *);\n" - "\n" --"ZMQ_Error zmq_device(int device1, ZMQ_Socket * insock2, ZMQ_Socket * outsock3);\n" -+"ZMQ_Ctx * zmq_init(int);\n" - "\n" --"ZMQ_StopWatch * zmq_stopwatch_start();\n" -+"ZMQ_Error zmq_device(int, ZMQ_Socket *, ZMQ_Socket *);\n" - "\n" --"void zmq_sleep(int seconds_1);\n" -+"void zmq_sleep(int);\n" - "\n" - "\n" - "]]\n" - "\n" -+"REG_OBJECTS_AS_GLOBALS = false\n" -+"local _obj_interfaces_ffi = {}\n" - "local _pub = {}\n" - "local _meth = {}\n" -+"local _push = {}\n" -+"local _obj_subs = {}\n" - "for obj_name,mt in pairs(_priv) do\n" --" if type(mt) == 'table' and mt.__index then\n" --" _meth[obj_name] = mt.__index\n" -+" if type(mt) == 'table' then\n" -+" _obj_subs[obj_name] = {}\n" -+" if mt.__index then\n" -+" _meth[obj_name] = mt.__index\n" -+" end\n" - " end\n" - "end\n" --"_pub.zmq = _M\n" - "for obj_name,pub in pairs(_M) do\n" - " _pub[obj_name] = pub\n" - "end\n" - "\n" --"\n" --"local obj_type_zmq_msg_t_check\n" --"local obj_type_zmq_msg_t_delete\n" --"local obj_type_zmq_msg_t_push\n" --"\n" --"(function()\n" --"local zmq_msg_t_mt = _priv.zmq_msg_t\n" --"local zmq_msg_t_objects = setmetatable({}, { __mode = \"k\",\n" --"__index = function(objects, ud_obj)\n" --" return obj_simple_udata_to_cdata(objects, ud_obj, \"zmq_msg_t *\", zmq_msg_t_mt)\n" --"end,\n" --"})\n" --"function obj_type_zmq_msg_t_check(ud_obj)\n" --" return zmq_msg_t_objects[ud_obj]\n" -+"--\n" -+"-- CData Metatable access\n" -+"--\n" -+"local _ctypes = {}\n" -+"local _type_names = {}\n" -+"local _get_mt_key = {}\n" -+"local _ctype_meta_map = {}\n" -+"\n" -+"local f_typeof = ffi.typeof\n" -+"local function get_cdata_type_id(cdata)\n" -+" return tonumber(f_typeof(cdata))\n" - "end\n" --"\n" --"function obj_type_zmq_msg_t_delete(ud_obj)\n" --" zmq_msg_t_objects[ud_obj] = nil\n" --" return obj_simple_udata_luadelete(ud_obj, zmq_msg_t_mt)\n" -+"local function get_cdata_mt(cdata)\n" -+" return _ctype_meta_map[tonumber(f_typeof(cdata))]\n" - "end\n" - "\n" --"local zmq_msg_t_sizeof = ffi.sizeof\"zmq_msg_t\"\n" --"function obj_type_zmq_msg_t_push(c_obj)\n" --" local ud_obj, cdata = obj_simple_udata_luapush(c_obj, zmq_msg_t_sizeof, zmq_msg_t_mt)\n" --" zmq_msg_t_objects[ud_obj] = cdata\n" --" return ud_obj\n" -+"local function obj_register_ctype(name, ctype)\n" -+" local obj_mt = _priv[name]\n" -+" local obj_type = obj_mt['.type']\n" -+" local obj_ctype = ffi.typeof(ctype)\n" -+" local obj_type_id = tonumber(obj_ctype)\n" -+" _ctypes[name] = obj_ctype\n" -+" _type_names[name] = tostring(obj_ctype)\n" -+" _ctype_meta_map[obj_type_id] = obj_mt\n" -+" _ctype_meta_map[obj_mt] = obj_type_id\n" -+" return obj_mt, obj_type, obj_ctype\n" - "end\n" --"end)()\n" --"\n" --"\n" --"local obj_type_ZMQ_Socket_check\n" --"local obj_type_ZMQ_Socket_delete\n" --"local obj_type_ZMQ_Socket_push\n" - "\n" --"(function()\n" --"local ZMQ_Socket_mt = _priv.ZMQ_Socket\n" --"local ZMQ_Socket_objects = setmetatable({}, { __mode = \"k\",\n" --"__index = function(objects, ud_obj)\n" --" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_Socket *\", ZMQ_Socket_mt)\n" --"end,\n" --"})\n" --"function obj_type_ZMQ_Socket_check(ud_obj)\n" --" return ZMQ_Socket_objects[ud_obj]\n" -+"--\n" -+"-- Interfaces helper code.\n" -+"--\n" -+"local _obj_interfaces_key = \"obj_interfaces<1.0>_table_key\"\n" -+"local _obj_interfaces_ud = reg_table[_obj_interfaces_key]\n" -+"local _obj_interfaces_key_ffi = _obj_interfaces_key .. \"_LJ2_FFI\"\n" -+"_obj_interfaces_ffi = reg_table[_obj_interfaces_key_ffi]\n" -+"if not _obj_interfaces_ffi then\n" -+" -- create missing interfaces table for FFI bindings.\n" -+" _obj_interfaces_ffi = {}\n" -+" reg_table[_obj_interfaces_key_ffi] = _obj_interfaces_ffi\n" - "end\n" - "\n" --"function obj_type_ZMQ_Socket_delete(ud_obj)\n" --" ZMQ_Socket_objects[ud_obj] = nil\n" --" return obj_udata_luadelete_weak(ud_obj, ZMQ_Socket_mt)\n" -+"local function obj_get_userdata_interface(if_name, expected_err)\n" -+" local impls_ud = _obj_interfaces_ud[if_name]\n" -+" if not impls_ud then\n" -+" impls_ud = {}\n" -+" _obj_interfaces_ud[if_name] = impls_ud\n" -+" end\n" -+" -- create cdata check function to be used by non-ffi bindings.\n" -+" if not impls_ud.cdata then\n" -+" function impls_ud.cdata(obj)\n" -+" return assert(impls_ud[get_cdata_mt(obj)], expected_err)\n" -+" end\n" -+" end\n" -+" return impls_ud\n" - "end\n" - "\n" --"local ZMQ_Socket_type = ffi.cast(\"obj_type *\", ZMQ_Socket_mt[\".type\"])\n" --"function obj_type_ZMQ_Socket_push(c_obj, flags)\n" --" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Socket_mt, ZMQ_Socket_type, flags)\n" --" ZMQ_Socket_objects[ud_obj] = c_obj\n" --" return ud_obj\n" -+"local function obj_get_interface_check(if_name, expected_err)\n" -+" local impls_ffi = _obj_interfaces_ffi[if_name]\n" -+" if not impls_ffi then\n" -+" local if_type = ffi.typeof(if_name .. \" *\")\n" -+" local impls_ud = obj_get_userdata_interface(if_name, expected_err)\n" -+" -- create table for FFI-based interface implementations.\n" -+" impls_ffi = setmetatable({}, {\n" -+" __index = function(impls_ffi, mt)\n" -+" local impl = impls_ud[mt]\n" -+" if impl then\n" -+" -- cast to cdata\n" -+" impl = if_type(impl)\n" -+" rawset(impls_ffi, mt, impl)\n" -+" end\n" -+" return impl\n" -+" end})\n" -+" _obj_interfaces_ffi[if_name] = impls_ffi\n" -+"\n" -+" -- create check function for this interface.\n" -+" function impls_ffi.check(obj)\n" -+" local impl\n" -+" if type(obj) == 'cdata' then\n" -+" impl = impls_ffi[get_cdata_type_id(obj)]\n" -+" else\n" -+" impl = impls_ud.userdata(impls_ffi, obj)\n" -+" end\n" -+" return assert(impl, expected_err)\n" -+" end\n" -+" end\n" -+" return impls_ffi.check\n" - "end\n" --"end)()\n" --"\n" --"\n" --"local obj_type_ZMQ_Poller_check\n" --"local obj_type_ZMQ_Poller_delete\n" --"local obj_type_ZMQ_Poller_push\n" - "\n" --"(function()\n" --"local ZMQ_Poller_mt = _priv.ZMQ_Poller\n" --"local ZMQ_Poller_objects = setmetatable({}, { __mode = \"k\",\n" --"__index = function(objects, ud_obj)\n" --" return obj_simple_udata_to_cdata(objects, ud_obj, \"ZMQ_Poller *\", ZMQ_Poller_mt)\n" --"end,\n" --"})\n" --"function obj_type_ZMQ_Poller_check(ud_obj)\n" --" return ZMQ_Poller_objects[ud_obj]\n" -+"local function obj_register_interface(if_name, obj_name)\n" -+" -- loopkup cdata id\n" -+" local obj_mt = _priv[obj_name]\n" -+" local obj_type_id = _ctype_meta_map[obj_mt]\n" -+" local impl_meths = {}\n" -+" local ffi_impls = _obj_interfaces_ffi[if_name]\n" -+" ffi_impls[obj_type_id] = impl_meths\n" -+" _meth[obj_name]['NOBJ_get_' .. if_name] = impl_meths\n" -+" return impl_meths\n" - "end\n" - "\n" --"function obj_type_ZMQ_Poller_delete(ud_obj)\n" --" ZMQ_Poller_objects[ud_obj] = nil\n" --" return obj_simple_udata_luadelete(ud_obj, ZMQ_Poller_mt)\n" --"end\n" - "\n" --"local ZMQ_Poller_sizeof = ffi.sizeof\"ZMQ_Poller\"\n" --"function obj_type_ZMQ_Poller_push(c_obj)\n" --" local ud_obj, cdata = obj_simple_udata_luapush(c_obj, ZMQ_Poller_sizeof, ZMQ_Poller_mt)\n" --" ZMQ_Poller_objects[ud_obj] = cdata\n" --" return ud_obj\n" --"end\n" --"end)()\n" -+"local obj_type_zmq_msg_t_check\n" -+"local obj_type_zmq_msg_t_delete\n" -+"local obj_type_zmq_msg_t_push\n" - "\n" -+"do\n" -+" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"zmq_msg_t\", \"zmq_msg_t\")\n" -+" local zmq_msg_t_sizeof = ffi.sizeof\"zmq_msg_t\"\n" - "\n" --"local obj_type_ZMQ_Ctx_check\n" --"local obj_type_ZMQ_Ctx_delete\n" --"local obj_type_ZMQ_Ctx_push\n" -+" function obj_type_zmq_msg_t_check(obj)\n" -+" return obj\n" -+" end\n" - "\n" --"(function()\n" --"local ZMQ_Ctx_mt = _priv.ZMQ_Ctx\n" --"local ZMQ_Ctx_objects = setmetatable({}, { __mode = \"k\",\n" --"__index = function(objects, ud_obj)\n" --" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_Ctx *\", ZMQ_Ctx_mt)\n" --"end,\n" --"})\n" --"function obj_type_ZMQ_Ctx_check(ud_obj)\n" --" return ZMQ_Ctx_objects[ud_obj]\n" --"end\n" -+" function obj_type_zmq_msg_t_delete(obj)\n" -+" return obj\n" -+" end\n" - "\n" --"function obj_type_ZMQ_Ctx_delete(ud_obj)\n" --" ZMQ_Ctx_objects[ud_obj] = nil\n" --" return obj_udata_luadelete_weak(ud_obj, ZMQ_Ctx_mt)\n" --"end\n" -+" function obj_type_zmq_msg_t_push(obj)\n" -+" return obj\n" -+" end\n" - "\n" --"local ZMQ_Ctx_type = ffi.cast(\"obj_type *\", ZMQ_Ctx_mt[\".type\"])\n" --"function obj_type_ZMQ_Ctx_push(c_obj, flags)\n" --" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Ctx_mt, ZMQ_Ctx_type, flags)\n" --" ZMQ_Ctx_objects[ud_obj] = c_obj\n" --" return ud_obj\n" --"end\n" --"end)()\n" -+" function obj_mt:__tostring()\n" -+" return sformat(\"zmq_msg_t: %p\", self)\n" -+" end\n" - "\n" -+" function obj_mt.__eq(val1, val2)\n" -+" if not ffi.istype(obj_type, val2) then return false end\n" -+" assert(ffi.istype(obj_type, val1), \"expected zmq_msg_t\")\n" -+" return (C.memcmp(val1, val2, zmq_msg_t_sizeof) == 0)\n" -+" end\n" - "\n" --"local obj_type_ZMQ_StopWatch_check\n" --"local obj_type_ZMQ_StopWatch_delete\n" --"local obj_type_ZMQ_StopWatch_push\n" -+" -- type checking function for C API.\n" -+" local function c_check(obj)\n" -+" if ffi.istype(obj_type, obj) then return obj end\n" -+" return nil\n" -+" end\n" -+" _priv[obj_type] = c_check\n" -+" -- push function for C API.\n" -+" reg_table[obj_type] = function(ptr)\n" -+" local obj = obj_ctype()\n" -+" ffi.copy(obj, ptr, zmq_msg_t_sizeof);\n" -+" return obj\n" -+" end\n" - "\n" --"(function()\n" --"local ZMQ_StopWatch_mt = _priv.ZMQ_StopWatch\n" --"local ZMQ_StopWatch_objects = setmetatable({}, { __mode = \"k\",\n" --"__index = function(objects, ud_obj)\n" --" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_StopWatch *\", ZMQ_StopWatch_mt)\n" --"end,\n" --"})\n" --"function obj_type_ZMQ_StopWatch_check(ud_obj)\n" --" return ZMQ_StopWatch_objects[ud_obj]\n" -+" -- export check functions for use in other modules.\n" -+" obj_mt.c_check = c_check\n" -+" obj_mt.ffi_check = obj_type_zmq_msg_t_check\n" - "end\n" - "\n" --"function obj_type_ZMQ_StopWatch_delete(ud_obj)\n" --" ZMQ_StopWatch_objects[ud_obj] = nil\n" --" return obj_udata_luadelete_weak(ud_obj, ZMQ_StopWatch_mt)\n" --"end\n" -+"\n", /* ----- CUT ----- */ -+"local obj_type_ZMQ_Socket_check\n" -+"local obj_type_ZMQ_Socket_delete\n" -+"local obj_type_ZMQ_Socket_push\n" - "\n" --"local ZMQ_StopWatch_type = ffi.cast(\"obj_type *\", ZMQ_StopWatch_mt[\".type\"])\n" --"function obj_type_ZMQ_StopWatch_push(c_obj, flags)\n" --" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_StopWatch_mt, ZMQ_StopWatch_type, flags)\n" --" ZMQ_StopWatch_objects[ud_obj] = c_obj\n" --" return ud_obj\n" --"end\n" --"end)()\n" -+"do\n" -+" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Socket\", \"ZMQ_Socket *\")\n" -+"\n" -+" function obj_type_ZMQ_Socket_check(ptr)\n" -+" -- if ptr is nil or is the correct type, then just return it.\n" -+" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" -+" -- check if it is a compatible type.\n" -+" local ctype = tostring(ffi.typeof(ptr))\n" -+" local bcaster = _obj_subs.ZMQ_Socket[ctype]\n" -+" if bcaster then\n" -+" return bcaster(ptr)\n" -+" end\n" -+" return error(\"Expected 'ZMQ_Socket *'\", 2)\n" -+" end\n" - "\n" -+" function obj_type_ZMQ_Socket_delete(ptr)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" local flags = nobj_obj_flags[id]\n" -+" if not flags then return nil, 0 end\n" -+" ffi.gc(ptr, nil)\n" -+" nobj_obj_flags[id] = nil\n" -+" return ptr, flags\n" -+" end\n" - "\n" --"local get_zmq_strerror = ffi.new(\"get_zmq_strerror_func\", _priv[\"get_zmq_strerror\"])\n" -+" function obj_type_ZMQ_Socket_push(ptr, flags)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" -- check weak refs\n" -+" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" - "\n" --"local simple_zmq_send = ffi.new(\"simple_zmq_send_func\", _priv[\"simple_zmq_send\"])\n" -+" if flags ~= 0 then\n" -+" nobj_obj_flags[id] = flags\n" -+" ffi.gc(ptr, obj_mt.__gc)\n" -+" end\n" -+" nobj_weak_objects[id] = ptr\n" -+" return ptr\n" -+" end\n" - "\n" --"local poller_find_sock_item = ffi.new(\"poller_find_sock_item_func\", _priv[\"poller_find_sock_item\"])\n" -+" function obj_mt:__tostring()\n" -+" return sformat(\"ZMQ_Socket: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" -+" end\n" - "\n" --"local poller_find_fd_item = ffi.new(\"poller_find_fd_item_func\", _priv[\"poller_find_fd_item\"])\n" -+" -- type checking function for C API.\n" -+" _priv[obj_type] = obj_type_ZMQ_Socket_check\n" -+" -- push function for C API.\n" -+" reg_table[obj_type] = function(ptr, flags)\n" -+" return obj_type_ZMQ_Socket_push(ffi.cast(obj_ctype,ptr), flags)\n" -+" end\n" - "\n" --"local poller_get_free_item = ffi.new(\"poller_get_free_item_func\", _priv[\"poller_get_free_item\"])\n" -+" -- export check functions for use in other modules.\n" -+" obj_mt.c_check = obj_type_ZMQ_Socket_check\n" -+" obj_mt.ffi_check = obj_type_ZMQ_Socket_check\n" -+"end\n" - "\n" --"local poller_poll = ffi.new(\"poller_poll_func\", _priv[\"poller_poll\"])\n" - "\n" --"local poller_remove_item = ffi.new(\"poller_remove_item_func\", _priv[\"poller_remove_item\"])\n" -+"local obj_type_ZMQ_Poller_check\n" -+"local obj_type_ZMQ_Poller_delete\n" -+"local obj_type_ZMQ_Poller_push\n" - "\n" --"local os_lib_table = {\n" --" [\"Windows\"] = \"libzmq\",\n" --"}\n" --"local C = ffi.load(os_lib_table[ffi.os] or \"zmq\")\n" -+"do\n" -+" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Poller\", \"ZMQ_Poller\")\n" -+" local ZMQ_Poller_sizeof = ffi.sizeof\"ZMQ_Poller\"\n" - "\n" --"local C_get_zmq_strerror = get_zmq_strerror\n" --"-- make nicer wrapper for exported error function.\n" --"local function get_zmq_strerror()\n" --" return ffi.string(C_get_zmq_strerror())\n" --"end\n" -+" function obj_type_ZMQ_Poller_check(obj)\n" -+" return obj\n" -+" end\n" - "\n" --"local function error_code__ZMQ_Error__push(err)\n" --" local err_str\n" --" if(-1 == err) then\n" --" err_str = get_zmq_strerror();\n" -+" function obj_type_ZMQ_Poller_delete(obj)\n" -+" return obj\n" - " end\n" - "\n" --" return err_str\n" -+" function obj_type_ZMQ_Poller_push(obj)\n" -+" return obj\n" -+" end\n" -+"\n" -+" function obj_mt:__tostring()\n" -+" return sformat(\"ZMQ_Poller: %p\", self)\n" -+" end\n" -+"\n" -+" function obj_mt.__eq(val1, val2)\n" -+" if not ffi.istype(obj_type, val2) then return false end\n" -+" assert(ffi.istype(obj_type, val1), \"expected ZMQ_Poller\")\n" -+" return (C.memcmp(val1, val2, ZMQ_Poller_sizeof) == 0)\n" -+" end\n" -+"\n" -+" -- type checking function for C API.\n" -+" local function c_check(obj)\n" -+" if ffi.istype(obj_type, obj) then return obj end\n" -+" return nil\n" -+" end\n" -+" _priv[obj_type] = c_check\n" -+" -- push function for C API.\n" -+" reg_table[obj_type] = function(ptr)\n" -+" local obj = obj_ctype()\n" -+" ffi.copy(obj, ptr, ZMQ_Poller_sizeof);\n" -+" return obj\n" -+" end\n" -+"\n" -+" -- export check functions for use in other modules.\n" -+" obj_mt.c_check = c_check\n" -+" obj_mt.ffi_check = obj_type_ZMQ_Poller_check\n" -+"end\n" -+"\n" -+"\n" -+"local obj_type_ZMQ_Ctx_check\n" -+"local obj_type_ZMQ_Ctx_delete\n" -+"local obj_type_ZMQ_Ctx_push\n" -+"\n" -+"do\n" -+" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Ctx\", \"ZMQ_Ctx *\")\n" -+"\n" -+" function obj_type_ZMQ_Ctx_check(ptr)\n" -+" -- if ptr is nil or is the correct type, then just return it.\n" -+" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" -+" -- check if it is a compatible type.\n" -+" local ctype = tostring(ffi.typeof(ptr))\n" -+" local bcaster = _obj_subs.ZMQ_Ctx[ctype]\n" -+" if bcaster then\n" -+" return bcaster(ptr)\n" -+" end\n" -+" return error(\"Expected 'ZMQ_Ctx *'\", 2)\n" -+" end\n" -+"\n" -+" function obj_type_ZMQ_Ctx_delete(ptr)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" local flags = nobj_obj_flags[id]\n" -+" if not flags then return nil, 0 end\n" -+" ffi.gc(ptr, nil)\n" -+" nobj_obj_flags[id] = nil\n" -+" return ptr, flags\n" -+" end\n" -+"\n" -+" function obj_type_ZMQ_Ctx_push(ptr, flags)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" -- check weak refs\n" -+" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" -+"\n" -+" if flags ~= 0 then\n" -+" nobj_obj_flags[id] = flags\n" -+" ffi.gc(ptr, obj_mt.__gc)\n" -+" end\n" -+" nobj_weak_objects[id] = ptr\n" -+" return ptr\n" -+" end\n" -+"\n" -+" function obj_mt:__tostring()\n" -+" return sformat(\"ZMQ_Ctx: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" -+" end\n" -+"\n" -+" -- type checking function for C API.\n" -+" _priv[obj_type] = obj_type_ZMQ_Ctx_check\n" -+" -- push function for C API.\n" -+" reg_table[obj_type] = function(ptr, flags)\n" -+" return obj_type_ZMQ_Ctx_push(ffi.cast(obj_ctype,ptr), flags)\n" -+" end\n" -+"\n" -+" -- export check functions for use in other modules.\n" -+" obj_mt.c_check = obj_type_ZMQ_Ctx_check\n" -+" obj_mt.ffi_check = obj_type_ZMQ_Ctx_check\n" -+"end\n" -+"\n" -+"\n" -+"local obj_type_ZMQ_StopWatch_check\n" -+"local obj_type_ZMQ_StopWatch_delete\n" -+"local obj_type_ZMQ_StopWatch_push\n" -+"\n" -+"do\n" -+" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_StopWatch\", \"ZMQ_StopWatch *\")\n" -+"\n" -+" function obj_type_ZMQ_StopWatch_check(ptr)\n" -+" -- if ptr is nil or is the correct type, then just return it.\n" -+" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" -+" -- check if it is a compatible type.\n" -+" local ctype = tostring(ffi.typeof(ptr))\n" -+" local bcaster = _obj_subs.ZMQ_StopWatch[ctype]\n" -+" if bcaster then\n" -+" return bcaster(ptr)\n" -+" end\n" -+" return error(\"Expected 'ZMQ_StopWatch *'\", 2)\n" -+" end\n" -+"\n" -+" function obj_type_ZMQ_StopWatch_delete(ptr)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" local flags = nobj_obj_flags[id]\n" -+" if not flags then return nil, 0 end\n" -+" ffi.gc(ptr, nil)\n" -+" nobj_obj_flags[id] = nil\n" -+" return ptr, flags\n" -+" end\n" -+"\n" -+" function obj_type_ZMQ_StopWatch_push(ptr, flags)\n" -+" local id = obj_ptr_to_id(ptr)\n" -+" -- check weak refs\n" -+" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" -+"\n" -+" if flags ~= 0 then\n" -+" nobj_obj_flags[id] = flags\n" -+" ffi.gc(ptr, obj_mt.__gc)\n" -+" end\n" -+" nobj_weak_objects[id] = ptr\n" -+" return ptr\n" -+" end\n" -+"\n" -+" function obj_mt:__tostring()\n" -+" return sformat(\"ZMQ_StopWatch: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" -+" end\n" -+"\n" -+" -- type checking function for C API.\n" -+" _priv[obj_type] = obj_type_ZMQ_StopWatch_check\n" -+" -- push function for C API.\n" -+" reg_table[obj_type] = function(ptr, flags)\n" -+" return obj_type_ZMQ_StopWatch_push(ffi.cast(obj_ctype,ptr), flags)\n" -+" end\n" -+"\n" -+" -- export check functions for use in other modules.\n" -+" obj_mt.c_check = obj_type_ZMQ_StopWatch_check\n" -+" obj_mt.ffi_check = obj_type_ZMQ_StopWatch_check\n" -+"end\n" -+"\n" -+"\n" -+"local obj_type_MutableBuffer_check =\n" -+" obj_get_interface_check(\"MutableBufferIF\", \"Expected object with MutableBuffer interface\")\n" -+"\n" -+"local obj_type_Buffer_check =\n" -+" obj_get_interface_check(\"BufferIF\", \"Expected object with Buffer interface\")\n" -+"\n" -+"local os_lib_table = {\n" -+" [\"Windows\"] = \"libzmq\",\n" -+"}\n" -+"C = ffi_load(os_lib_table[ffi.os] or \"zmq\")\n" -+"\n" -+"\n" -+"-- Start \"ZErrors\" FFI interface\n" -+"-- End \"ZErrors\" FFI interface\n" -+"\n" -+"-- get ZErrors table to map errno to error name.\n" -+"local ZError_names = _M.ZErrors\n" -+"\n" -+"local function get_zmq_strerror()\n" -+" return ZError_names[C.zmq_errno()]\n" -+"end\n" -+"\n" -+"local function error_code__ZMQ_Error__push(err)\n" -+" local err_str\n" -+" if(-1 == err) then\n" -+" err_str = ZError_names[C.zmq_errno()]\n" -+" end\n" -+"\n" -+" return err_str\n" - "end\n" - "\n" - "\n" - "-- Start \"zmq_msg_t\" FFI interface\n" -+"-- method: init\n" -+"function _pub.zmq_msg_t.init()\n" -+" local self = ffi.new(\"zmq_msg_t\")\n" -+" local rc_zmq_msg_init2 = 0\n" -+" rc_zmq_msg_init2 = C.zmq_msg_init(self)\n" -+" if (-1 == rc_zmq_msg_init2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_zmq_msg_init2)\n" -+" end\n" -+" return obj_type_zmq_msg_t_push(self)\n" -+"end\n" -+"register_default_constructor(_pub,\"zmq_msg_t\",_pub.zmq_msg_t.init)\n" -+"\n" -+"-- method: init_size\n" -+"function _pub.zmq_msg_t.init_size(size1)\n" -+" \n" -+" local self = ffi.new(\"zmq_msg_t\")\n" -+" local rc_zmq_msg_init_size2 = 0\n" -+" rc_zmq_msg_init_size2 = C.zmq_msg_init_size(self, size1)\n" -+" if (-1 == rc_zmq_msg_init_size2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_zmq_msg_init_size2)\n" -+" end\n" -+" return obj_type_zmq_msg_t_push(self)\n" -+"end\n" -+"\n" -+"-- method: init_data\n" -+"function _pub.zmq_msg_t.init_data(data1)\n" -+" local data_len1 = #data1\n" -+" local self = ffi.new(\"zmq_msg_t\")\n" -+" local err2 = 0\n" -+" err2 = C.zmq_msg_init_size(self, data_len1)\n" -+" if(0 == err2) then\n" -+" -- fill message\n" -+" ffi.copy(C.zmq_msg_data(self), data1, data_len1)\n" -+" end\n" -+"\n" -+" if (-1 == err2) then\n" -+" return nil,error_code__ZMQ_Error__push(err2)\n" -+" end\n" -+" return obj_type_zmq_msg_t_push(self)\n" -+"end\n" -+"\n" - "-- method: __gc\n" - "function _priv.zmq_msg_t.__gc(self)\n" --" local this1,this_flags1 = obj_type_zmq_msg_t_delete(self)\n" --" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" --" local rc_zmq_msg_close1\n" --" rc_zmq_msg_close1 = C.zmq_msg_close(this1)\n" -+" local self = obj_type_zmq_msg_t_delete(self)\n" -+" if not self then return end\n" -+" local rc_zmq_msg_close1 = 0\n" -+" rc_zmq_msg_close1 = C.zmq_msg_close(self)\n" - " -- check for error.\n" --" local rc_zmq_msg_close1_err\n" - " if (-1 == rc_zmq_msg_close1) then\n" --" rc_zmq_msg_close1_err = error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" --" rc_zmq_msg_close1 = nil\n" --" else\n" --" rc_zmq_msg_close1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" - " end\n" --" return rc_zmq_msg_close1, rc_zmq_msg_close1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: close\n" - "function _meth.zmq_msg_t.close(self)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" --" local rc_zmq_msg_close1\n" --" rc_zmq_msg_close1 = C.zmq_msg_close(this1)\n" -+" \n" -+" local rc_zmq_msg_close1 = 0\n" -+" rc_zmq_msg_close1 = C.zmq_msg_close(self)\n" - " -- check for error.\n" --" local rc_zmq_msg_close1_err\n" - " if (-1 == rc_zmq_msg_close1) then\n" --" rc_zmq_msg_close1_err = error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" --" rc_zmq_msg_close1 = nil\n" --" else\n" --" rc_zmq_msg_close1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" - " end\n" --" return rc_zmq_msg_close1, rc_zmq_msg_close1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: move\n" - "function _meth.zmq_msg_t.move(self, src2)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" --" src2 = obj_type_zmq_msg_t_check(src2)\n" --" local rc_zmq_msg_move1\n" --" rc_zmq_msg_move1 = C.zmq_msg_move(this1, src2)\n" -+" \n" -+" \n" -+" local rc_zmq_msg_move1 = 0\n" -+" rc_zmq_msg_move1 = C.zmq_msg_move(self, src2)\n" - " -- check for error.\n" --" local rc_zmq_msg_move1_err\n" - " if (-1 == rc_zmq_msg_move1) then\n" --" rc_zmq_msg_move1_err = error_code__ZMQ_Error__push(rc_zmq_msg_move1)\n" --" rc_zmq_msg_move1 = nil\n" --" else\n" --" rc_zmq_msg_move1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_move1)\n" - " end\n" --" return rc_zmq_msg_move1, rc_zmq_msg_move1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: copy\n" - "function _meth.zmq_msg_t.copy(self, src2)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" --" src2 = obj_type_zmq_msg_t_check(src2)\n" --" local rc_zmq_msg_copy1\n" --" rc_zmq_msg_copy1 = C.zmq_msg_copy(this1, src2)\n" -+" \n" -+" \n" -+" local rc_zmq_msg_copy1 = 0\n" -+" rc_zmq_msg_copy1 = C.zmq_msg_copy(self, src2)\n" - " -- check for error.\n" --" local rc_zmq_msg_copy1_err\n" - " if (-1 == rc_zmq_msg_copy1) then\n" --" rc_zmq_msg_copy1_err = error_code__ZMQ_Error__push(rc_zmq_msg_copy1)\n" --" rc_zmq_msg_copy1 = nil\n" --" else\n" --" rc_zmq_msg_copy1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_copy1)\n" - " end\n" --" return rc_zmq_msg_copy1, rc_zmq_msg_copy1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: set_data\n" - "function _meth.zmq_msg_t.set_data(self, data2)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" -+" \n" - " local data_len2 = #data2\n" --" local err1\n" -+" local err1 = 0\n" - " -- check message data size.\n" --" if (C.zmq_msg_size(this1) ~= data_len2) then\n" -+" if (C.zmq_msg_size(self) ~= data_len2) then\n" - " -- need to resize message.\n" --" C.zmq_msg_close(this1); -- close old message, to free old data.\n" --" err1 = C.zmq_msg_init_size(this1, data_len2); -- re-initialize message.\n" -+" C.zmq_msg_close(self); -- close old message, to free old data.\n" -+" err1 = C.zmq_msg_init_size(self, data_len2); -- re-initialize message.\n" - " if (0 ~= err1) then\n" - " error(\"set_data() failed: \" .. get_zmq_strerror());\n" - " end\n" - " end\n" - " -- copy data into message\n" --" ffi.copy(C.zmq_msg_data(this1), data2, data_len2);\n" -+" ffi.copy(C.zmq_msg_data(self), data2, data_len2);\n" - "\n" - " -- check for error.\n" --" local err1_err\n" - " if (-1 == err1) then\n" --" err1_err = error_code__ZMQ_Error__push(err1)\n" --" err1 = nil\n" --" else\n" --" err1 = true\n" -+" return nil, error_code__ZMQ_Error__push(err1)\n" - " end\n" --" return err1, err1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: data\n" - "function _meth.zmq_msg_t.data(self)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" -+" \n" - " local rc_zmq_msg_data1\n" --" rc_zmq_msg_data1 = C.zmq_msg_data(this1)\n" --" rc_zmq_msg_data1 = rc_zmq_msg_data1\n" -+" rc_zmq_msg_data1 = C.zmq_msg_data(self)\n" - " return rc_zmq_msg_data1\n" - "end\n" - "\n" - "-- method: set_size\n" - "function _meth.zmq_msg_t.set_size(self, size2)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" - " \n" --" local err1\n" -+" \n" -+" local err1 = 0\n" - " -- check message data size.\n" --" if (C.zmq_msg_size(this1) ~= size2) then\n" -+" if (C.zmq_msg_size(self) ~= size2) then\n" - " -- need to resize message.\n" --" C.zmq_msg_close(this1); -- close old message, to free old data.\n" --" err1 = C.zmq_msg_init_size(this1, size2); -- re-initialize message.\n" -+" C.zmq_msg_close(self); -- close old message, to free old data.\n" -+" err1 = C.zmq_msg_init_size(self, size2); -- re-initialize message.\n" - " if (0 ~= err1) then\n" - " error(\"set_size() failed: \" .. get_zmq_strerror());\n" - " end\n" - " end\n" - "\n" - " -- check for error.\n" --" local err1_err\n" - " if (-1 == err1) then\n" --" err1_err = error_code__ZMQ_Error__push(err1)\n" --" err1 = nil\n" --" else\n" --" err1 = true\n" -+" return nil, error_code__ZMQ_Error__push(err1)\n" - " end\n" --" return err1, err1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: size\n" - "function _meth.zmq_msg_t.size(self)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" --" local rc_zmq_msg_size1\n" --" rc_zmq_msg_size1 = C.zmq_msg_size(this1)\n" --" rc_zmq_msg_size1 = rc_zmq_msg_size1\n" --" return rc_zmq_msg_size1\n" -+" \n" -+" local size1 = 0\n" -+" size1 = C.zmq_msg_size(self)\n" -+" return tonumber(size1)\n" - "end\n" - "\n" - "-- method: __tostring\n" - "function _priv.zmq_msg_t.__tostring(self)\n" --" local this1 = obj_type_zmq_msg_t_check(self)\n" -+" \n" - " local data_len1 = 0\n" - " local data1\n" --" data1 = C.zmq_msg_data(this1);\n" --" data_len1 = C.zmq_msg_size(this1);\n" -+" data1 = C.zmq_msg_data(self);\n" -+" data_len1 = C.zmq_msg_size(self);\n" -+"\n" -+" return ffi_string_len(data1,data_len1)\n" -+"end\n" -+"\n" -+"-- zmq_msg_t implements Buffer interface\n" -+"do\n" -+" local impl_meths = obj_register_interface(\"BufferIF\", \"zmq_msg_t\")\n" -+"-- Buffer interface method const_data\n" -+"impl_meths.const_data = C.zmq_msg_data\n" -+"-- Buffer interface method get_size\n" -+"impl_meths.get_size = C.zmq_msg_size\n" -+"end\n" - "\n" --" data1 = ((nil ~= data1) and ffi.string(data1,data_len1))\n" --" return data1\n" -+"-- zmq_msg_t implements MutableBuffer interface\n" -+"do\n" -+" local impl_meths = obj_register_interface(\"MutableBufferIF\", \"zmq_msg_t\")\n" -+"-- MutableBuffer interface method data\n" -+"impl_meths.data = C.zmq_msg_data\n" -+"-- MutableBuffer interface method get_size\n" -+"impl_meths.get_size = C.zmq_msg_size\n" - "end\n" - "\n" -+"_push.zmq_msg_t = obj_type_zmq_msg_t_push\n" -+"ffi.metatype(\"zmq_msg_t\", _priv.zmq_msg_t)\n" - "-- End \"zmq_msg_t\" FFI interface\n" - "\n" - "\n" - "-- Start \"ZMQ_Socket\" FFI interface\n" - "-- method: close\n" - "function _meth.ZMQ_Socket.close(self)\n" --" local this1,this_flags1 = obj_type_ZMQ_Socket_delete(self)\n" --" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" --" local rc_zmq_close1\n" --" rc_zmq_close1 = C.zmq_close(this1)\n" -+" local self,this_flags1 = obj_type_ZMQ_Socket_delete(self)\n" -+" if not self then return end\n" -+" local rc_zmq_close1 = 0\n" -+" rc_zmq_close1 = C.zmq_close(self)\n" - " -- check for error.\n" --" local rc_zmq_close1_err\n" - " if (-1 == rc_zmq_close1) then\n" --" rc_zmq_close1_err = error_code__ZMQ_Error__push(rc_zmq_close1)\n" --" rc_zmq_close1 = nil\n" --" else\n" --" rc_zmq_close1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_close1)\n" - " end\n" --" return rc_zmq_close1, rc_zmq_close1_err\n" -+" return true\n" - "end\n" -+"_priv.ZMQ_Socket.__gc = _meth.ZMQ_Socket.close\n" - "\n" - "-- method: bind\n" - "function _meth.ZMQ_Socket.bind(self, addr2)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" -+" \n" - " local addr_len2 = #addr2\n" --" local rc_zmq_bind1\n" --" rc_zmq_bind1 = C.zmq_bind(this1, addr2)\n" -+" local rc_zmq_bind1 = 0\n" -+" rc_zmq_bind1 = C.zmq_bind(self, addr2)\n" - " -- check for error.\n" --" local rc_zmq_bind1_err\n" - " if (-1 == rc_zmq_bind1) then\n" --" rc_zmq_bind1_err = error_code__ZMQ_Error__push(rc_zmq_bind1)\n" --" rc_zmq_bind1 = nil\n" --" else\n" --" rc_zmq_bind1 = true\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_bind1)\n" - " end\n" --" return rc_zmq_bind1, rc_zmq_bind1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: connect\n" - "function _meth.ZMQ_Socket.connect(self, addr2)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" -+" \n" - " local addr_len2 = #addr2\n" --" local rc_zmq_connect1\n" --" rc_zmq_connect1 = C.zmq_connect(this1, addr2)\n" -+" local rc_zmq_connect1 = 0\n" -+" rc_zmq_connect1 = C.zmq_connect(self, addr2)\n" - " -- check for error.\n" --" local rc_zmq_connect1_err\n" - " if (-1 == rc_zmq_connect1) then\n" --" rc_zmq_connect1_err = error_code__ZMQ_Error__push(rc_zmq_connect1)\n" --" rc_zmq_connect1 = nil\n" --" else\n" --" rc_zmq_connect1 = true\n" --" end\n" --" return rc_zmq_connect1, rc_zmq_connect1_err\n" --"end\n" --"\n" --"local option_types = {\n" --"[zmq.HWM] = 'uint64_t[1]',\n" --"[zmq.SWAP] = 'int64_t[1]',\n" --"[zmq.AFFINITY] = 'uint64_t[1]',\n" --"[zmq.IDENTITY] = 'string',\n" --"[zmq.SUBSCRIBE] = 'string',\n" --"[zmq.UNSUBSCRIBE] = 'string',\n" --"[zmq.RATE] = 'int64_t[1]',\n" --"[zmq.RECOVERY_IVL] = 'int64_t[1]',\n" --"[zmq.MCAST_LOOP] = 'int64_t[1]',\n" --"[zmq.SNDBUF] = 'uint64_t[1]',\n" --"[zmq.RCVBUF] = 'uint64_t[1]',\n" --"[zmq.RCVMORE] = 'int64_t[1]',\n" --"[zmq.FD] = 'int[1]',\n" --"[zmq.EVENTS] = 'uint32_t[1]',\n" --"[zmq.TYPE] = 'int[1]',\n" --"[zmq.LINGER] = 'int[1]',\n" --"[zmq.RECONNECT_IVL] = 'int[1]',\n" --"[zmq.BACKLOG] = 'int[1]',\n" --"}\n" --"local option_len = {}\n" --"local option_tmps = {}\n" --"for k,v in pairs(option_types) do\n" --" if v ~= 'string' then\n" --" option_len[k] = ffi.sizeof(v)\n" --" option_tmps[k] = ffi.new(v, 0)\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_connect1)\n" - " end\n" -+" return true\n" -+"end\n" -+"\n" -+"local option_gets = {}\n" -+"local option_sets = {}\n" -+"\n" -+"do\n" -+" local opt_name\n" -+" local methods = _meth.ZMQ_Socket\n" -+" setmetatable(option_gets,{__index = function(tab,opt)\n" -+" local opt_name = opt_name[opt]\n" -+" if not opt_name then return nil end\n" -+" local method = methods[opt_name]\n" -+" rawset(tab, opt, method)\n" -+" return method\n" -+" end})\n" -+" setmetatable(option_sets,{__index = function(tab,opt)\n" -+" local opt_name = opt_name[opt]\n" -+" if not opt_name then return nil end\n" -+" local method = methods['set_' .. opt_name] or methods[opt_name]\n" -+" rawset(tab, opt, method)\n" -+" return method\n" -+" end})\n" -+" opt_name = {\n" -+" [1] = 'hwm',\n" -+" [3] = 'swap',\n" -+" [4] = 'affinity',\n" -+" [5] = 'identity',\n" -+" [6] = 'subscribe',\n" -+" [7] = 'unsubscribe',\n" -+" [8] = 'rate',\n" -+" [9] = 'recovery_ivl',\n" -+" [10] = 'mcast_loop',\n" -+" [11] = 'sndbuf',\n" -+" [12] = 'rcvbuf',\n" -+" [13] = 'rcvmore',\n" -+" [14] = 'fd',\n" -+" [15] = 'events',\n" -+" [16] = 'type',\n" -+" [17] = 'linger',\n" -+" [18] = 'reconnect_ivl',\n" -+" [19] = 'backlog',\n" -+" [20] = 'recovery_ivl_msec',\n" -+" [21] = 'reconnect_ivl_max',\n" -+" [27] = 'rcvtimeo',\n" -+" [28] = 'sndtimeo',\n" -+" [22] = 'maxmsgsize',\n" -+" [23] = 'sndhwm',\n" -+" [24] = 'rcvhwm',\n" -+" [25] = 'multicast_hops',\n" -+" [31] = 'ipv4only',\n" -+"}\n" - "end\n" - "\n" - "\n" - "-- method: setopt\n" - "function _meth.ZMQ_Socket.setopt(self, opt2, val3)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" --" \n" --" local err1\n" --" local ctype = option_types[opt2]\n" --" local tval\n" --" local tval_len = 0\n" --" if ctype == 'string' then\n" --" tval = tostring(val3)\n" --" tval_len = #val3\n" -+" \n" -+" \n" -+" local err1 = 0\n" -+" local set = option_sets[opt2]\n" -+" if set then\n" -+" return set(self,val3)\n" - " else\n" --" tval = option_tmps[opt2]\n" --" tval[0] = val3\n" --" tval_len = option_len[opt2]\n" -+" error(\"Invalid socket option.\")\n" - " end\n" --" err1 = C.zmq_setsockopt(this1, opt2, tval, tval_len)\n" - "\n" - " -- check for error.\n" --" local err1_err\n" - " if (-1 == err1) then\n" --" err1_err = error_code__ZMQ_Error__push(err1)\n" --" err1 = nil\n" --" else\n" --" err1 = true\n" -+" return nil, error_code__ZMQ_Error__push(err1)\n" - " end\n" --" return err1, err1_err\n" -+" return true\n" - "end\n" - "\n" - "local tmp_val_len = ffi.new('size_t[1]', 4)\n" - "\n" - "-- method: getopt\n" - "function _meth.ZMQ_Socket.getopt(self, opt2)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" -+" \n" - " \n" - " local val1\n" --" local err2\n" --" local ctype = option_types[opt2]\n" --" local val\n" --" local val_len = tmp_val_len\n" --" if ctype == 'string' then\n" --" val_len[0] = 255\n" --" val = ffi.new('uint8_t[?]', val_len[0])\n" --" ffi.fill(val, val_len[0])\n" -+" local err2 = 0\n" -+" local get = option_gets[opt2]\n" -+" if get then\n", /* ----- CUT ----- */ -+" return get(self)\n" - " else\n" --" val = option_tmps[opt2]\n" --" val[0] = 0\n" --" val_len[0] = option_len[opt2]\n" --" end\n" --" err2 = C.zmq_getsockopt(this1, opt2, val, val_len)\n" --" if err2 == 0 then\n" --" if ctype == 'string' then\n" --" val_len = val_len[0]\n" --" return ffi.string(val, val_len)\n" --" else\n" --" return tonumber(val[0])\n" --" end\n" -+" error(\"Invalid socket option.\")\n" - " end\n" - "\n" --" err2 = error_code__ZMQ_Error__push(err2)\n" --" return val1, err2\n" --"end\n" --"\n" --"-- temp. values for 'events' function.\n" --"local events_tmp = ffi.new('uint32_t[1]', 0)\n" --"local events_tmp_size = ffi.sizeof('uint32_t')\n" --"local events_tmp_len = ffi.new('size_t[1]', events_tmp_size)\n" --"local ZMQ_EVENTS = _M.EVENTS\n" --"\n" --"-- method: events\n" --"function _meth.ZMQ_Socket.events(self)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" --" local events1\n" --" local err2\n" --" events_tmp_len[0] = events_tmp_size\n" --" err2 = C.zmq_getsockopt(this1, ZMQ_EVENTS, events_tmp, events_tmp_len);\n" --" events1 = events_tmp[0]\n" --"\n" --" if not (-1 == err2) then\n" --" events1 = events1\n" --" else\n" --" events1 = nil\n" --" end\n" --" err2 = error_code__ZMQ_Error__push(err2)\n" --" return events1, err2\n" -+" return val1\n" - "end\n" - "\n" - "-- method: send_msg\n" - "function _meth.ZMQ_Socket.send_msg(self, msg2, flags3)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" --" msg2 = obj_type_zmq_msg_t_check(msg2)\n" --" flags3 = flags3 or 0\n" --" local rc_zmq_send1\n" --" rc_zmq_send1 = C.zmq_send(this1, msg2, flags3)\n" -+" \n" -+" \n" -+" flags3 = flags3 or 0\n" -+" local rc_zmq_sendmsg1 = 0\n" -+" rc_zmq_sendmsg1 = C.zmq_sendmsg(self, msg2, flags3)\n" - " -- check for error.\n" --" local rc_zmq_send1_err\n" --" if (-1 == rc_zmq_send1) then\n" --" rc_zmq_send1_err = error_code__ZMQ_Error__push(rc_zmq_send1)\n" --" rc_zmq_send1 = nil\n" --" else\n" --" rc_zmq_send1 = true\n" -+" if (-1 == rc_zmq_sendmsg1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_sendmsg1)\n" - " end\n" --" return rc_zmq_send1, rc_zmq_send1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: send\n" - "function _meth.ZMQ_Socket.send(self, data2, flags3)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" -+" \n" - " local data_len2 = #data2\n" --" flags3 = flags3 or 0\n" --" local err1\n" --" err1 = simple_zmq_send(this1, data2, data_len2, flags3);\n" --"\n" -+" flags3 = flags3 or 0\n" -+" local rc_simple_zmq_send1 = 0\n" -+" rc_simple_zmq_send1 = Cmod.simple_zmq_send(self, data2, data_len2, flags3)\n" - " -- check for error.\n" --" local err1_err\n" --" if (-1 == err1) then\n" --" err1_err = error_code__ZMQ_Error__push(err1)\n" --" err1 = nil\n" --" else\n" --" err1 = true\n" -+" if (-1 == rc_simple_zmq_send1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_simple_zmq_send1)\n" - " end\n" --" return err1, err1_err\n" -+" return true\n" - "end\n" - "\n" - "-- method: recv_msg\n" - "function _meth.ZMQ_Socket.recv_msg(self, msg2, flags3)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" --" msg2 = obj_type_zmq_msg_t_check(msg2)\n" --" flags3 = flags3 or 0\n" --" local rc_zmq_recv1\n" --" rc_zmq_recv1 = C.zmq_recv(this1, msg2, flags3)\n" -+" \n" -+" \n" -+" flags3 = flags3 or 0\n" -+" local rc_zmq_recvmsg1 = 0\n" -+" rc_zmq_recvmsg1 = C.zmq_recvmsg(self, msg2, flags3)\n" - " -- check for error.\n" --" local rc_zmq_recv1_err\n" --" if (-1 == rc_zmq_recv1) then\n" --" rc_zmq_recv1_err = error_code__ZMQ_Error__push(rc_zmq_recv1)\n" --" rc_zmq_recv1 = nil\n" --" else\n" --" rc_zmq_recv1 = true\n" -+" if (-1 == rc_zmq_recvmsg1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_recvmsg1)\n" - " end\n" --" return rc_zmq_recv1, rc_zmq_recv1_err\n" -+" return true\n" - "end\n" - "\n" - "local tmp_msg = ffi.new('zmq_msg_t')\n" - "\n" - "-- method: recv\n" - "function _meth.ZMQ_Socket.recv(self, flags2)\n" --" local this1 = obj_type_ZMQ_Socket_check(self)\n" --" flags2 = flags2 or 0\n" -+" \n" -+" flags2 = flags2 or 0\n" - " local data_len1 = 0\n" - " local data1\n" --" local err2\n" -+" local err2 = 0\n" - " local msg = tmp_msg\n" - " -- initialize blank message.\n" - " if C.zmq_msg_init(msg) < 0 then\n" -@@ -1658,1106 +2772,3462 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" - " end\n" - "\n" - " -- receive message\n" --" err2 = C.zmq_recv(this1, msg, flags2)\n" --" if 0 == err2 then\n" -+" err2 = C.zmq_recvmsg(self, msg, flags2)\n" -+" if err2 >= 0 then\n" - " local data = ffi.string(C.zmq_msg_data(msg), C.zmq_msg_size(msg))\n" - " -- close message\n" - " C.zmq_msg_close(msg)\n" - " return data\n" - " end\n" - "\n" --" if not (-1 == err2) then\n" --" data1 = ((nil ~= data1) and ffi.string(data1,data_len1))\n" --" else\n" --" data1 = nil\n" -+" if (-1 == err2) then\n" -+" return nil,error_code__ZMQ_Error__push(err2)\n" - " end\n" --" err2 = error_code__ZMQ_Error__push(err2)\n" - " -- close message\n" - " C.zmq_msg_close(msg)\n" - "\n" --" return data1, err2\n" -+" return ffi_string_len(data1,data_len1)\n" - "end\n" - "\n" --"-- End \"ZMQ_Socket\" FFI interface\n" --"\n" --"\n" --"-- Start \"ZMQ_Poller\" FFI interface\n" --"-- method: poll\n" --"function _meth.ZMQ_Poller.poll(self, timeout2)\n" --" local this1 = obj_type_ZMQ_Poller_check(self)\n" -+"do\n" -+" local hwm_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: hwm\n" -+"if (_meth.ZMQ_Socket.hwm) then\n" -+"function _meth.ZMQ_Socket.hwm(self)\n" - " \n" --" local err1\n" --" -- poll for events\n" --" err1 = poller_poll(this1, timeout2)\n" --" if(err1 > 0) then\n" --" this1.next = 0\n" --" else\n" --" this1.next = -1\n" --" end\n" -+" local value1 = hwm_value_tmp\n" -+" local rc_lzmq_socket_hwm2 = 0\n" -+" rc_lzmq_socket_hwm2 = Cmod.lzmq_socket_hwm(self, value1)\n" -+" if (-1 == rc_lzmq_socket_hwm2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_hwm2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" - "\n" -+"-- method: set_hwm\n" -+"if (_meth.ZMQ_Socket.set_hwm) then\n" -+"function _meth.ZMQ_Socket.set_hwm(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_hwm1 = 0\n" -+" rc_lzmq_socket_set_hwm1 = Cmod.lzmq_socket_set_hwm(self, value2)\n" - " -- check for error.\n" --" local err1_err\n" --" if (-1 == err1) then\n" --" err1_err = error_code__ZMQ_Error__push(err1)\n" --" err1 = nil\n" --" else\n" --" err1 = true\n" --" end\n" --" return err1, err1_err\n" --"end\n" --"\n" --"-- method: next_revents\n" --"function _meth.ZMQ_Poller.next_revents(self)\n" --" local this1 = obj_type_ZMQ_Poller_check(self)\n" --" local sock1\n" --" local revents2\n" --" local sock\n" --" local idx = this1.next\n" --" if (idx < 0) then return nil, -1 end\n" --" local count = this1.count\n" --" -- find next item with pending events.\n" --" while (idx < count and this1.items[idx].revents == 0) do\n" --" idx = idx + 1\n" --" if (idx >= count) then\n" --" idx = -1\n" --" break\n" --" end\n" --" end\n" --" -- did we find a pending event?\n" --" if(idx >= 0) then\n" --" -- push the event's sock/fd.\n" --" if(this1.items[idx].socket ~= nil) then\n" --" sock = obj_type_ZMQ_Socket_push(this1.items[idx].socket, 0)\n" --" else\n" --" sock = tonumber(this1.items[idx].fd)\n" --" end\n" --" revents2 = this1.items[idx].revents\n" --" -- is this the last event.\n" --" idx = idx + 1\n" --" if (idx >= count) then\n" --" idx = -1\n" --" end\n" --" this1.next = idx\n" --" return sock, revents2\n" --" end\n" --" this1.next = idx\n" --"\n" --" revents2 = revents2\n" --" return sock1, revents2\n" -+" if (-1 == rc_lzmq_socket_set_hwm1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_hwm1)\n" -+" end\n" -+" return true\n" -+"end\n" - "end\n" - "\n" --"-- method: count\n" --"function _meth.ZMQ_Poller.count(self)\n" --" local this1 = obj_type_ZMQ_Poller_check(self)\n" --" local count1\n" --" count1 = this1.count;\n" --"\n" --" count1 = count1\n" --" return count1\n" -+"do\n" -+" local swap_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: swap\n" -+"if (_meth.ZMQ_Socket.swap) then\n" -+"function _meth.ZMQ_Socket.swap(self)\n" -+" \n" -+" local value1 = swap_value_tmp\n" -+" local rc_lzmq_socket_swap2 = 0\n" -+" rc_lzmq_socket_swap2 = Cmod.lzmq_socket_swap(self, value1)\n" -+" if (-1 == rc_lzmq_socket_swap2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_swap2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" - "end\n" - "\n" --"-- End \"ZMQ_Poller\" FFI interface\n" -+"-- method: set_swap\n" -+"if (_meth.ZMQ_Socket.set_swap) then\n" -+"function _meth.ZMQ_Socket.set_swap(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_swap1 = 0\n" -+" rc_lzmq_socket_set_swap1 = Cmod.lzmq_socket_set_swap(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_swap1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_swap1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" - "\n" -+"do\n" -+" local affinity_value_tmp = ffi.new(\"uint64_t[1]\")\n" -+"-- method: affinity\n" -+"if (_meth.ZMQ_Socket.affinity) then\n" -+"function _meth.ZMQ_Socket.affinity(self)\n" -+" \n" -+" local value1 = affinity_value_tmp\n" -+" local rc_lzmq_socket_affinity2 = 0\n" -+" rc_lzmq_socket_affinity2 = Cmod.lzmq_socket_affinity(self, value1)\n" -+" if (-1 == rc_lzmq_socket_affinity2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_affinity2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" - "\n" --"-- Start \"ZMQ_Ctx\" FFI interface\n" --"-- method: term\n" --"function _meth.ZMQ_Ctx.term(self)\n" --" local this1,this_flags1 = obj_type_ZMQ_Ctx_delete(self)\n" --" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" --" local rc_zmq_term1\n" --" rc_zmq_term1 = C.zmq_term(this1)\n" -+"-- method: set_affinity\n" -+"if (_meth.ZMQ_Socket.set_affinity) then\n" -+"function _meth.ZMQ_Socket.set_affinity(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_affinity1 = 0\n" -+" rc_lzmq_socket_set_affinity1 = Cmod.lzmq_socket_set_affinity(self, value2)\n" - " -- check for error.\n" --" local rc_zmq_term1_err\n" --" if (-1 == rc_zmq_term1) then\n" --" rc_zmq_term1_err = error_code__ZMQ_Error__push(rc_zmq_term1)\n" --" rc_zmq_term1 = nil\n" --" else\n" --" rc_zmq_term1 = true\n" -+" if (-1 == rc_lzmq_socket_set_affinity1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_affinity1)\n" - " end\n" --" return rc_zmq_term1, rc_zmq_term1_err\n" -+" return true\n" -+"end\n" - "end\n" - "\n" --"-- method: socket\n" --"function _meth.ZMQ_Ctx.socket(self, type2)\n" --" local this1 = obj_type_ZMQ_Ctx_check(self)\n" -+"-- method: identity\n" -+"if (_meth.ZMQ_Socket.identity) then\n" -+"function _meth.ZMQ_Socket.identity(self)\n" - " \n" --" local rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN\n" --" local rc_zmq_socket1\n" --" rc_zmq_socket1 = C.zmq_socket(this1, type2)\n" --" local rc_zmq_socket1_err\n" --" if (nil == rc_zmq_socket1) then\n" --" rc_zmq_socket1_err = get_zmq_strerror()\n" --" else\n" --" rc_zmq_socket1 = obj_type_ZMQ_Socket_push(rc_zmq_socket1, rc_zmq_socket_flags1)\n" -+" local value_len1 = 0\n" -+" local value1\n" -+" local rc_lzmq_socket_identity2 = 0\n" -+" rc_lzmq_socket_identity2 = Cmod.lzmq_socket_identity(self, value1, value_len1)\n" -+" if (-1 == rc_lzmq_socket_identity2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_identity2)\n" - " end\n" --" return rc_zmq_socket1, rc_zmq_socket1_err\n" -+" return ffi_string_len(value1,value_len1)\n" -+"end\n" - "end\n" - "\n" --"-- End \"ZMQ_Ctx\" FFI interface\n" -+"-- method: set_identity\n" -+"if (_meth.ZMQ_Socket.set_identity) then\n" -+"function _meth.ZMQ_Socket.set_identity(self, value2)\n" -+" \n" -+" local value_len2 = #value2\n" -+" local rc_lzmq_socket_set_identity1 = 0\n" -+" rc_lzmq_socket_set_identity1 = Cmod.lzmq_socket_set_identity(self, value2, value_len2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_identity1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_identity1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" - "\n" -+"-- method: subscribe\n" -+"if (_meth.ZMQ_Socket.subscribe) then\n" -+"function _meth.ZMQ_Socket.subscribe(self, value2)\n" -+" \n" -+" local value_len2 = #value2\n" -+" local rc_lzmq_socket_subscribe1 = 0\n" -+" rc_lzmq_socket_subscribe1 = Cmod.lzmq_socket_subscribe(self, value2, value_len2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_subscribe1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_subscribe1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" - "\n" --"-- Start \"ZMQ_StopWatch\" FFI interface\n" --"-- method: start\n" --"function _pub.ZMQ_StopWatch.start()\n" --" local this_flags1 = OBJ_UDATA_FLAG_OWN\n" --" local this1\n" --" this1 = C.zmq_stopwatch_start()\n" --" this1 = obj_type_ZMQ_StopWatch_push(this1, this_flags1)\n" --" return this1\n" -+"-- method: unsubscribe\n" -+"if (_meth.ZMQ_Socket.unsubscribe) then\n" -+"function _meth.ZMQ_Socket.unsubscribe(self, value2)\n" -+" \n" -+" local value_len2 = #value2\n" -+" local rc_lzmq_socket_unsubscribe1 = 0\n" -+" rc_lzmq_socket_unsubscribe1 = Cmod.lzmq_socket_unsubscribe(self, value2, value_len2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_unsubscribe1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_unsubscribe1)\n" -+" end\n" -+" return true\n" -+"end\n" - "end\n" - "\n" --"-- method: stop\n" --"function _meth.ZMQ_StopWatch.stop(self)\n" --" local this1,this_flags1 = obj_type_ZMQ_StopWatch_delete(self)\n" --" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" --" local usecs1\n" --" usecs1 = C.zmq_stopwatch_stop(this1)\n" --" usecs1 = tonumber(usecs1)\n" --" return usecs1\n" -+"do\n" -+" local rate_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: rate\n" -+"if (_meth.ZMQ_Socket.rate) then\n" -+"function _meth.ZMQ_Socket.rate(self)\n" -+" \n" -+" local value1 = rate_value_tmp\n" -+" local rc_lzmq_socket_rate2 = 0\n" -+" rc_lzmq_socket_rate2 = Cmod.lzmq_socket_rate(self, value1)\n" -+" if (-1 == rc_lzmq_socket_rate2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rate2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" - "end\n" - "\n" --"-- End \"ZMQ_StopWatch\" FFI interface\n" -+"-- method: set_rate\n" -+"if (_meth.ZMQ_Socket.set_rate) then\n" -+"function _meth.ZMQ_Socket.set_rate(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_rate1 = 0\n" -+" rc_lzmq_socket_set_rate1 = Cmod.lzmq_socket_set_rate(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_rate1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rate1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" - "\n" --"-- method: init\n" --"function _pub.zmq.init(io_threads1)\n" -+"do\n" -+" local recovery_ivl_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: recovery_ivl\n" -+"if (_meth.ZMQ_Socket.recovery_ivl) then\n" -+"function _meth.ZMQ_Socket.recovery_ivl(self)\n" - " \n" --" local rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN\n" --" local rc_zmq_init1\n" --" rc_zmq_init1 = C.zmq_init(io_threads1)\n" --" local rc_zmq_init1_err\n" --" if (nil == rc_zmq_init1) then\n" --" rc_zmq_init1_err = get_zmq_strerror()\n" --" else\n" --" rc_zmq_init1 = obj_type_ZMQ_Ctx_push(rc_zmq_init1, rc_zmq_init_flags1)\n" -+" local value1 = recovery_ivl_value_tmp\n" -+" local rc_lzmq_socket_recovery_ivl2 = 0\n" -+" rc_lzmq_socket_recovery_ivl2 = Cmod.lzmq_socket_recovery_ivl(self, value1)\n" -+" if (-1 == rc_lzmq_socket_recovery_ivl2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_recovery_ivl2)\n" - " end\n" --" return rc_zmq_init1, rc_zmq_init1_err\n" -+" return value1[0]\n" -+"end\n" -+"end\n" - "end\n" - "\n" --"-- method: init_ctx\n" --"function _pub.zmq.init_ctx(ptr1)\n" --" local ctx1\n" --" local p_type = type(ptr1)\n" --" if p_type == 'userdata' then\n" --" ctx1 = ffi.cast('void *', ptr1);\n" --" elseif p_type == 'cdata' then\n" --" ctx1 = ptr1;\n" --" else\n" --" return error(\"expected lightuserdata/cdata\");\n" --" end\n" -+"-- method: set_recovery_ivl\n" -+"if (_meth.ZMQ_Socket.set_recovery_ivl) then\n" -+"function _meth.ZMQ_Socket.set_recovery_ivl(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_recovery_ivl1 = 0\n" -+" rc_lzmq_socket_set_recovery_ivl1 = Cmod.lzmq_socket_set_recovery_ivl(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_recovery_ivl1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_recovery_ivl1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" - "\n" --" local ctx1_err\n" --" if (nil == ctx1) then\n" --" ctx1_err = get_zmq_strerror()\n" --" else\n" --" ctx1 = obj_type_ZMQ_Ctx_push(ctx1, 0)\n" -+"do\n" -+" local mcast_loop_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: mcast_loop\n" -+"if (_meth.ZMQ_Socket.mcast_loop) then\n" -+"function _meth.ZMQ_Socket.mcast_loop(self)\n" -+" \n" -+" local value1 = mcast_loop_value_tmp\n" -+" local rc_lzmq_socket_mcast_loop2 = 0\n" -+" rc_lzmq_socket_mcast_loop2 = Cmod.lzmq_socket_mcast_loop(self, value1)\n" -+" if (-1 == rc_lzmq_socket_mcast_loop2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_mcast_loop2)\n" - " end\n" --" return ctx1, ctx1_err\n" -+" return value1[0]\n" -+"end\n" -+"end\n" - "end\n" - "\n" --"-- method: device\n" --"function _pub.zmq.device(device1, insock2, outsock3)\n" -+"-- method: set_mcast_loop\n" -+"if (_meth.ZMQ_Socket.set_mcast_loop) then\n" -+"function _meth.ZMQ_Socket.set_mcast_loop(self, value2)\n" - " \n" --" insock2 = obj_type_ZMQ_Socket_check(insock2)\n" --" outsock3 = obj_type_ZMQ_Socket_check(outsock3)\n" --" local rc_zmq_device1\n" --" rc_zmq_device1 = C.zmq_device(device1, insock2, outsock3)\n" -+" \n" -+" local rc_lzmq_socket_set_mcast_loop1 = 0\n" -+" rc_lzmq_socket_set_mcast_loop1 = Cmod.lzmq_socket_set_mcast_loop(self, value2)\n" - " -- check for error.\n" --" local rc_zmq_device1_err\n" --" if (-1 == rc_zmq_device1) then\n" --" rc_zmq_device1_err = error_code__ZMQ_Error__push(rc_zmq_device1)\n" --" rc_zmq_device1 = nil\n" --" else\n" --" rc_zmq_device1 = true\n" -+" if (-1 == rc_lzmq_socket_set_mcast_loop1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_mcast_loop1)\n" - " end\n" --" return rc_zmq_device1, rc_zmq_device1_err\n" -+" return true\n" -+"end\n" - "end\n" - "\n" --"-- method: stopwatch_start\n" --"function _pub.zmq.stopwatch_start()\n" --" local rc_zmq_stopwatch_start_flags1 = OBJ_UDATA_FLAG_OWN\n" --" local rc_zmq_stopwatch_start1\n" --" rc_zmq_stopwatch_start1 = C.zmq_stopwatch_start()\n" --" rc_zmq_stopwatch_start1 = obj_type_ZMQ_StopWatch_push(rc_zmq_stopwatch_start1, rc_zmq_stopwatch_start_flags1)\n" --" return rc_zmq_stopwatch_start1\n" -+"do\n" -+" local sndbuf_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: sndbuf\n" -+"if (_meth.ZMQ_Socket.sndbuf) then\n" -+"function _meth.ZMQ_Socket.sndbuf(self)\n" -+" \n" -+" local value1 = sndbuf_value_tmp\n" -+" local rc_lzmq_socket_sndbuf2 = 0\n" -+" rc_lzmq_socket_sndbuf2 = Cmod.lzmq_socket_sndbuf(self, value1)\n" -+" if (-1 == rc_lzmq_socket_sndbuf2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndbuf2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" - "end\n" - "\n" --"-- method: sleep\n" --"function _pub.zmq.sleep(seconds_1)\n" -+"-- method: set_sndbuf\n" -+"if (_meth.ZMQ_Socket.set_sndbuf) then\n" -+"function _meth.ZMQ_Socket.set_sndbuf(self, value2)\n" - " \n" --" C.zmq_sleep(seconds_1)\n" --" return \n" -+" \n" -+" local rc_lzmq_socket_set_sndbuf1 = 0\n" -+" rc_lzmq_socket_set_sndbuf1 = Cmod.lzmq_socket_set_sndbuf(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_sndbuf1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndbuf1)\n" -+" end\n" -+" return true\n" -+"end\n" - "end\n" - "\n" --""; -- --/* detect zmq version >= 2.1.0 */ --#define VERSION_2_1 0 --#if defined(ZMQ_VERSION) --#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0)) --#undef VERSION_2_1 --#define VERSION_2_1 1 -+"do\n" -+" local rcvbuf_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: rcvbuf\n" -+"if (_meth.ZMQ_Socket.rcvbuf) then\n" -+"function _meth.ZMQ_Socket.rcvbuf(self)\n" -+" \n" -+" local value1 = rcvbuf_value_tmp\n" -+" local rc_lzmq_socket_rcvbuf2 = 0\n" -+" rc_lzmq_socket_rcvbuf2 = Cmod.lzmq_socket_rcvbuf(self, value1)\n" -+" if (-1 == rc_lzmq_socket_rcvbuf2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvbuf2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_rcvbuf\n" -+"if (_meth.ZMQ_Socket.set_rcvbuf) then\n" -+"function _meth.ZMQ_Socket.set_rcvbuf(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_rcvbuf1 = 0\n" -+" rc_lzmq_socket_set_rcvbuf1 = Cmod.lzmq_socket_set_rcvbuf(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_rcvbuf1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvbuf1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local rcvmore_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: rcvmore\n" -+"if (_meth.ZMQ_Socket.rcvmore) then\n" -+"function _meth.ZMQ_Socket.rcvmore(self)\n" -+" \n" -+" local value1 = rcvmore_value_tmp\n" -+" local rc_lzmq_socket_rcvmore2 = 0\n" -+" rc_lzmq_socket_rcvmore2 = Cmod.lzmq_socket_rcvmore(self, value1)\n" -+" if (-1 == rc_lzmq_socket_rcvmore2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvmore2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local fd_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: fd\n" -+"if (_meth.ZMQ_Socket.fd) then\n" -+"function _meth.ZMQ_Socket.fd(self)\n" -+" \n" -+" local value1 = fd_value_tmp\n" -+" local rc_lzmq_socket_fd2 = 0\n" -+" rc_lzmq_socket_fd2 = Cmod.lzmq_socket_fd(self, value1)\n" -+" if (-1 == rc_lzmq_socket_fd2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_fd2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local events_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: events\n" -+"if (_meth.ZMQ_Socket.events) then\n" -+"function _meth.ZMQ_Socket.events(self)\n" -+" \n" -+" local value1 = events_value_tmp\n" -+" local rc_lzmq_socket_events2 = 0\n" -+" rc_lzmq_socket_events2 = Cmod.lzmq_socket_events(self, value1)\n" -+" if (-1 == rc_lzmq_socket_events2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_events2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local type_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: type\n" -+"if (_meth.ZMQ_Socket.type) then\n" -+"function _meth.ZMQ_Socket.type(self)\n" -+" \n" -+" local value1 = type_value_tmp\n" -+" local rc_lzmq_socket_type2 = 0\n" -+" rc_lzmq_socket_type2 = Cmod.lzmq_socket_type(self, value1)\n" -+" if (-1 == rc_lzmq_socket_type2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_type2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local linger_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: linger\n" -+"if (_meth.ZMQ_Socket.linger) then\n" -+"function _meth.ZMQ_Socket.linger(self)\n" -+" \n" -+" local value1 = linger_value_tmp\n" -+" local rc_lzmq_socket_linger2 = 0\n" -+" rc_lzmq_socket_linger2 = Cmod.lzmq_socket_linger(self, value1)\n" -+" if (-1 == rc_lzmq_socket_linger2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_linger2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_linger\n" -+"if (_meth.ZMQ_Socket.set_linger) then\n" -+"function _meth.ZMQ_Socket.set_linger(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_linger1 = 0\n" -+" rc_lzmq_socket_set_linger1 = Cmod.lzmq_socket_set_linger(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_linger1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_linger1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local reconnect_ivl_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: reconnect_ivl\n" -+"if (_meth.ZMQ_Socket.reconnect_ivl) then\n" -+"function _meth.ZMQ_Socket.reconnect_ivl(self)\n" -+" \n" -+" local value1 = reconnect_ivl_value_tmp\n" -+" local rc_lzmq_socket_reconnect_ivl2 = 0\n" -+" rc_lzmq_socket_reconnect_ivl2 = Cmod.lzmq_socket_reconnect_ivl(self, value1)\n" -+" if (-1 == rc_lzmq_socket_reconnect_ivl2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_reconnect_ivl2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_reconnect_ivl\n" -+"if (_meth.ZMQ_Socket.set_reconnect_ivl) then\n" -+"function _meth.ZMQ_Socket.set_reconnect_ivl(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_reconnect_ivl1 = 0\n" -+" rc_lzmq_socket_set_reconnect_ivl1 = Cmod.lzmq_socket_set_reconnect_ivl(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_reconnect_ivl1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_reconnect_ivl1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local backlog_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: backlog\n" -+"if (_meth.ZMQ_Socket.backlog) then\n" -+"function _meth.ZMQ_Socket.backlog(self)\n" -+" \n" -+" local value1 = backlog_value_tmp\n" -+" local rc_lzmq_socket_backlog2 = 0\n" -+" rc_lzmq_socket_backlog2 = Cmod.lzmq_socket_backlog(self, value1)\n" -+" if (-1 == rc_lzmq_socket_backlog2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_backlog2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_backlog\n" -+"if (_meth.ZMQ_Socket.set_backlog) then\n" -+"function _meth.ZMQ_Socket.set_backlog(self, value2)\n" -+" \n" -+" \n", /* ----- CUT ----- */ -+" local rc_lzmq_socket_set_backlog1 = 0\n" -+" rc_lzmq_socket_set_backlog1 = Cmod.lzmq_socket_set_backlog(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_backlog1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_backlog1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local recovery_ivl_msec_value_tmp = ffi.new(\"int64_t[1]\")\n" -+"-- method: recovery_ivl_msec\n" -+"if (_meth.ZMQ_Socket.recovery_ivl_msec) then\n" -+"function _meth.ZMQ_Socket.recovery_ivl_msec(self)\n" -+" \n" -+" local value1 = recovery_ivl_msec_value_tmp\n" -+" local rc_lzmq_socket_recovery_ivl_msec2 = 0\n" -+" rc_lzmq_socket_recovery_ivl_msec2 = Cmod.lzmq_socket_recovery_ivl_msec(self, value1)\n" -+" if (-1 == rc_lzmq_socket_recovery_ivl_msec2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_recovery_ivl_msec2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_recovery_ivl_msec\n" -+"if (_meth.ZMQ_Socket.set_recovery_ivl_msec) then\n" -+"function _meth.ZMQ_Socket.set_recovery_ivl_msec(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_recovery_ivl_msec1 = 0\n" -+" rc_lzmq_socket_set_recovery_ivl_msec1 = Cmod.lzmq_socket_set_recovery_ivl_msec(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_recovery_ivl_msec1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_recovery_ivl_msec1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local reconnect_ivl_max_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: reconnect_ivl_max\n" -+"if (_meth.ZMQ_Socket.reconnect_ivl_max) then\n" -+"function _meth.ZMQ_Socket.reconnect_ivl_max(self)\n" -+" \n" -+" local value1 = reconnect_ivl_max_value_tmp\n" -+" local rc_lzmq_socket_reconnect_ivl_max2 = 0\n" -+" rc_lzmq_socket_reconnect_ivl_max2 = Cmod.lzmq_socket_reconnect_ivl_max(self, value1)\n" -+" if (-1 == rc_lzmq_socket_reconnect_ivl_max2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_reconnect_ivl_max2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_reconnect_ivl_max\n" -+"if (_meth.ZMQ_Socket.set_reconnect_ivl_max) then\n" -+"function _meth.ZMQ_Socket.set_reconnect_ivl_max(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_reconnect_ivl_max1 = 0\n" -+" rc_lzmq_socket_set_reconnect_ivl_max1 = Cmod.lzmq_socket_set_reconnect_ivl_max(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_reconnect_ivl_max1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_reconnect_ivl_max1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local maxmsgsize_value_tmp = ffi.new(\"int64_t[1]\")\n" -+"-- method: maxmsgsize\n" -+"if (_meth.ZMQ_Socket.maxmsgsize) then\n" -+"function _meth.ZMQ_Socket.maxmsgsize(self)\n" -+" \n" -+" local value1 = maxmsgsize_value_tmp\n" -+" local rc_lzmq_socket_maxmsgsize2 = 0\n" -+" rc_lzmq_socket_maxmsgsize2 = Cmod.lzmq_socket_maxmsgsize(self, value1)\n" -+" if (-1 == rc_lzmq_socket_maxmsgsize2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_maxmsgsize2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_maxmsgsize\n" -+"if (_meth.ZMQ_Socket.set_maxmsgsize) then\n" -+"function _meth.ZMQ_Socket.set_maxmsgsize(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_maxmsgsize1 = 0\n" -+" rc_lzmq_socket_set_maxmsgsize1 = Cmod.lzmq_socket_set_maxmsgsize(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_maxmsgsize1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_maxmsgsize1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local sndhwm_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: sndhwm\n" -+"if (_meth.ZMQ_Socket.sndhwm) then\n" -+"function _meth.ZMQ_Socket.sndhwm(self)\n" -+" \n" -+" local value1 = sndhwm_value_tmp\n" -+" local rc_lzmq_socket_sndhwm2 = 0\n" -+" rc_lzmq_socket_sndhwm2 = Cmod.lzmq_socket_sndhwm(self, value1)\n" -+" if (-1 == rc_lzmq_socket_sndhwm2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndhwm2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_sndhwm\n" -+"if (_meth.ZMQ_Socket.set_sndhwm) then\n" -+"function _meth.ZMQ_Socket.set_sndhwm(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_sndhwm1 = 0\n" -+" rc_lzmq_socket_set_sndhwm1 = Cmod.lzmq_socket_set_sndhwm(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_sndhwm1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndhwm1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local rcvhwm_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: rcvhwm\n" -+"if (_meth.ZMQ_Socket.rcvhwm) then\n" -+"function _meth.ZMQ_Socket.rcvhwm(self)\n" -+" \n" -+" local value1 = rcvhwm_value_tmp\n" -+" local rc_lzmq_socket_rcvhwm2 = 0\n" -+" rc_lzmq_socket_rcvhwm2 = Cmod.lzmq_socket_rcvhwm(self, value1)\n" -+" if (-1 == rc_lzmq_socket_rcvhwm2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvhwm2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_rcvhwm\n" -+"if (_meth.ZMQ_Socket.set_rcvhwm) then\n" -+"function _meth.ZMQ_Socket.set_rcvhwm(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_rcvhwm1 = 0\n" -+" rc_lzmq_socket_set_rcvhwm1 = Cmod.lzmq_socket_set_rcvhwm(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_rcvhwm1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvhwm1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local multicast_hops_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: multicast_hops\n" -+"if (_meth.ZMQ_Socket.multicast_hops) then\n" -+"function _meth.ZMQ_Socket.multicast_hops(self)\n" -+" \n" -+" local value1 = multicast_hops_value_tmp\n" -+" local rc_lzmq_socket_multicast_hops2 = 0\n" -+" rc_lzmq_socket_multicast_hops2 = Cmod.lzmq_socket_multicast_hops(self, value1)\n" -+" if (-1 == rc_lzmq_socket_multicast_hops2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_multicast_hops2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_multicast_hops\n" -+"if (_meth.ZMQ_Socket.set_multicast_hops) then\n" -+"function _meth.ZMQ_Socket.set_multicast_hops(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_multicast_hops1 = 0\n" -+" rc_lzmq_socket_set_multicast_hops1 = Cmod.lzmq_socket_set_multicast_hops(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_multicast_hops1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_multicast_hops1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local rcvtimeo_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: rcvtimeo\n" -+"if (_meth.ZMQ_Socket.rcvtimeo) then\n" -+"function _meth.ZMQ_Socket.rcvtimeo(self)\n" -+" \n" -+" local value1 = rcvtimeo_value_tmp\n" -+" local rc_lzmq_socket_rcvtimeo2 = 0\n" -+" rc_lzmq_socket_rcvtimeo2 = Cmod.lzmq_socket_rcvtimeo(self, value1)\n" -+" if (-1 == rc_lzmq_socket_rcvtimeo2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvtimeo2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_rcvtimeo\n" -+"if (_meth.ZMQ_Socket.set_rcvtimeo) then\n" -+"function _meth.ZMQ_Socket.set_rcvtimeo(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_rcvtimeo1 = 0\n" -+" rc_lzmq_socket_set_rcvtimeo1 = Cmod.lzmq_socket_set_rcvtimeo(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_rcvtimeo1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvtimeo1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local sndtimeo_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: sndtimeo\n" -+"if (_meth.ZMQ_Socket.sndtimeo) then\n" -+"function _meth.ZMQ_Socket.sndtimeo(self)\n" -+" \n" -+" local value1 = sndtimeo_value_tmp\n" -+" local rc_lzmq_socket_sndtimeo2 = 0\n" -+" rc_lzmq_socket_sndtimeo2 = Cmod.lzmq_socket_sndtimeo(self, value1)\n" -+" if (-1 == rc_lzmq_socket_sndtimeo2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndtimeo2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_sndtimeo\n" -+"if (_meth.ZMQ_Socket.set_sndtimeo) then\n" -+"function _meth.ZMQ_Socket.set_sndtimeo(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_sndtimeo1 = 0\n" -+" rc_lzmq_socket_set_sndtimeo1 = Cmod.lzmq_socket_set_sndtimeo(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_sndtimeo1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndtimeo1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"do\n" -+" local ipv4only_value_tmp = ffi.new(\"int[1]\")\n" -+"-- method: ipv4only\n" -+"if (_meth.ZMQ_Socket.ipv4only) then\n" -+"function _meth.ZMQ_Socket.ipv4only(self)\n" -+" \n" -+" local value1 = ipv4only_value_tmp\n" -+" local rc_lzmq_socket_ipv4only2 = 0\n" -+" rc_lzmq_socket_ipv4only2 = Cmod.lzmq_socket_ipv4only(self, value1)\n" -+" if (-1 == rc_lzmq_socket_ipv4only2) then\n" -+" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_ipv4only2)\n" -+" end\n" -+" return value1[0]\n" -+"end\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: set_ipv4only\n" -+"if (_meth.ZMQ_Socket.set_ipv4only) then\n" -+"function _meth.ZMQ_Socket.set_ipv4only(self, value2)\n" -+" \n" -+" \n" -+" local rc_lzmq_socket_set_ipv4only1 = 0\n" -+" rc_lzmq_socket_set_ipv4only1 = Cmod.lzmq_socket_set_ipv4only(self, value2)\n" -+" -- check for error.\n" -+" if (-1 == rc_lzmq_socket_set_ipv4only1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_ipv4only1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"_push.ZMQ_Socket = obj_type_ZMQ_Socket_push\n" -+"ffi.metatype(\"ZMQ_Socket\", _priv.ZMQ_Socket)\n" -+"-- End \"ZMQ_Socket\" FFI interface\n" -+"\n" -+"\n" -+"-- Start \"ZMQ_Poller\" FFI interface\n" -+"-- method: new\n" -+"function _pub.ZMQ_Poller.new(length1)\n" -+" length1 = length1 or 10\n" -+" local self = ffi.new(\"ZMQ_Poller\")\n" -+" Cmod.poller_init(self, length1)\n" -+" return obj_type_ZMQ_Poller_push(self)\n" -+"end\n" -+"register_default_constructor(_pub,\"ZMQ_Poller\",_pub.ZMQ_Poller.new)\n" -+"\n" -+"-- method: close\n" -+"function _meth.ZMQ_Poller.close(self)\n" -+" local self = obj_type_ZMQ_Poller_delete(self)\n" -+" if not self then return end\n" -+" Cmod.poller_cleanup(self)\n" -+" return \n" -+"end\n" -+"_priv.ZMQ_Poller.__gc = _meth.ZMQ_Poller.close\n" -+"\n" -+"-- method: add\n" -+"function _meth.ZMQ_Poller.add(self, sock2, events3)\n" -+" \n" -+" \n" -+" local idx1 = 0\n" -+" local fd = 0\n" -+" local sock_type = type(sock2)\n" -+" if sock_type == 'cdata' then\n" -+" sock = obj_type_ZMQ_Socket_check(sock2)\n" -+" elseif sock_type == 'number' then\n" -+" fd = sock2\n" -+" else\n" -+" error(\"expected number or ZMQ_Socket\")\n" -+" end\n" -+" idx1 = Cmod.poller_get_free_item(self)\n" -+" local item = self.items[idx1]\n" -+" item.socket = sock\n" -+" item.fd = fd\n" -+" item.events = events3\n" -+"\n" -+" return idx1\n" -+"end\n" -+"\n" -+"-- method: modify\n" -+"function _meth.ZMQ_Poller.modify(self, sock2, events3)\n" -+" \n" -+" \n" -+" local idx1 = 0\n" -+" local fd = 0\n" -+" local sock_type = type(sock2)\n" -+" if sock_type == 'cdata' then\n" -+" sock = obj_type_ZMQ_Socket_check(sock2)\n" -+" -- find sock in items list.\n" -+" idx1 = Cmod.poller_find_sock_item(self, sock)\n" -+" elseif sock_type == 'number' then\n" -+" fd = sock2\n" -+" -- find fd in items list.\n" -+" idx1 = Cmod.poller_find_fd_item(self, fd);\n" -+" else\n" -+" error(\"expected number or ZMQ_Socket\")\n" -+" end\n" -+" if events3 ~= 0 then\n" -+" local item = self.items[idx1]\n" -+" item.socket = sock\n" -+" item.fd = fd\n" -+" item.events = events3\n" -+" else\n" -+" Cmod.poller_remove_item(self, idx1)\n" -+" end\n" -+"\n" -+" return idx1\n" -+"end\n" -+"\n" -+"-- method: remove\n" -+"function _meth.ZMQ_Poller.remove(self, sock2)\n" -+" \n" -+" local idx1 = 0\n" -+" local fd = 0\n" -+" local sock_type = type(sock2)\n" -+" if sock_type == 'cdata' then\n" -+" sock = obj_type_ZMQ_Socket_check(sock2)\n" -+" -- find sock in items list.\n" -+" idx1 = Cmod.poller_find_sock_item(self, sock)\n" -+" elseif sock_type == 'number' then\n" -+" fd = sock2\n" -+" -- find fd in items list.\n" -+" idx1 = Cmod.poller_find_fd_item(self, fd);\n" -+" else\n" -+" error(\"expected number or ZMQ_Socket\")\n" -+" end\n" -+" if idx1 >= 0 then\n" -+" Cmod.poller_remove_item(self, idx1)\n" -+" end\n" -+"\n" -+" return idx1\n" -+"end\n" -+"\n" -+"-- method: poll\n" -+"function _meth.ZMQ_Poller.poll(self, timeout2)\n" -+" \n" -+" \n" -+" local count1 = 0\n" -+" local err2 = 0\n" -+" err2 = Cmod.poller_poll(self, timeout2)\n" -+" if(err2 > 0) then\n" -+" self.next = 0\n" -+" count1 = err2\n" -+" else\n" -+" self.next = -1\n" -+" count1 = 0\n" -+" end\n" -+"\n" -+" if (-1 == err2) then\n" -+" return nil,error_code__ZMQ_Error__push(err2)\n" -+" end\n" -+" return count1\n" -+"end\n" -+"\n" -+"do\n" -+" local next_revents_idx_revents_tmp = ffi.new(\"int[1]\")\n" -+"-- method: next_revents_idx\n" -+"function _meth.ZMQ_Poller.next_revents_idx(self)\n" -+" \n" -+" local idx1 = 0\n" -+" local revents2 = next_revents_idx_revents_tmp\n" -+" idx1 = Cmod.poller_next_revents(self, revents2)\n" -+" return idx1, revents2[0]\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: count\n" -+"function _meth.ZMQ_Poller.count(self)\n" -+" \n" -+" local count1 = 0\n" -+" count1 = self.count;\n" -+"\n" -+" return count1\n" -+"end\n" -+"\n" -+"_push.ZMQ_Poller = obj_type_ZMQ_Poller_push\n" -+"ffi.metatype(\"ZMQ_Poller\", _priv.ZMQ_Poller)\n" -+"-- End \"ZMQ_Poller\" FFI interface\n" -+"\n" -+"\n" -+"-- Start \"ZMQ_Ctx\" FFI interface\n" -+"-- method: term\n" -+"function _meth.ZMQ_Ctx.term(self)\n" -+" local self,this_flags1 = obj_type_ZMQ_Ctx_delete(self)\n" -+" if not self then return end\n" -+" local rc_zmq_term1 = 0\n" -+" rc_zmq_term1 = C.zmq_term(self)\n" -+" -- check for error.\n" -+" if (-1 == rc_zmq_term1) then\n" -+" return nil, error_code__ZMQ_Error__push(rc_zmq_term1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"_priv.ZMQ_Ctx.__gc = _meth.ZMQ_Ctx.term\n" -+"\n" -+"-- method: socket\n" -+"function _meth.ZMQ_Ctx.socket(self, type2)\n" -+" \n" -+" \n" -+" local rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN\n" -+" local rc_zmq_socket1\n" -+" rc_zmq_socket1 = C.zmq_socket(self, type2)\n" -+" if (nil == rc_zmq_socket1) then\n" -+" return nil, get_zmq_strerror()\n" -+" end\n" -+" return obj_type_ZMQ_Socket_push(rc_zmq_socket1, rc_zmq_socket_flags1)\n" -+"end\n" -+"\n" -+"_push.ZMQ_Ctx = obj_type_ZMQ_Ctx_push\n" -+"ffi.metatype(\"ZMQ_Ctx\", _priv.ZMQ_Ctx)\n" -+"-- End \"ZMQ_Ctx\" FFI interface\n" -+"\n" -+"\n" -+"-- Start \"ZMQ_StopWatch\" FFI interface\n" -+"-- method: start\n" -+"function _pub.ZMQ_StopWatch.start()\n" -+" local this_flags1 = OBJ_UDATA_FLAG_OWN\n" -+" local self\n" -+" self = C.zmq_stopwatch_start()\n" -+" return obj_type_ZMQ_StopWatch_push(self, this_flags1)\n" -+"end\n" -+"register_default_constructor(_pub,\"ZMQ_StopWatch\",_pub.ZMQ_StopWatch.start)\n" -+"\n" -+"-- method: stop\n" -+"function _meth.ZMQ_StopWatch.stop(self)\n" -+" local self,this_flags1 = obj_type_ZMQ_StopWatch_delete(self)\n" -+" if not self then return end\n" -+" local usecs1 = 0\n" -+" usecs1 = C.zmq_stopwatch_stop(self)\n" -+" return tonumber(usecs1)\n" -+"end\n" -+"_priv.ZMQ_StopWatch.__gc = _meth.ZMQ_StopWatch.stop\n" -+"\n" -+"_push.ZMQ_StopWatch = obj_type_ZMQ_StopWatch_push\n" -+"ffi.metatype(\"ZMQ_StopWatch\", _priv.ZMQ_StopWatch)\n" -+"-- End \"ZMQ_StopWatch\" FFI interface\n" -+"\n" -+"-- method: init\n" -+"function _M.init(io_threads1)\n" -+" io_threads1 = io_threads1 or 1\n" -+" local rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN\n" -+" local rc_zmq_init1\n" -+" rc_zmq_init1 = C.zmq_init(io_threads1)\n" -+" if (nil == rc_zmq_init1) then\n" -+" return nil, get_zmq_strerror()\n" -+" end\n" -+" return obj_type_ZMQ_Ctx_push(rc_zmq_init1, rc_zmq_init_flags1)\n" -+"end\n" -+"\n" -+"-- method: init_ctx\n" -+"function _M.init_ctx(ptr1)\n" -+" local ctx1\n" -+" local p_type = type(ptr1)\n" -+" if p_type == 'userdata' then\n" -+" ctx1 = ffi.cast('ZMQ_Ctx *', ptr1);\n" -+" elseif p_type == 'cdata' and ffi.istype('void *', ptr1) then\n" -+" ctx1 = ffi.cast('ZMQ_Ctx *', ptr1);\n" -+" else\n" -+" return error(\"expected lightuserdata/cdata\");\n" -+" end\n" -+"\n" -+" if (nil == ctx1) then\n" -+" return nil, get_zmq_strerror()\n" -+" end\n" -+" return obj_type_ZMQ_Ctx_push(ctx1, 0)\n" -+"end\n" -+"\n" -+"-- method: device\n" -+"if (_M.device) then\n" -+"function _M.device(device1, insock2, outsock3)\n" -+" \n" -+" \n" -+" \n" -+" local rc_zmq_device1 = 0\n" -+" rc_zmq_device1 = C.zmq_device(device1, insock2, outsock3)\n" -+" -- check for error.\n" -+" if (-1 == rc_zmq_device1) then\n", /* ----- CUT ----- */ -+" return nil, error_code__ZMQ_Error__push(rc_zmq_device1)\n" -+" end\n" -+" return true\n" -+"end\n" -+"end\n" -+"\n" -+"-- method: stopwatch_start\n" -+"function _M.stopwatch_start()\n" -+" local rc_zmq_stopwatch_start_flags1 = OBJ_UDATA_FLAG_OWN\n" -+" local rc_zmq_stopwatch_start1\n" -+" rc_zmq_stopwatch_start1 = C.zmq_stopwatch_start()\n" -+" return obj_type_ZMQ_StopWatch_push(rc_zmq_stopwatch_start1, rc_zmq_stopwatch_start_flags1)\n" -+"end\n" -+"\n" -+"-- method: sleep\n" -+"function _M.sleep(seconds_1)\n" -+" \n" -+" C.zmq_sleep(seconds_1)\n" -+" return \n" -+"end\n" -+"\n", NULL }; -+static char *zmq_ZErrors_key = "zmq_ZErrors_key"; -+/* -+ * This wrapper function is to make the EAGAIN/ETERM error messages more like -+ * what is returned by LuaSocket. -+ */ -+static const char *get_zmq_strerror() { -+ int err = zmq_errno(); -+ switch(err) { -+ case EAGAIN: -+ return "timeout"; -+ break; -+ case EINTR: -+ return "interrupted"; -+ break; -+#if defined(ETERM) -+ case ETERM: -+ return "closed"; -+ break; - #endif -+ default: -+ break; -+ } -+ return zmq_strerror(err); -+} -+ -+ -+ -+/* detect really old ZeroMQ 2.0.x series. */ -+#if !defined(ZMQ_RCVMORE) -+# error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" - #endif - --/* detect really old ZeroMQ 2.0.x series. */ --#if !defined(ZMQ_RCVMORE) --#error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" --#endif -+typedef struct ZMQ_Socket ZMQ_Socket; -+ -+#ifdef _WIN32 -+#include -+typedef SOCKET socket_t; -+#else -+typedef int socket_t; -+#endif -+ -+#if VERSION_2_0 -+# define zmq_sendmsg zmq_send -+# define zmq_recvmsg zmq_recv -+#endif -+ -+/* socket option types. */ -+#define OPT_TYPE_NONE 0 -+#define OPT_TYPE_INT 1 -+#define OPT_TYPE_UINT32 2 -+#define OPT_TYPE_UINT64 3 -+#define OPT_TYPE_INT64 4 -+#define OPT_TYPE_BLOB 5 -+#define OPT_TYPE_FD 6 -+ -+static const int opt_types[] = { -+ OPT_TYPE_NONE, /* 0 unused */ -+#if VERSION_2_0 -+#define VERSION_2_0_MAX_OPT 13 -+ OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ -+ OPT_TYPE_NONE, /* 2 unused */ -+ OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ -+ OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ -+ OPT_TYPE_BLOB, /* 5 ZMQ_IDENTITY */ -+ OPT_TYPE_BLOB, /* 6 ZMQ_SUBSCRIBE */ -+ OPT_TYPE_BLOB, /* 7 ZMQ_UNSUBSCRIBE */ -+ OPT_TYPE_INT64, /* 8 ZMQ_RATE */ -+ OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ -+ OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ -+ OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ -+ OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ -+ OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ -+#endif /* #if VERSION_2_0 */ -+#if VERSION_2_1 -+#define VERSION_2_1_MAX_OPT 21 -+ OPT_TYPE_FD, /* 14 ZMQ_FD */ -+ OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ -+ OPT_TYPE_INT, /* 16 ZMQ_TYPE */ -+ OPT_TYPE_INT, /* 17 ZMQ_LINGER */ -+ OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ -+ OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ -+ OPT_TYPE_INT64, /* 20 ZMQ_RECOVERY_IVL_MSEC */ -+ OPT_TYPE_INT, /* 21 ZMQ_RECONNECT_IVL_MAX */ -+#endif /* #if VERSION_2_1 */ -+#if VERSION_2_2 -+#define VERSION_2_2_MAX_OPT 28 -+ OPT_TYPE_NONE, /* 22 unused */ -+ OPT_TYPE_NONE, /* 23 unused */ -+ OPT_TYPE_NONE, /* 24 unused */ -+ OPT_TYPE_NONE, /* 25 unused */ -+ OPT_TYPE_NONE, /* 26 unused */ -+ OPT_TYPE_INT, /* 27 ZMQ_RCVTIMEO */ -+ OPT_TYPE_INT, /* 28 ZMQ_SNDTIMEO */ -+#endif /* #if VERSION_2_2 */ -+#if VERSION_3_0 -+#define VERSION_3_0_MAX_OPT 31 -+ OPT_TYPE_INT, /* 1 ZMQ_HWM */ -+ OPT_TYPE_NONE, /* 2 unused */ -+ OPT_TYPE_NONE, /* 3 unused */ -+ OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ -+ OPT_TYPE_BLOB, /* 5 ZMQ_IDENTITY */ -+ OPT_TYPE_BLOB, /* 6 ZMQ_SUBSCRIBE */ -+ OPT_TYPE_BLOB, /* 7 ZMQ_UNSUBSCRIBE */ -+ OPT_TYPE_INT, /* 8 ZMQ_RATE */ -+ OPT_TYPE_INT, /* 9 ZMQ_RECOVERY_IVL */ -+ OPT_TYPE_NONE, /* 10 unused */ -+ OPT_TYPE_INT, /* 11 ZMQ_SNDBUF */ -+ OPT_TYPE_INT, /* 12 ZMQ_RCVBUF */ -+ OPT_TYPE_INT, /* 13 ZMQ_RCVMORE */ -+ OPT_TYPE_FD, /* 14 ZMQ_FD */ -+ OPT_TYPE_INT, /* 15 ZMQ_EVENTS */ -+ OPT_TYPE_INT, /* 16 ZMQ_TYPE */ -+ OPT_TYPE_INT, /* 17 ZMQ_LINGER */ -+ OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ -+ OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ -+ OPT_TYPE_NONE, /* 20 unused */ -+ OPT_TYPE_INT, /* 21 ZMQ_RECONNECT_IVL_MAX */ -+ OPT_TYPE_INT64, /* 22 ZMQ_MAXMSGSIZE */ -+ OPT_TYPE_INT, /* 23 ZMQ_SNDHWM */ -+ OPT_TYPE_INT, /* 24 ZMQ_RCVHWM */ -+ OPT_TYPE_INT, /* 25 ZMQ_MULTICAST_HOPS */ -+ OPT_TYPE_NONE, /* 26 unused */ -+ OPT_TYPE_INT, /* 27 ZMQ_RCVTIMEO */ -+ OPT_TYPE_INT, /* 28 ZMQ_SNDTIMEO */ -+ OPT_TYPE_NONE, /* 29 unused */ -+ OPT_TYPE_NONE, /* 30 unused */ -+ OPT_TYPE_INT, /* 31 ZMQ_IPV4ONLY */ -+#endif /* #if VERSION_3_0 */ -+#if VERSION_3_0 -+# define MAX_OPTS VERSION_3_0_MAX_OPT -+#else -+# if VERSION_2_2 -+# define MAX_OPTS VERSION_2_2_MAX_OPT -+# elif VERSION_2_1 -+# define MAX_OPTS VERSION_2_1_MAX_OPT -+# else -+# define MAX_OPTS VERSION_2_0_MAX_OPT -+# endif -+#endif -+}; -+ -+#if VERSION_2_0 -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { -+ uint64_t val = (uint64_t)value; -+ return zmq_setsockopt(sock, ZMQ_HWM, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { -+ uint64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_HWM, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_swap(ZMQ_Socket *sock, int value) { -+ int64_t val = (int64_t)value; -+ return zmq_setsockopt(sock, ZMQ_SWAP, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_swap(ZMQ_Socket *sock, int *value) { -+ int64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_SWAP, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *sock, uint64_t value) { -+ return zmq_setsockopt(sock, ZMQ_AFFINITY, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *sock, uint64_t *value) { -+ size_t val_len = sizeof(uint64_t); -+ return zmq_getsockopt(sock, ZMQ_AFFINITY, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_IDENTITY, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_identity(ZMQ_Socket *sock, char *value, size_t *len) { -+ return zmq_getsockopt(sock, ZMQ_IDENTITY, value, len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_SUBSCRIBE, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_UNSUBSCRIBE, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *sock, int value) { -+ int64_t val = (int64_t)value; -+ return zmq_setsockopt(sock, ZMQ_RATE, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rate(ZMQ_Socket *sock, int *value) { -+ int64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_RATE, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *sock, int value) { -+ int64_t val = (int64_t)value; -+ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *sock, int *value) { -+ int64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_RECOVERY_IVL, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_mcast_loop(ZMQ_Socket *sock, int value) { -+ int64_t val = (int64_t)value; -+ return zmq_setsockopt(sock, ZMQ_MCAST_LOOP, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_mcast_loop(ZMQ_Socket *sock, int *value) { -+ int64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_MCAST_LOOP, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *sock, int value) { -+ uint64_t val = (uint64_t)value; -+ return zmq_setsockopt(sock, ZMQ_SNDBUF, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *sock, int *value) { -+ uint64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_SNDBUF, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *sock, int value) { -+ uint64_t val = (uint64_t)value; -+ return zmq_setsockopt(sock, ZMQ_RCVBUF, &val, sizeof(val)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *sock, int *value) { -+ uint64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_RCVBUF, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *sock, int *value) { -+ int64_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_RCVMORE, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+#endif /* #if VERSION_2_0 */ -+#if VERSION_2_1 -+LUA_NOBJ_API ZMQ_Error lzmq_socket_fd(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_FD, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_events(ZMQ_Socket *sock, int *value) { -+ uint32_t val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ZMQ_EVENTS, &val, &val_len); -+ *value = (int)val; -+ return rc; -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_type(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_TYPE, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_LINGER, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_linger(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_LINGER, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_BACKLOG, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_BACKLOG, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl_msec(ZMQ_Socket *sock, int64_t value) { -+ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL_MSEC, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl_msec(ZMQ_Socket *sock, int64_t *value) { -+ size_t val_len = sizeof(int64_t); -+ return zmq_getsockopt(sock, ZMQ_RECOVERY_IVL_MSEC, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL_MAX, value, &val_len); -+} -+ -+#endif /* #if VERSION_2_1 */ -+#if VERSION_2_2 -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RCVTIMEO, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RCVTIMEO, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_SNDTIMEO, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_SNDTIMEO, value, &val_len); -+} -+ -+#endif /* #if VERSION_2_2 */ -+#if VERSION_3_0 -+ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { -+ int val; -+ int rc; -+ val = (int)value; -+ rc = zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); -+ if(-1 == rc) return rc; -+ val = (int)value; -+ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); -+} -+ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { -+ size_t val_len; -+ int rc; -+ val_len = sizeof(value); -+ rc = zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); -+ if(-1 == rc) return rc; -+ val_len = sizeof(value); -+ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *sock, uint64_t value) { -+ return zmq_setsockopt(sock, ZMQ_AFFINITY, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *sock, uint64_t *value) { -+ size_t val_len = sizeof(uint64_t); -+ return zmq_getsockopt(sock, ZMQ_AFFINITY, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_IDENTITY, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_identity(ZMQ_Socket *sock, char *value, size_t *len) { -+ return zmq_getsockopt(sock, ZMQ_IDENTITY, value, len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_SUBSCRIBE, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ZMQ_UNSUBSCRIBE, value, str_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RATE, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rate(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RATE, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RECOVERY_IVL, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_SNDBUF, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_SNDBUF, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RCVBUF, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RCVBUF, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RCVMORE, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_fd(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_FD, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_events(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_EVENTS, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_type(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_TYPE, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_LINGER, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_linger(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_LINGER, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_BACKLOG, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_BACKLOG, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL_MAX, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_maxmsgsize(ZMQ_Socket *sock, int64_t value) { -+ return zmq_setsockopt(sock, ZMQ_MAXMSGSIZE, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_maxmsgsize(ZMQ_Socket *sock, int64_t *value) { -+ size_t val_len = sizeof(int64_t); -+ return zmq_getsockopt(sock, ZMQ_MAXMSGSIZE, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndhwm(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_sndhwm(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvhwm(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvhwm(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_multicast_hops(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_MULTICAST_HOPS, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_multicast_hops(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_MULTICAST_HOPS, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_RCVTIMEO, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_RCVTIMEO, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_SNDTIMEO, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_SNDTIMEO, value, &val_len); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_set_ipv4only(ZMQ_Socket *sock, int value) { -+ return zmq_setsockopt(sock, ZMQ_IPV4ONLY, &value, sizeof(value)); -+} -+ -+LUA_NOBJ_API ZMQ_Error lzmq_socket_ipv4only(ZMQ_Socket *sock, int *value) { -+ size_t val_len = sizeof(int); -+ return zmq_getsockopt(sock, ZMQ_IPV4ONLY, value, &val_len); -+} -+ -+#endif /* #if VERSION_3_0 */ -+ -+LUA_NOBJ_API ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { -+ ZMQ_Error err; -+ zmq_msg_t msg; -+ /* initialize message */ -+ err = zmq_msg_init_size(&msg, data_len); -+ if(0 == err) { -+ /* fill message */ -+ memcpy(zmq_msg_data(&msg), data, data_len); -+ /* send message */ -+ err = zmq_sendmsg(sock, &msg, flags); -+ /* close message */ -+ zmq_msg_close(&msg); -+ } -+ return err; -+} -+ -+struct ZMQ_Poller { -+ zmq_pollitem_t *items; -+ int next; -+ int count; -+ int free_list; -+ int len; -+}; -+ -+ -+typedef struct ZMQ_Poller ZMQ_Poller; -+ -+#define FREE_ITEM_EVENTS_TAG ((short)0xFFFF) -+ -+#define ITEM_TO_INDEX(items, item) (item - (items)) -+ -+static int poller_resize_items(ZMQ_Poller *poller, int len) { -+ int old_len = poller->len; -+ -+ /* make sure new length is atleast as large as items count. */ -+ len = (poller->count <= len) ? len : poller->count; -+ -+ /* if the new length is the same as the old length, then don't try to resize. */ -+ if(old_len == len) return len; -+ -+ poller->items = (zmq_pollitem_t *)realloc(poller->items, len * sizeof(zmq_pollitem_t)); -+ poller->len = len; -+ if(len > old_len) { -+ /* clear new space. */ -+ memset(&(poller->items[old_len]), 0, (len - old_len) * sizeof(zmq_pollitem_t)); -+ } -+ return len; -+} -+ -+void poller_init(ZMQ_Poller *poller, int length) { -+ poller->items = (zmq_pollitem_t *)calloc(length, sizeof(zmq_pollitem_t)); -+ poller->next = -1; -+ poller->count = 0; -+ poller->len = length; -+ poller->free_list = -1; -+} -+ -+void poller_cleanup(ZMQ_Poller *poller) { -+ free(poller->items); -+ poller->items = NULL; -+ poller->next = -1; -+ poller->count = 0; -+ poller->len = 0; -+ poller->free_list = -1; -+} -+ -+int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { -+ zmq_pollitem_t *items; -+ int count; -+ int n; -+ -+ /* find ZMQ_Socket */ -+ items = poller->items; -+ count = poller->count; -+ for(n=0; n < count; n++) { -+ if(items[n].socket == sock) return n; -+ } -+ /* not found. */ -+ return -1; -+} -+ -+int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { -+ zmq_pollitem_t *items; -+ int count; -+ int n; -+ -+ /* find fd */ -+ items = poller->items; -+ count = poller->count; -+ for(n=0; n < count; n++) { -+ if(items[n].fd == fd) return n; -+ } -+ /* not found. */ -+ return -1; -+} -+ -+void poller_remove_item(ZMQ_Poller *poller, int idx) { -+ zmq_pollitem_t *items; -+ int free_list; -+ int count; -+ -+ count = poller->count; -+ /* no item to remove. */ -+ if(idx >= count || count == 0) return; -+ -+ items = poller->items; -+ free_list = poller->free_list; -+ -+ /* link new free slot to head of free list. */ -+ if(free_list >= 0 && free_list < count) { -+ /* use socket pointer for free list's 'next' field. */ -+ items[idx].socket = &(items[free_list]); -+ } else { -+ /* free list is empty mark poller slot as the end. */ -+ items[idx].socket = NULL; -+ } -+ poller->free_list = idx; -+ /* mark poller slot as a free slot. */ -+ items[idx].events = FREE_ITEM_EVENTS_TAG; -+ /* clear old revents. */ -+ items[idx].revents = 0; -+} -+ -+int poller_get_free_item(ZMQ_Poller *poller) { -+ zmq_pollitem_t *curr; -+ zmq_pollitem_t *next; -+ int count; -+ int idx; -+ -+ count = poller->count; -+ idx = poller->free_list; -+ /* check for a free slot in the free list. */ -+ if(idx >= 0 && idx < count) { -+ /* remove free slot from free list. */ -+ curr = &(poller->items[idx]); -+ /* valid free slot. */ -+ assert(curr->events == FREE_ITEM_EVENTS_TAG); -+ /* is poller the last free slot? */ -+ next = ((zmq_pollitem_t *)curr->socket); -+ if(next != NULL) { -+ /* set next free slot as head of free list. */ -+ poller->free_list = ITEM_TO_INDEX(poller->items, next); -+ } else { -+ /* free list is empty now. */ -+ poller->free_list = -1; -+ } -+ /* clear slot */ -+ memset(curr, 0, sizeof(zmq_pollitem_t)); -+ return idx; -+ } -+ -+ idx = count; -+ poller->count = ++count; -+ /* make room for new item. */ -+ if(count >= poller->len) { -+ poller_resize_items(poller, poller->len + 10); -+ } -+ return idx; -+} -+ -+static int poller_compact_items(ZMQ_Poller *poller) { -+ zmq_pollitem_t *items; -+ int count; -+ int old_count; -+ int next; -+ -+ count = poller->count; -+ /* if no free slot, then return. */ -+ if(poller->free_list < 0) return count; -+ old_count = count; -+ -+ items = poller->items; -+ next = 0; -+ /* find first free slot. */ -+ while(next < count && items[next].events != FREE_ITEM_EVENTS_TAG) { -+ ++next; -+ } -+ -+ /* move non-free slots into free slot. */ -+ count = next; -+ ++next; -+ while(next < old_count) { -+ if(items[next].events != FREE_ITEM_EVENTS_TAG) { -+ /* found non-free slot, move it to the current free slot. */ -+ items[count] = items[next]; -+ ++count; -+ } -+ ++next; -+ } -+ -+ /* clear old used-space */ -+ memset(&(items[count]), 0, ((old_count - count) * sizeof(zmq_pollitem_t))); -+ poller->count = count; -+ poller->free_list = -1; /* free list is now empty. */ - --typedef struct ZMQ_Socket ZMQ_Socket; -+ assert(count <= poller->len); -+ return count; -+} - --#ifdef _WIN32 --#include --typedef SOCKET socket_t; --#else --typedef int socket_t; --#endif -+int poller_poll(ZMQ_Poller *poller, long timeout) { -+ int count; -+ /* remove free slots from items list. */ -+ if(poller->free_list >= 0) { -+ count = poller_compact_items(poller); -+ } else { -+ count = poller->count; -+ } -+ /* poll for events. */ -+ return zmq_poll(poller->items, count, timeout); -+} - --/* socket option types. */ --#define OPT_TYPE_NONE 0 --#define OPT_TYPE_INT 1 --#define OPT_TYPE_UINT32 2 --#define OPT_TYPE_UINT64 3 --#define OPT_TYPE_INT64 4 --#define OPT_TYPE_STR 5 --#define OPT_TYPE_FD 6 -+int poller_next_revents(ZMQ_Poller *poller, int *revents) { -+ zmq_pollitem_t *items; -+ int count; -+ int idx; -+ int next; - --static const int opt_types[] = { -- OPT_TYPE_NONE, /* 0 unused */ -- OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ -- OPT_TYPE_NONE, /* 2 unused */ -- OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ -- OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ -- OPT_TYPE_STR, /* 5 ZMQ_IDENTITY */ -- OPT_TYPE_STR, /* 6 ZMQ_SUBSCRIBE */ -- OPT_TYPE_STR, /* 7 ZMQ_UNSUBSCRIBE */ -- OPT_TYPE_INT64, /* 8 ZMQ_RATE */ -- OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ -- OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ -- OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ -- OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ -- OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ -+ idx = poller->next; -+ /* do we need to poll for more events? */ -+ if(idx < 0) { -+ return idx; -+ } -+ items = poller->items; -+ count = poller->count; -+ /* find next item with pending events. */ -+ for(;idx < count; ++idx) { -+ /* did we find a pending event? */ -+ if(items[idx].revents != 0) { -+ *revents = items[idx].revents; -+ poller->next = idx+1; -+ return idx; -+ } -+ } -+ /* processed all pending events. */ -+ poller->next = -1; -+ *revents = 0; -+ return -1; -+} - --#if VERSION_2_1 -- OPT_TYPE_FD, /* 14 ZMQ_FD */ -- OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ -- OPT_TYPE_INT, /* 16 ZMQ_TYPE */ -- OPT_TYPE_INT, /* 17 ZMQ_LINGER */ -- OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ -- OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ --#endif --}; --#if VERSION_2_1 --#define MAX_OPTS ZMQ_BACKLOG --#else --#define MAX_OPTS ZMQ_RCVMORE -+ -+typedef struct ZMQ_Ctx ZMQ_Ctx; -+ -+typedef struct ZMQ_StopWatch ZMQ_StopWatch; -+ -+ -+ -+/* method: description */ -+static int ZErrors__description__meth(lua_State *L) { -+ const char * msg1 = NULL; -+ int err_type; -+ int err_num = -1; -+ -+ err_type = lua_type(L, 2); -+ if(err_type == LUA_TSTRING) { -+ lua_pushvalue(L, 2); -+ lua_rawget(L, 1); -+ if(lua_isnumber(L, -1)) { -+ err_num = lua_tointeger(L, -1); -+ } -+ lua_pop(L, 1); -+ } else if(err_type == LUA_TNUMBER) { -+ err_num = lua_tointeger(L, 2); -+ } else { -+ return luaL_argerror(L, 2, "expected string/number"); -+ } -+ if(err_num < 0) { -+ lua_pushnil(L); -+ lua_pushliteral(L, "UNKNOWN ERROR"); -+ return 2; -+ } -+ msg1 = strerror(err_num); -+ -+ lua_pushstring(L, msg1); -+ return 1; -+} -+ -+/* method: __index */ -+static int ZErrors____index__meth(lua_State *L) { -+ int err2; -+ const char * msg1 = NULL; -+ err2 = luaL_checkinteger(L,2); -+ switch(err2) { -+ case EAGAIN: -+ msg1 = "timeout"; -+ break; -+ case EINTR: -+ msg1 = "interrupted"; -+ break; -+#if defined(ETERM) -+ case ETERM: -+ msg1 = "closed"; -+ break; - #endif -+ default: -+ msg1 = zmq_strerror(err2); -+ break; -+ } -+ lua_pushvalue(L, 2); -+ lua_pushstring(L, msg1); -+ lua_rawset(L, 1); - -+ lua_pushstring(L, msg1); -+ return 1; -+} - --static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { -- ZMQ_Error err; -- zmq_msg_t msg; -- /* initialize message */ -- err = zmq_msg_init_size(&msg, data_len); -- if(0 == err) { -+static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err) { -+ const char *err_str = NULL; -+ int num; -+ if(-1 == err) { -+ /* get ZErrors table. */ -+ lua_pushlightuserdata(L, zmq_ZErrors_key); -+ lua_rawget(L, LUA_REGISTRYINDEX); -+ /* convert zmq_errno to string. */ -+ num = zmq_errno(); -+ lua_pushinteger(L, num); -+ lua_gettable(L, -2); -+ /* remove ZErrors table. */ -+ lua_remove(L, -2); -+ if(!lua_isnil(L, -1)) { -+ /* found error. */ -+ return; -+ } -+ /* Unknown error. */ -+ lua_pop(L, 1); -+ lua_pushfstring(L, "UNKNOWN ERROR(%d)", num); -+ return; -+ } -+ -+ if(err_str) { -+ lua_pushstring(L, err_str); -+ } else { -+ lua_pushnil(L); -+ } -+} -+ -+/* method: init */ -+static int zmq_msg_t__init__meth(lua_State *L) { -+ zmq_msg_t this1_store; -+ zmq_msg_t * this1 = &(this1_store); -+ ZMQ_Error rc_zmq_msg_init2 = 0; -+ rc_zmq_msg_init2 = zmq_msg_init(this1); -+ if(!(-1 == rc_zmq_msg_init2)) { -+ obj_type_zmq_msg_t_push(L, this1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_init2); -+ return 2; -+} -+ -+/* method: init_size */ -+static int zmq_msg_t__init_size__meth(lua_State *L) { -+ size_t size1; -+ zmq_msg_t this1_store; -+ zmq_msg_t * this1 = &(this1_store); -+ ZMQ_Error rc_zmq_msg_init_size2 = 0; -+ size1 = luaL_checkinteger(L,1); -+ rc_zmq_msg_init_size2 = zmq_msg_init_size(this1, size1); -+ if(!(-1 == rc_zmq_msg_init_size2)) { -+ obj_type_zmq_msg_t_push(L, this1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_init_size2); -+ return 2; -+} -+ -+/* method: init_data */ -+static int zmq_msg_t__init_data__meth(lua_State *L) { -+ size_t data_len1; -+ const char * data1; -+ zmq_msg_t this1_store; -+ zmq_msg_t * this1 = &(this1_store); -+ ZMQ_Error err2 = 0; -+ data1 = luaL_checklstring(L,1,&(data_len1)); -+ err2 = zmq_msg_init_size(this1, data_len1); -+ if(0 == err2) { - /* fill message */ -- memcpy(zmq_msg_data(&msg), data, data_len); -- /* send message */ -- err = zmq_send(sock, &msg, flags); -- /* close message */ -- zmq_msg_close(&msg); -+ memcpy(zmq_msg_data(this1), data1, data_len1); - } -- return err; -+ -+ if(!(-1 == err2)) { -+ obj_type_zmq_msg_t_push(L, this1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, err2); -+ return 2; -+} -+ -+/* method: _priv */ -+static int zmq_msg_t__delete__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ ZMQ_Error rc_zmq_msg_close1 = 0; -+ this1 = obj_type_zmq_msg_t_delete(L,1); -+ rc_zmq_msg_close1 = zmq_msg_close(this1); -+ /* check for error. */ -+ if((-1 == rc_zmq_msg_close1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+ -+/* method: close */ -+static int zmq_msg_t__close__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ ZMQ_Error rc_zmq_msg_close1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ rc_zmq_msg_close1 = zmq_msg_close(this1); -+ /* check for error. */ -+ if((-1 == rc_zmq_msg_close1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+ -+/* method: move */ -+static int zmq_msg_t__move__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ zmq_msg_t * src2; -+ ZMQ_Error rc_zmq_msg_move1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ src2 = obj_type_zmq_msg_t_check(L,2); -+ rc_zmq_msg_move1 = zmq_msg_move(this1, src2); -+ /* check for error. */ -+ if((-1 == rc_zmq_msg_move1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_move1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+ -+/* method: copy */ -+static int zmq_msg_t__copy__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ zmq_msg_t * src2; -+ ZMQ_Error rc_zmq_msg_copy1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ src2 = obj_type_zmq_msg_t_check(L,2); -+ rc_zmq_msg_copy1 = zmq_msg_copy(this1, src2); -+ /* check for error. */ -+ if((-1 == rc_zmq_msg_copy1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_msg_copy1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+ -+/* method: set_data */ -+static int zmq_msg_t__set_data__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ size_t data_len2; -+ const char * data2; -+ ZMQ_Error err1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ data2 = luaL_checklstring(L,2,&(data_len2)); -+ /* check message data size. */ -+ if(zmq_msg_size(this1) != data_len2) { -+ /* need to resize message. */ -+ zmq_msg_close(this1); /* close old message, to free old data. */ -+ err1 = zmq_msg_init_size(this1, data_len2); /* re-initialize message. */ -+ if(0 != err1) { -+ luaL_error(L, "set_data() failed: %s", get_zmq_strerror()); -+ } -+ } -+ /* copy data into message */ -+ memcpy(zmq_msg_data(this1), data2, data_len2); -+ -+ /* check for error. */ -+ if((-1 == err1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, err1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+ -+/* method: data */ -+static int zmq_msg_t__data__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ void * rc_zmq_msg_data1 = NULL; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ rc_zmq_msg_data1 = zmq_msg_data(this1); -+ lua_pushlightuserdata(L, rc_zmq_msg_data1); -+ return 1; -+} -+ -+/* method: set_size */ -+static int zmq_msg_t__set_size__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ size_t size2; -+ ZMQ_Error err1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ size2 = luaL_checkinteger(L,2); -+ /* check message data size. */ -+ if(zmq_msg_size(this1) != size2) { -+ /* need to resize message. */ -+ zmq_msg_close(this1); /* close old message, to free old data. */ -+ err1 = zmq_msg_init_size(this1, size2); /* re-initialize message. */ -+ if(0 != err1) { -+ luaL_error(L, "set_size() failed: %s", get_zmq_strerror()); -+ } -+ } -+ -+ /* check for error. */ -+ if((-1 == err1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, err1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; - } - --struct ZMQ_Poller { -- zmq_pollitem_t *items; -- int next; -- int count; -- int free_list; -- int len; --}; -+/* method: size */ -+static int zmq_msg_t__size__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ size_t size1 = 0; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ size1 = zmq_msg_size(this1); -+ lua_pushinteger(L, size1); -+ return 1; -+} - -+/* method: __tostring */ -+static int zmq_msg_t____tostring__meth(lua_State *L) { -+ zmq_msg_t * this1; -+ size_t data_len1 = 0; -+ const char * data1 = NULL; -+ this1 = obj_type_zmq_msg_t_check(L,1); -+ data1 = zmq_msg_data(this1); -+ data_len1 = zmq_msg_size(this1); - --typedef struct ZMQ_Poller ZMQ_Poller; -+ if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); -+ return 1; -+} - --#define FREE_ITEM_EVENTS_TAG ((short)0xFFFF) -+/* method: close */ -+static int ZMQ_Socket__close__meth(lua_State *L) { -+ int this_flags1 = 0; -+ ZMQ_Socket * this1; -+ ZMQ_Error rc_zmq_close1 = 0; -+ this1 = obj_type_ZMQ_Socket_delete(L,1,&(this_flags1)); -+ if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } -+ rc_zmq_close1 = zmq_close(this1); -+ /* check for error. */ -+ if((-1 == rc_zmq_close1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_close1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - --#define ITEM_TO_INDEX(items, item) (item - (items)) -+/* method: bind */ -+static int ZMQ_Socket__bind__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t addr_len2; -+ const char * addr2; -+ ZMQ_Error rc_zmq_bind1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ addr2 = luaL_checklstring(L,2,&(addr_len2)); -+ rc_zmq_bind1 = zmq_bind(this1, addr2); -+ /* check for error. */ -+ if((-1 == rc_zmq_bind1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_bind1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - --static int poller_resize_items(ZMQ_Poller *poller, int len) { -- int old_len = poller->len; -+/* method: connect */ -+static int ZMQ_Socket__connect__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t addr_len2; -+ const char * addr2; -+ ZMQ_Error rc_zmq_connect1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ addr2 = luaL_checklstring(L,2,&(addr_len2)); -+ rc_zmq_connect1 = zmq_connect(this1, addr2); -+ /* check for error. */ -+ if((-1 == rc_zmq_connect1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_connect1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - -- /* make sure new length is atleast as large as items count. */ -- len = (poller->count <= len) ? len : poller->count; -+/* method: setopt */ -+static int ZMQ_Socket__setopt__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ uint32_t opt2; -+ ZMQ_Error err1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ opt2 = luaL_checkinteger(L,2); -+ size_t val_len; -+ const void *val; - -- /* if the new length is the same as the old length, then don't try to resize. */ -- if(old_len == len) return len; -+#if defined(VERSION_2_1) || defined(VERSION_3_0) -+ socket_t fd_val; -+#endif -+ int int_val; -+ uint32_t uint32_val; -+ uint64_t uint64_val; -+ int64_t int64_val; - -- poller->items = (zmq_pollitem_t *)realloc(poller->items, len * sizeof(zmq_pollitem_t)); -- poller->len = len; -- if(len > old_len) { -- /* clear new space. */ -- memset(&(poller->items[old_len]), 0, (len - old_len) * sizeof(zmq_pollitem_t)); -+#if VERSION_3_0 -+ /* 3.0 backwards compatibility support for HWM. */ -+ if(opt2 == ZMQ_HWM) { -+ int_val = luaL_checklong(L, 3); -+ val = &int_val; -+ val_len = sizeof(int_val); -+ err1 = zmq_setsockopt(this1, ZMQ_SNDHWM, val, val_len); -+ if(-1 != err1) { -+ err1 = zmq_setsockopt(this1, ZMQ_RCVHWM, val, val_len); -+ } -+ goto finished; - } -- return len; --} -- --static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { -- zmq_pollitem_t *items; -- int count; -- int n; -+#endif - -- /* find ZMQ_Socket */ -- items = poller->items; -- count = poller->count; -- for(n=0; n < count; n++) { -- if(items[n].socket == sock) return n; -+ if(opt2 > MAX_OPTS) { -+ return luaL_argerror(L, 2, "Invalid socket option."); - } -- /* not found. */ -- return -1; --} -- --static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { -- zmq_pollitem_t *items; -- int count; -- int n; - -- /* find fd */ -- items = poller->items; -- count = poller->count; -- for(n=0; n < count; n++) { -- if(items[n].fd == fd) return n; -+ switch(opt_types[opt2]) { -+#if defined(VERSION_2_1) || defined(VERSION_3_0) -+ case OPT_TYPE_FD: -+ fd_val = luaL_checklong(L, 3); -+ val = &fd_val; -+ val_len = sizeof(fd_val); -+ break; -+#endif -+ case OPT_TYPE_INT: -+ int_val = luaL_checklong(L, 3); -+ val = &int_val; -+ val_len = sizeof(int_val); -+ break; -+ case OPT_TYPE_UINT32: -+ uint32_val = luaL_checklong(L, 3); -+ val = &uint32_val; -+ val_len = sizeof(uint32_val); -+ break; -+ case OPT_TYPE_UINT64: -+ uint64_val = luaL_checklong(L, 3); -+ val = &uint64_val; -+ val_len = sizeof(uint64_val); -+ break; -+ case OPT_TYPE_INT64: -+ int64_val = luaL_checklong(L, 3); -+ val = &int64_val; -+ val_len = sizeof(int64_val); -+ break; -+ case OPT_TYPE_BLOB: -+ val = luaL_checklstring(L, 3, &(val_len)); -+ break; -+ default: -+ printf("Invalid socket option type, this shouldn't happen.\n"); -+ abort(); -+ break; - } -- /* not found. */ -- return -1; --} -+ err1 = zmq_setsockopt(this1, opt2, val, val_len); -+finished: - --static void poller_remove_item(ZMQ_Poller *poller, int idx) { -- zmq_pollitem_t *items; -- int free_list; -- int count; -+ /* check for error. */ -+ if((-1 == err1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, err1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - -- count = poller->count; -- /* no item to remove. */ -- if(idx >= count || count == 0) return; -+/* method: getopt */ -+static int ZMQ_Socket__getopt__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ uint32_t opt2; -+ ZMQ_Error err2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ opt2 = luaL_checkinteger(L,2); -+ size_t val_len; - -- items = poller->items; -- free_list = poller->free_list; -+#if defined(VERSION_2_1) || defined(VERSION_3_0) -+ socket_t fd_val; -+#endif -+ int int_val; -+ uint32_t uint32_val; -+ uint64_t uint64_val; -+ int64_t int64_val; -+#define STR_MAX 255 -+ char str_val[STR_MAX]; - -- /* link new free slot to head of free list. */ -- if(free_list >= 0 && free_list < count) { -- /* use socket pointer for free list's 'next' field. */ -- items[idx].socket = &(items[free_list]); -- } else { -- /* free list is empty mark poller slot as the end. */ -- items[idx].socket = NULL; -+ if(opt2 > MAX_OPTS) { -+ lua_pushnil(L); -+ lua_pushliteral(L, "Invalid socket option."); -+ return 2; - } -- poller->free_list = idx; -- /* mark poller slot as a free slot. */ -- items[idx].events = FREE_ITEM_EVENTS_TAG; -- /* clear old revents. */ -- items[idx].revents = 0; --} - --static int poller_get_free_item(ZMQ_Poller *poller) { -- zmq_pollitem_t *curr; -- zmq_pollitem_t *next; -- int count; -- int idx; -- -- count = poller->count; -- idx = poller->free_list; -- /* check for a free slot in the free list. */ -- if(idx >= 0 && idx < count) { -- /* remove free slot from free list. */ -- curr = &(poller->items[idx]); -- /* valid free slot. */ -- assert(curr->events == FREE_ITEM_EVENTS_TAG); -- /* is poller the last free slot? */ -- next = ((zmq_pollitem_t *)curr->socket); -- if(next != NULL) { -- /* set next free slot as head of free list. */ -- poller->free_list = ITEM_TO_INDEX(poller->items, next); -- } else { -- /* free list is empty now. */ -- poller->free_list = -1; -+ switch(opt_types[opt2]) { -+#if defined(VERSION_2_1) || defined(VERSION_3_0) -+ case OPT_TYPE_FD: -+ val_len = sizeof(fd_val); -+ err2 = zmq_getsockopt(this1, opt2, &fd_val, &val_len); -+ if(0 == err2) { -+ lua_pushinteger(L, (lua_Integer)fd_val); -+ return 1; -+ } -+ break; -+#endif -+ case OPT_TYPE_INT: -+ val_len = sizeof(int_val); -+ err2 = zmq_getsockopt(this1, opt2, &int_val, &val_len); -+ if(0 == err2) { -+ lua_pushinteger(L, (lua_Integer)int_val); -+ return 1; -+ } -+ break; -+ case OPT_TYPE_UINT32: -+ val_len = sizeof(uint32_val); -+ err2 = zmq_getsockopt(this1, opt2, &uint32_val, &val_len); -+ if(0 == err2) { -+ lua_pushinteger(L, (lua_Integer)uint32_val); -+ return 1; -+ } -+ break; -+ case OPT_TYPE_UINT64: -+ val_len = sizeof(uint64_val); -+ err2 = zmq_getsockopt(this1, opt2, &uint64_val, &val_len); -+ if(0 == err2) { -+ lua_pushinteger(L, (lua_Integer)uint64_val); -+ return 1; - } -- /* clear slot */ -- memset(curr, 0, sizeof(zmq_pollitem_t)); -- return idx; -+ break; -+ case OPT_TYPE_INT64: -+ val_len = sizeof(int64_val); -+ err2 = zmq_getsockopt(this1, opt2, &int64_val, &val_len); -+ if(0 == err2) { -+ lua_pushinteger(L, (lua_Integer)int64_val); -+ return 1; -+ } -+ break; -+ case OPT_TYPE_BLOB: -+ val_len = STR_MAX; -+ err2 = zmq_getsockopt(this1, opt2, str_val, &val_len); -+ if(0 == err2) { -+ lua_pushlstring(L, str_val, val_len); -+ return 1; -+ } -+#undef STR_MAX -+ break; -+ default: -+ printf("Invalid socket option type, this shouldn't happen.\n"); -+ abort(); -+ break; - } -+ lua_pushnil(L); - -- idx = count; -- poller->count = ++count; -- /* make room for new item. */ -- if(count >= poller->len) { -- poller_resize_items(poller, poller->len + 10); -- } -- return idx; -+ error_code__ZMQ_Error__push(L, err2); -+ return 2; - } - --static int poller_compact_items(ZMQ_Poller *poller) { -- zmq_pollitem_t *items; -- int count; -- int old_count; -- int next; -+/* method: send_msg */ -+static int ZMQ_Socket__send_msg__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ zmq_msg_t * msg2; -+ int flags3; -+ ZMQ_Error rc_zmq_sendmsg1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ msg2 = obj_type_zmq_msg_t_check(L,2); -+ flags3 = luaL_optinteger(L,3,0); -+ rc_zmq_sendmsg1 = zmq_sendmsg(this1, msg2, flags3); -+ /* check for error. */ -+ if((-1 == rc_zmq_sendmsg1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_sendmsg1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - -- count = poller->count; -- /* if no free slot, then return. */ -- if(poller->free_list < 0) return count; -- old_count = count; -+/* method: send */ -+static int ZMQ_Socket__send__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t data_len2; -+ const char * data2; -+ int flags3; -+ ZMQ_Error rc_simple_zmq_send1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ data2 = luaL_checklstring(L,2,&(data_len2)); -+ flags3 = luaL_optinteger(L,3,0); -+ rc_simple_zmq_send1 = simple_zmq_send(this1, data2, data_len2, flags3); -+ /* check for error. */ -+ if((-1 == rc_simple_zmq_send1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_simple_zmq_send1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - -- items = poller->items; -- next = 0; -- /* find first free slot. */ -- while(next < count && items[next].events != FREE_ITEM_EVENTS_TAG) { -- ++next; -- } -+/* method: recv_msg */ -+static int ZMQ_Socket__recv_msg__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ zmq_msg_t * msg2; -+ int flags3; -+ ZMQ_Error rc_zmq_recvmsg1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ msg2 = obj_type_zmq_msg_t_check(L,2); -+ flags3 = luaL_optinteger(L,3,0); -+ rc_zmq_recvmsg1 = zmq_recvmsg(this1, msg2, flags3); -+ /* check for error. */ -+ if((-1 == rc_zmq_recvmsg1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_zmq_recvmsg1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - -- /* move non-free slots into free slot. */ -- count = next; -- ++next; -- while(next < old_count) { -- if(items[next].events != FREE_ITEM_EVENTS_TAG) { -- /* found non-free slot, move it to the current free slot. */ -- items[count] = items[next]; -- ++count; -+/* method: recv */ -+static int ZMQ_Socket__recv__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int flags2; -+ size_t data_len1 = 0; -+ const char * data1 = NULL; -+ ZMQ_Error err2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ flags2 = luaL_optinteger(L,2,0); -+ zmq_msg_t msg; -+ /* initialize message */ -+ err2 = zmq_msg_init(&msg); -+ if(0 == err2) { -+ /* receive message */ -+ err2 = zmq_recvmsg(this1, &msg, flags2); -+ if(err2 >= 0) { -+ data1 = zmq_msg_data(&msg); -+ data_len1 = zmq_msg_size(&msg); - } -- ++next; - } - -- /* clear old used-space */ -- memset(&(items[count]), 0, ((old_count - count) * sizeof(zmq_pollitem_t))); -- poller->count = count; -- poller->free_list = -1; /* free list is now empty. */ -+ if(!(-1 == err2)) { -+ if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, err2); -+ /* close message */ -+ zmq_msg_close(&msg); - -- assert(count <= poller->len); -- return count; -+ return 2; - } - --static int poller_poll(ZMQ_Poller *poller, long timeout) { -- int count; -- /* remove free slots from items list. */ -- count = poller_compact_items(poller); -- /* poll for events. */ -- return zmq_poll(poller->items, count, timeout); -+/* method: hwm */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__hwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_hwm2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_hwm2 = lzmq_socket_hwm(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_hwm2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_hwm2); -+ return 2; - } -+#endif - -+/* method: set_hwm */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_hwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_hwm1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_hwm1 = lzmq_socket_set_hwm(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_hwm1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_hwm1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - --typedef struct ZMQ_Ctx ZMQ_Ctx; -+/* method: swap */ -+#if (VERSION_2_0) -+static int ZMQ_Socket__swap__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_swap2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_swap2 = lzmq_socket_swap(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_swap2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_swap2); -+ return 2; -+} -+#endif - --typedef struct ZMQ_StopWatch ZMQ_StopWatch; -+/* method: set_swap */ -+#if (VERSION_2_0) -+static int ZMQ_Socket__set_swap__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_swap1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_swap1 = lzmq_socket_set_swap(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_swap1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_swap1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - --/* -- * This wrapper function is to make the EAGAIN/ETERM error messages more like -- * what is returned by LuaSocket. -- */ --static const char *get_zmq_strerror() { -- int err = zmq_errno(); -- switch(err) { -- case EAGAIN: -- return "timeout"; -- break; --#if defined(ETERM) -- case ETERM: -- return "closed"; -- break; -+/* method: affinity */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__affinity__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ uint64_t value1 = 0; -+ ZMQ_Error rc_lzmq_socket_affinity2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_affinity2 = lzmq_socket_affinity(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_affinity2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_affinity2); -+ return 2; -+} - #endif -- default: -- break; -- } -- return zmq_strerror(err); -+ -+/* method: set_affinity */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_affinity__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ uint64_t value2; -+ ZMQ_Error rc_lzmq_socket_set_affinity1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_affinity1 = lzmq_socket_set_affinity(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_affinity1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_affinity1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif -+ -+/* method: identity */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__identity__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t value_len1 = 0; -+ char * value1 = NULL; -+ ZMQ_Error rc_lzmq_socket_identity2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_identity2 = lzmq_socket_identity(this1, value1, &(value_len1)); -+ if(!(-1 == rc_lzmq_socket_identity2)) { -+ if(value1 == NULL) lua_pushnil(L); else lua_pushlstring(L, value1,value_len1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_identity2); -+ return 2; - } -+#endif - -+/* method: set_identity */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_identity__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t value_len2; -+ const char * value2; -+ ZMQ_Error rc_lzmq_socket_set_identity1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checklstring(L,2,&(value_len2)); -+ rc_lzmq_socket_set_identity1 = lzmq_socket_set_identity(this1, value2, value_len2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_identity1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_identity1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - -+/* method: subscribe */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__subscribe__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t value_len2; -+ const char * value2; -+ ZMQ_Error rc_lzmq_socket_subscribe1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checklstring(L,2,&(value_len2)); -+ rc_lzmq_socket_subscribe1 = lzmq_socket_subscribe(this1, value2, value_len2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_subscribe1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_subscribe1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - -+/* method: unsubscribe */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__unsubscribe__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ size_t value_len2; -+ const char * value2; -+ ZMQ_Error rc_lzmq_socket_unsubscribe1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checklstring(L,2,&(value_len2)); -+ rc_lzmq_socket_unsubscribe1 = lzmq_socket_unsubscribe(this1, value2, value_len2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_unsubscribe1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_unsubscribe1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - --static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err) { -- const char *err_str = NULL; -- if(-1 == err) { -- err_str = get_zmq_strerror(); -- } -+/* method: rate */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__rate__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_rate2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_rate2 = lzmq_socket_rate(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_rate2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rate2); -+ return 2; -+} -+#endif - -- if(err_str) { -- lua_pushstring(L, err_str); -- } else { -- lua_pushnil(L); -- } -+/* method: set_rate */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_rate__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_rate1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_rate1 = lzmq_socket_set_rate(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_rate1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rate1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; - } -+#endif - --/* method: init */ --static int zmq_msg_t__init__meth(lua_State *L) { -- int this_flags1 = OBJ_UDATA_FLAG_OWN; -- zmq_msg_t * this1; -- ZMQ_Error err2 = 0; -- zmq_msg_t tmp; -- this1 = &tmp; -- err2 = zmq_msg_init(this1); -+/* method: recovery_ivl */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__recovery_ivl__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_recovery_ivl2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_recovery_ivl2 = lzmq_socket_recovery_ivl(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_recovery_ivl2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_recovery_ivl2); -+ return 2; -+} -+#endif - -- if(!(-1 == err2)) { -- obj_type_zmq_msg_t_push(L, this1, this_flags1); -+/* method: set_recovery_ivl */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_recovery_ivl__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_recovery_ivl1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_recovery_ivl1 = lzmq_socket_set_recovery_ivl(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_recovery_ivl1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_recovery_ivl1); - } else { -+ lua_pushboolean(L, 1); - lua_pushnil(L); - } -- error_code__ZMQ_Error__push(L, err2); - return 2; - } -+#endif - --/* method: init_size */ --static int zmq_msg_t__init_size__meth(lua_State *L) { -- size_t size1 = luaL_checkinteger(L,1); -- int this_flags1 = OBJ_UDATA_FLAG_OWN; -- zmq_msg_t * this1; -- ZMQ_Error err2 = 0; -- zmq_msg_t tmp; -- this1 = &tmp; -- err2 = zmq_msg_init_size(this1, size1); -- -- if(!(-1 == err2)) { -- obj_type_zmq_msg_t_push(L, this1, this_flags1); -+/* method: mcast_loop */ -+#if (VERSION_2_0) -+static int ZMQ_Socket__mcast_loop__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_mcast_loop2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_mcast_loop2 = lzmq_socket_mcast_loop(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_mcast_loop2)) { -+ lua_pushinteger(L, value1); - } else { - lua_pushnil(L); - } -- error_code__ZMQ_Error__push(L, err2); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_mcast_loop2); - return 2; - } -+#endif - --/* method: init_data */ --static int zmq_msg_t__init_data__meth(lua_State *L) { -- size_t data_len1; -- const char * data1 = luaL_checklstring(L,1,&(data_len1)); -- int this_flags1 = OBJ_UDATA_FLAG_OWN; -- zmq_msg_t * this1; -- ZMQ_Error err2 = 0; -- zmq_msg_t tmp; -- this1 = &tmp; -- err2 = zmq_msg_init_size(this1, data_len1); -- if(0 == err2) { -- /* fill message */ -- memcpy(zmq_msg_data(this1), data1, data_len1); -- } -+/* method: set_mcast_loop */ -+#if (VERSION_2_0) -+static int ZMQ_Socket__set_mcast_loop__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_mcast_loop1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_mcast_loop1 = lzmq_socket_set_mcast_loop(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_mcast_loop1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_mcast_loop1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} -+#endif - -- if(!(-1 == err2)) { -- obj_type_zmq_msg_t_push(L, this1, this_flags1); -+/* method: sndbuf */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__sndbuf__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_sndbuf2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_sndbuf2 = lzmq_socket_sndbuf(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_sndbuf2)) { -+ lua_pushinteger(L, value1); - } else { - lua_pushnil(L); - } -- error_code__ZMQ_Error__push(L, err2); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndbuf2); - return 2; - } -+#endif - --/* method: delete */ --static int zmq_msg_t__delete__meth(lua_State *L) { -- int this_flags1 = 0; -- zmq_msg_t * this1 = obj_type_zmq_msg_t_delete(L,1,&(this_flags1)); -- ZMQ_Error rc_zmq_msg_close1 = 0; -- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } -- rc_zmq_msg_close1 = zmq_msg_close(this1); -+/* method: set_sndbuf */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_sndbuf__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_sndbuf1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_sndbuf1 = lzmq_socket_set_sndbuf(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_msg_close1)) { -+ if((-1 == rc_lzmq_socket_set_sndbuf1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndbuf1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: close */ --static int zmq_msg_t__close__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- ZMQ_Error rc_zmq_msg_close1 = 0; -- rc_zmq_msg_close1 = zmq_msg_close(this1); -+/* method: rcvbuf */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__rcvbuf__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_rcvbuf2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_rcvbuf2 = lzmq_socket_rcvbuf(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_rcvbuf2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvbuf2); -+ return 2; -+} -+#endif -+ -+/* method: set_rcvbuf */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__set_rcvbuf__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_rcvbuf1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_rcvbuf1 = lzmq_socket_set_rcvbuf(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_msg_close1)) { -+ if((-1 == rc_lzmq_socket_set_rcvbuf1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvbuf1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: move */ --static int zmq_msg_t__move__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- zmq_msg_t * src2 = obj_type_zmq_msg_t_check(L,2); -- ZMQ_Error rc_zmq_msg_move1 = 0; -- rc_zmq_msg_move1 = zmq_msg_move(this1, src2); -- /* check for error. */ -- if((-1 == rc_zmq_msg_move1)) { -+/* method: rcvmore */ -+#if (VERSION_2_0|VERSION_3_0) -+static int ZMQ_Socket__rcvmore__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_rcvmore2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_rcvmore2 = lzmq_socket_rcvmore(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_rcvmore2)) { -+ lua_pushinteger(L, value1); -+ } else { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_msg_move1); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvmore2); -+ return 2; -+} -+#endif -+ -+/* method: fd */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__fd__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_fd2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_fd2 = lzmq_socket_fd(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_fd2)) { -+ lua_pushinteger(L, value1); - } else { -- lua_pushboolean(L, 1); - lua_pushnil(L); - } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_fd2); - return 2; - } -+#endif - --/* method: copy */ --static int zmq_msg_t__copy__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- zmq_msg_t * src2 = obj_type_zmq_msg_t_check(L,2); -- ZMQ_Error rc_zmq_msg_copy1 = 0; -- rc_zmq_msg_copy1 = zmq_msg_copy(this1, src2); -- /* check for error. */ -- if((-1 == rc_zmq_msg_copy1)) { -+/* method: events */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__events__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_events2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_events2 = lzmq_socket_events(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_events2)) { -+ lua_pushinteger(L, value1); -+ } else { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_msg_copy1); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_events2); -+ return 2; -+} -+#endif -+ -+/* method: type */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__type__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_type2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_type2 = lzmq_socket_type(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_type2)) { -+ lua_pushinteger(L, value1); - } else { -- lua_pushboolean(L, 1); - lua_pushnil(L); - } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_type2); - return 2; - } -+#endif - --/* method: set_data */ --static int zmq_msg_t__set_data__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- size_t data_len2; -- const char * data2 = luaL_checklstring(L,2,&(data_len2)); -- ZMQ_Error err1 = 0; -- /* check message data size. */ -- if(zmq_msg_size(this1) != data_len2) { -- /* need to resize message. */ -- zmq_msg_close(this1); /* close old message, to free old data. */ -- err1 = zmq_msg_init_size(this1, data_len2); /* re-initialize message. */ -- if(0 != err1) { -- luaL_error(L, "set_data() failed: %s", get_zmq_strerror()); -- } -- } -- /* copy data into message */ -- memcpy(zmq_msg_data(this1), data2, data_len2); -+/* method: linger */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__linger__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_linger2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_linger2 = lzmq_socket_linger(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_linger2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_linger2); -+ return 2; -+} -+#endif - -+/* method: set_linger */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__set_linger__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_linger1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_linger1 = lzmq_socket_set_linger(this1, value2); - /* check for error. */ -- if((-1 == err1)) { -+ if((-1 == rc_lzmq_socket_set_linger1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, err1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_linger1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: data */ --static int zmq_msg_t__data__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- void * rc_zmq_msg_data1 = NULL; -- rc_zmq_msg_data1 = zmq_msg_data(this1); -- lua_pushlightuserdata(L, rc_zmq_msg_data1); -- return 1; -+/* method: reconnect_ivl */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__reconnect_ivl__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_reconnect_ivl2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_reconnect_ivl2 = lzmq_socket_reconnect_ivl(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_reconnect_ivl2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_reconnect_ivl2); -+ return 2; - } -+#endif - --/* method: set_size */ --static int zmq_msg_t__set_size__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- size_t size2 = luaL_checkinteger(L,2); -- ZMQ_Error err1 = 0; -- /* check message data size. */ -- if(zmq_msg_size(this1) != size2) { -- /* need to resize message. */ -- zmq_msg_close(this1); /* close old message, to free old data. */ -- err1 = zmq_msg_init_size(this1, size2); /* re-initialize message. */ -- if(0 != err1) { -- luaL_error(L, "set_size() failed: %s", get_zmq_strerror()); -- } -- } -- -+/* method: set_reconnect_ivl */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__set_reconnect_ivl__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_reconnect_ivl1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_reconnect_ivl1 = lzmq_socket_set_reconnect_ivl(this1, value2); - /* check for error. */ -- if((-1 == err1)) { -+ if((-1 == rc_lzmq_socket_set_reconnect_ivl1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, err1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_reconnect_ivl1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: size */ --static int zmq_msg_t__size__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- size_t rc_zmq_msg_size1 = 0; -- rc_zmq_msg_size1 = zmq_msg_size(this1); -- lua_pushinteger(L, rc_zmq_msg_size1); -- return 1; --} -- --/* method: __tostring */ --static int zmq_msg_t____tostring__meth(lua_State *L) { -- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); -- size_t data_len1 = 0; -- const char * data1 = NULL; -- data1 = zmq_msg_data(this1); -- data_len1 = zmq_msg_size(this1); -- -- if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); -- return 1; -+/* method: backlog */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__backlog__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_backlog2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_backlog2 = lzmq_socket_backlog(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_backlog2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_backlog2); -+ return 2; - } -+#endif - --/* method: close */ --static int ZMQ_Socket__close__meth(lua_State *L) { -- int this_flags1 = 0; -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_delete(L,1,&(this_flags1)); -- ZMQ_Error rc_zmq_close1 = 0; -- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } -- rc_zmq_close1 = zmq_close(this1); -+/* method: set_backlog */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__set_backlog__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_backlog1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_backlog1 = lzmq_socket_set_backlog(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_close1)) { -+ if((-1 == rc_lzmq_socket_set_backlog1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_close1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_backlog1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: bind */ --static int ZMQ_Socket__bind__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- size_t addr_len2; -- const char * addr2 = luaL_checklstring(L,2,&(addr_len2)); -- ZMQ_Error rc_zmq_bind1 = 0; -- rc_zmq_bind1 = zmq_bind(this1, addr2); -+/* method: recovery_ivl_msec */ -+#if (VERSION_2_1) -+static int ZMQ_Socket__recovery_ivl_msec__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int64_t value1 = 0; -+ ZMQ_Error rc_lzmq_socket_recovery_ivl_msec2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_recovery_ivl_msec2 = lzmq_socket_recovery_ivl_msec(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_recovery_ivl_msec2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_recovery_ivl_msec2); -+ return 2; -+} -+#endif -+ -+/* method: set_recovery_ivl_msec */ -+#if (VERSION_2_1) -+static int ZMQ_Socket__set_recovery_ivl_msec__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int64_t value2; -+ ZMQ_Error rc_lzmq_socket_set_recovery_ivl_msec1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_recovery_ivl_msec1 = lzmq_socket_set_recovery_ivl_msec(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_bind1)) { -+ if((-1 == rc_lzmq_socket_set_recovery_ivl_msec1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_bind1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_recovery_ivl_msec1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: connect */ --static int ZMQ_Socket__connect__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- size_t addr_len2; -- const char * addr2 = luaL_checklstring(L,2,&(addr_len2)); -- ZMQ_Error rc_zmq_connect1 = 0; -- rc_zmq_connect1 = zmq_connect(this1, addr2); -+/* method: reconnect_ivl_max */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__reconnect_ivl_max__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_reconnect_ivl_max2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_reconnect_ivl_max2 = lzmq_socket_reconnect_ivl_max(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_reconnect_ivl_max2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_reconnect_ivl_max2); -+ return 2; -+} -+#endif -+ -+/* method: set_reconnect_ivl_max */ -+#if (VERSION_2_1|VERSION_3_0) -+static int ZMQ_Socket__set_reconnect_ivl_max__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_reconnect_ivl_max1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_reconnect_ivl_max1 = lzmq_socket_set_reconnect_ivl_max(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_connect1)) { -+ if((-1 == rc_lzmq_socket_set_reconnect_ivl_max1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_connect1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_reconnect_ivl_max1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -- --/* method: setopt */ --static int ZMQ_Socket__setopt__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- uint32_t opt2 = luaL_checkinteger(L,2); -- ZMQ_Error err1 = 0; -- size_t val_len; -- const void *val; -- --#if VERSION_2_1 -- socket_t fd_val; - #endif -- int int_val; -- uint32_t uint32_val; -- uint64_t uint64_val; -- int64_t int64_val; -- -- if(opt2 > MAX_OPTS) { -- return luaL_argerror(L, 2, "Invalid socket option."); -- } - -- switch(opt_types[opt2]) { --#if VERSION_2_1 -- case OPT_TYPE_FD: -- fd_val = luaL_checklong(L, 3); -- val = &fd_val; -- val_len = sizeof(fd_val); -- break; -+/* method: maxmsgsize */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__maxmsgsize__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int64_t value1 = 0; -+ ZMQ_Error rc_lzmq_socket_maxmsgsize2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_maxmsgsize2 = lzmq_socket_maxmsgsize(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_maxmsgsize2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_maxmsgsize2); -+ return 2; -+} - #endif -- case OPT_TYPE_INT: -- int_val = luaL_checklong(L, 3); -- val = &int_val; -- val_len = sizeof(int_val); -- break; -- case OPT_TYPE_UINT32: -- uint32_val = luaL_checklong(L, 3); -- val = &uint32_val; -- val_len = sizeof(uint32_val); -- break; -- case OPT_TYPE_UINT64: -- uint64_val = luaL_checklong(L, 3); -- val = &uint64_val; -- val_len = sizeof(uint64_val); -- break; -- case OPT_TYPE_INT64: -- int64_val = luaL_checklong(L, 3); -- val = &int64_val; -- val_len = sizeof(int64_val); -- break; -- case OPT_TYPE_STR: -- val = luaL_checklstring(L, 3, &(val_len)); -- break; -- default: -- printf("Invalid socket option type, this shouldn't happen.\n"); -- abort(); -- break; -- } -- err1 = zmq_setsockopt(this1, opt2, val, val_len); - -+/* method: set_maxmsgsize */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__set_maxmsgsize__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int64_t value2; -+ ZMQ_Error rc_lzmq_socket_set_maxmsgsize1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_maxmsgsize1 = lzmq_socket_set_maxmsgsize(this1, value2); - /* check for error. */ -- if((-1 == err1)) { -+ if((-1 == rc_lzmq_socket_set_maxmsgsize1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, err1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_maxmsgsize1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -- --/* method: getopt */ --static int ZMQ_Socket__getopt__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- uint32_t opt2 = luaL_checkinteger(L,2); -- ZMQ_Error err2 = 0; -- size_t val_len; -- --#if VERSION_2_1 -- socket_t fd_val; - #endif -- int int_val; -- uint32_t uint32_val; -- uint64_t uint64_val; -- int64_t int64_val; --#define STR_MAX 255 -- char str_val[STR_MAX]; - -- if(opt2 > MAX_OPTS) { -- lua_pushnil(L); -- lua_pushliteral(L, "Invalid socket option."); -- return 2; -- } -+/* method: sndhwm */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__sndhwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_sndhwm2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_sndhwm2 = lzmq_socket_sndhwm(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_sndhwm2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndhwm2); -+ return 2; -+} -+#endif - -- switch(opt_types[opt2]) { --#if VERSION_2_1 -- case OPT_TYPE_FD: -- val_len = sizeof(fd_val); -- err2 = zmq_getsockopt(this1, opt2, &fd_val, &val_len); -- if(0 == err2) { -- lua_pushinteger(L, (lua_Integer)fd_val); -- return 1; -- } -- break; -+/* method: set_sndhwm */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__set_sndhwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_sndhwm1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_sndhwm1 = lzmq_socket_set_sndhwm(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_sndhwm1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndhwm1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - #endif -- case OPT_TYPE_INT: -- val_len = sizeof(int_val); -- err2 = zmq_getsockopt(this1, opt2, &int_val, &val_len); -- if(0 == err2) { -- lua_pushinteger(L, (lua_Integer)int_val); -- return 1; -- } -- break; -- case OPT_TYPE_UINT32: -- val_len = sizeof(uint32_val); -- err2 = zmq_getsockopt(this1, opt2, &uint32_val, &val_len); -- if(0 == err2) { -- lua_pushinteger(L, (lua_Integer)uint32_val); -- return 1; -- } -- break; -- case OPT_TYPE_UINT64: -- val_len = sizeof(uint64_val); -- err2 = zmq_getsockopt(this1, opt2, &uint64_val, &val_len); -- if(0 == err2) { -- lua_pushinteger(L, (lua_Integer)uint64_val); -- return 1; -- } -- break; -- case OPT_TYPE_INT64: -- val_len = sizeof(int64_val); -- err2 = zmq_getsockopt(this1, opt2, &int64_val, &val_len); -- if(0 == err2) { -- lua_pushinteger(L, (lua_Integer)int64_val); -- return 1; -- } -- break; -- case OPT_TYPE_STR: -- val_len = STR_MAX; -- err2 = zmq_getsockopt(this1, opt2, str_val, &val_len); -- if(0 == err2) { -- lua_pushlstring(L, str_val, val_len); -- return 1; -- } --#undef STR_MAX -- break; -- default: -- printf("Invalid socket option type, this shouldn't happen.\n"); -- abort(); -- break; -- } -- lua_pushnil(L); - -- error_code__ZMQ_Error__push(L, err2); -+/* method: rcvhwm */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__rcvhwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_rcvhwm2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_rcvhwm2 = lzmq_socket_rcvhwm(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_rcvhwm2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvhwm2); - return 2; - } -+#endif - --/* method: events */ --static int ZMQ_Socket__events__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- uint32_t events1 = 0; -- ZMQ_Error err2 = 0; --#if VERSION_2_1 -- size_t val_len = sizeof(events1); -- err2 = zmq_getsockopt(this1, ZMQ_EVENTS, &(events1), &val_len); --#else -- luaL_error(L, "'events' method only supported in 0MQ version >= 2.1"); -+/* method: set_rcvhwm */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__set_rcvhwm__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_rcvhwm1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_rcvhwm1 = lzmq_socket_set_rcvhwm(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_rcvhwm1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvhwm1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } -+ return 2; -+} - #endif - -- if(!(-1 == err2)) { -- lua_pushinteger(L, events1); -+/* method: multicast_hops */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__multicast_hops__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_multicast_hops2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_multicast_hops2 = lzmq_socket_multicast_hops(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_multicast_hops2)) { -+ lua_pushinteger(L, value1); - } else { - lua_pushnil(L); - } -- error_code__ZMQ_Error__push(L, err2); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_multicast_hops2); - return 2; - } -+#endif - --/* method: send_msg */ --static int ZMQ_Socket__send_msg__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- zmq_msg_t * msg2 = obj_type_zmq_msg_t_check(L,2); -- int flags3 = luaL_optinteger(L,3,0); -- ZMQ_Error rc_zmq_send1 = 0; -- rc_zmq_send1 = zmq_send(this1, msg2, flags3); -+/* method: set_multicast_hops */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__set_multicast_hops__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_multicast_hops1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_multicast_hops1 = lzmq_socket_set_multicast_hops(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_send1)) { -+ if((-1 == rc_lzmq_socket_set_multicast_hops1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_send1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_multicast_hops1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: send */ --static int ZMQ_Socket__send__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- size_t data_len2; -- const char * data2 = luaL_checklstring(L,2,&(data_len2)); -- int flags3 = luaL_optinteger(L,3,0); -- ZMQ_Error err1 = 0; -- err1 = simple_zmq_send(this1, data2, data_len2, flags3); -+/* method: rcvtimeo */ -+#if (VERSION_2_2|VERSION_3_0) -+static int ZMQ_Socket__rcvtimeo__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_rcvtimeo2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_rcvtimeo2 = lzmq_socket_rcvtimeo(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_rcvtimeo2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvtimeo2); -+ return 2; -+} -+#endif - -+/* method: set_rcvtimeo */ -+#if (VERSION_2_2|VERSION_3_0) -+static int ZMQ_Socket__set_rcvtimeo__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_rcvtimeo1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_rcvtimeo1 = lzmq_socket_set_rcvtimeo(this1, value2); - /* check for error. */ -- if((-1 == err1)) { -+ if((-1 == rc_lzmq_socket_set_rcvtimeo1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, err1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvtimeo1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif -+ -+/* method: sndtimeo */ -+#if (VERSION_2_2|VERSION_3_0) -+static int ZMQ_Socket__sndtimeo__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_sndtimeo2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_sndtimeo2 = lzmq_socket_sndtimeo(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_sndtimeo2)) { -+ lua_pushinteger(L, value1); -+ } else { -+ lua_pushnil(L); -+ } -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndtimeo2); -+ return 2; -+} -+#endif - --/* method: recv_msg */ --static int ZMQ_Socket__recv_msg__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- zmq_msg_t * msg2 = obj_type_zmq_msg_t_check(L,2); -- int flags3 = luaL_optinteger(L,3,0); -- ZMQ_Error rc_zmq_recv1 = 0; -- rc_zmq_recv1 = zmq_recv(this1, msg2, flags3); -+/* method: set_sndtimeo */ -+#if (VERSION_2_2|VERSION_3_0) -+static int ZMQ_Socket__set_sndtimeo__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_sndtimeo1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_sndtimeo1 = lzmq_socket_set_sndtimeo(this1, value2); - /* check for error. */ -- if((-1 == rc_zmq_recv1)) { -+ if((-1 == rc_lzmq_socket_set_sndtimeo1)) { - lua_pushnil(L); -- error_code__ZMQ_Error__push(L, rc_zmq_recv1); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndtimeo1); - } else { - lua_pushboolean(L, 1); - lua_pushnil(L); - } - return 2; - } -+#endif - --/* method: recv */ --static int ZMQ_Socket__recv__meth(lua_State *L) { -- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); -- int flags2 = luaL_optinteger(L,2,0); -- size_t data_len1 = 0; -- const char * data1 = NULL; -- ZMQ_Error err2 = 0; -- zmq_msg_t msg; -- /* initialize message */ -- err2 = zmq_msg_init(&msg); -- if(0 == err2) { -- /* receive message */ -- err2 = zmq_recv(this1, &msg, flags2); -- if(0 == err2) { -- data1 = zmq_msg_data(&msg); -- data_len1 = zmq_msg_size(&msg); -- } -- } -- -- if(!(-1 == err2)) { -- if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); -+/* method: ipv4only */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__ipv4only__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value1 = 0; -+ ZMQ_Error rc_lzmq_socket_ipv4only2 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ rc_lzmq_socket_ipv4only2 = lzmq_socket_ipv4only(this1, &(value1)); -+ if(!(-1 == rc_lzmq_socket_ipv4only2)) { -+ lua_pushinteger(L, value1); - } else { - lua_pushnil(L); - } -- error_code__ZMQ_Error__push(L, err2); -- /* close message */ -- zmq_msg_close(&msg); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_ipv4only2); -+ return 2; -+} -+#endif - -+/* method: set_ipv4only */ -+#if (VERSION_3_0) -+static int ZMQ_Socket__set_ipv4only__meth(lua_State *L) { -+ ZMQ_Socket * this1; -+ int value2; -+ ZMQ_Error rc_lzmq_socket_set_ipv4only1 = 0; -+ this1 = obj_type_ZMQ_Socket_check(L,1); -+ value2 = luaL_checkinteger(L,2); -+ rc_lzmq_socket_set_ipv4only1 = lzmq_socket_set_ipv4only(this1, value2); -+ /* check for error. */ -+ if((-1 == rc_lzmq_socket_set_ipv4only1)) { -+ lua_pushnil(L); -+ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_ipv4only1); -+ } else { -+ lua_pushboolean(L, 1); -+ lua_pushnil(L); -+ } - return 2; - } -+#endif - - /* method: new */ - static int ZMQ_Poller__new__meth(lua_State *L) { -- unsigned int length1 = luaL_optinteger(L,1,10); -- int this_flags1 = OBJ_UDATA_FLAG_OWN; -- ZMQ_Poller * this1; -- ZMQ_Poller poller; -- this1 = &poller; -- this1->items = (zmq_pollitem_t *)calloc(length1, sizeof(zmq_pollitem_t)); -- this1->next = -1; -- this1->count = 0; -- this1->len = length1; -- this1->free_list = -1; -- -- obj_type_ZMQ_Poller_push(L, this1, this_flags1); -+ unsigned int length1; -+ ZMQ_Poller this1_store; -+ ZMQ_Poller * this1 = &(this1_store); -+ length1 = luaL_optinteger(L,1,10); -+ poller_init(this1, length1); -+ obj_type_ZMQ_Poller_push(L, this1); - return 1; - } - - /* method: close */ - static int ZMQ_Poller__close__meth(lua_State *L) { -- int this_flags1 = 0; -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_delete(L,1,&(this_flags1)); -- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } -- free(this1->items); -- this1->items = NULL; -- this1->next = -1; -- this1->count = 0; -- this1->len = 0; -- this1->free_list = -1; -- -+ ZMQ_Poller * this1; -+ this1 = obj_type_ZMQ_Poller_delete(L,1); -+ poller_cleanup(this1); - return 0; - } - - /* method: add */ - static int ZMQ_Poller__add__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -- short events3 = luaL_checkinteger(L,3); -+ ZMQ_Poller * this1; -+ short events3; - int idx1 = 0; - zmq_pollitem_t *item; - ZMQ_Socket *sock = NULL; - socket_t fd = 0; - -+ this1 = obj_type_ZMQ_Poller_check(L,1); -+ events3 = luaL_checkinteger(L,3); - if(lua_isuserdata(L, 2)) { - sock = obj_type_ZMQ_Socket_check(L, 2); - } else if(lua_isnumber(L, 2)) { -@@ -2777,13 +6247,15 @@ static int ZMQ_Poller__add__meth(lua_State *L) { - - /* method: modify */ - static int ZMQ_Poller__modify__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -- short events3 = luaL_checkinteger(L,3); -+ ZMQ_Poller * this1; -+ short events3; - int idx1 = 0; - zmq_pollitem_t *item; - ZMQ_Socket *sock = NULL; - socket_t fd = 0; - -+ this1 = obj_type_ZMQ_Poller_check(L,1); -+ events3 = luaL_checkinteger(L,3); - if(lua_isuserdata(L, 2)) { - sock = obj_type_ZMQ_Socket_check(L, 2); - /* find sock in items list. */ -@@ -2815,98 +6287,76 @@ static int ZMQ_Poller__modify__meth(lua_State *L) { - - /* method: remove */ - static int ZMQ_Poller__remove__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -+ ZMQ_Poller * this1; -+ int idx1 = 0; - ZMQ_Socket *sock; - socket_t fd; -- int idx; - -+ this1 = obj_type_ZMQ_Poller_check(L,1); - /* ZMQ_Socket or fd */ - if(lua_isuserdata(L, 2)) { - sock = obj_type_ZMQ_Socket_check(L, 2); - /* find sock in items list. */ -- idx = poller_find_sock_item(this1, sock); -+ idx1 = poller_find_sock_item(this1, sock); - } else if(lua_isnumber(L, 2)) { - fd = lua_tonumber(L, 2); - /* find fd in items list. */ -- idx = poller_find_fd_item(this1, fd); -+ idx1 = poller_find_fd_item(this1, fd); - } else { - return luaL_typerror(L, 2, "number or ZMQ_Socket"); - } - /* if sock/fd was found. */ -- if(idx >= 0) { -- poller_remove_item(this1, idx); -+ if(idx1 >= 0) { -+ poller_remove_item(this1, idx1); - } - -- return 0; -+ lua_pushinteger(L, idx1); -+ return 1; - } - - /* method: poll */ - static int ZMQ_Poller__poll__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -- long timeout2 = luaL_checkinteger(L,2); -- ZMQ_Error err1 = 0; -- /* poll for events */ -- err1 = poller_poll(this1, timeout2); -- if(err1 > 0) { -+ ZMQ_Poller * this1; -+ long timeout2; -+ int count1 = 0; -+ ZMQ_Error err2 = 0; -+ this1 = obj_type_ZMQ_Poller_check(L,1); -+ timeout2 = luaL_checkinteger(L,2); -+ err2 = poller_poll(this1, timeout2); -+ if(err2 > 0) { - this1->next = 0; -+ count1 = err2; - } else { - this1->next = -1; -+ count1 = 0; - } - -- /* check for error. */ -- if((-1 == err1)) { -- lua_pushnil(L); -- error_code__ZMQ_Error__push(L, err1); -+ if(!(-1 == err2)) { -+ lua_pushinteger(L, count1); - } else { -- lua_pushboolean(L, 1); - lua_pushnil(L); - } -+ error_code__ZMQ_Error__push(L, err2); - return 2; - } - --/* method: next_revents */ --static int ZMQ_Poller__next_revents__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -- short revents2 = 0; -- zmq_pollitem_t *items; -- int count; -- int idx; -- -- revents2 = -1; -- idx = this1->next; -- if(idx >= 0) { -- count = this1->count; -- items = this1->items; -- /* find next item with pending events. */ -- while(idx < count && items[idx].revents == 0) ++idx; -- /* did we find a pending event? */ -- if(idx < count) { -- /* push the event's sock/fd. */ -- if(items[idx].socket != NULL) { -- obj_type_ZMQ_Socket_push(L, items[idx].socket, 0); -- } else { -- lua_pushnumber(L, items[idx].fd); -- } -- revents2 = items[idx].revents; -- /* is this the last event. */ -- ++idx; -- this1->next = (idx < count) ? idx : -1; -- } -- } -- if(revents2 < 0) { -- /* no more pending events. */ -- lua_pushnil(L); -- this1->next = -1; -- } -- -+/* method: next_revents_idx */ -+static int ZMQ_Poller__next_revents_idx__meth(lua_State *L) { -+ ZMQ_Poller * this1; -+ int idx1 = 0; -+ int revents2 = 0; -+ this1 = obj_type_ZMQ_Poller_check(L,1); -+ idx1 = poller_next_revents(this1, &(revents2)); -+ lua_pushinteger(L, idx1); - lua_pushinteger(L, revents2); - return 2; - } - - /* method: count */ - static int ZMQ_Poller__count__meth(lua_State *L) { -- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); -+ ZMQ_Poller * this1; - int count1 = 0; -+ this1 = obj_type_ZMQ_Poller_check(L,1); - count1 = this1->count; - - lua_pushinteger(L, count1); -@@ -2916,8 +6366,9 @@ static int ZMQ_Poller__count__meth(lua_State *L) { - /* method: term */ - static int ZMQ_Ctx__term__meth(lua_State *L) { - int this_flags1 = 0; -- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_delete(L,1,&(this_flags1)); -+ ZMQ_Ctx * this1; - ZMQ_Error rc_zmq_term1 = 0; -+ this1 = obj_type_ZMQ_Ctx_delete(L,1,&(this_flags1)); - if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } - rc_zmq_term1 = zmq_term(this1); - /* check for error. */ -@@ -2933,8 +6384,9 @@ static int ZMQ_Ctx__term__meth(lua_State *L) { - - /* method: lightuserdata */ - static int ZMQ_Ctx__lightuserdata__meth(lua_State *L) { -- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_check(L,1); -+ ZMQ_Ctx * this1; - void * ptr1 = NULL; -+ this1 = obj_type_ZMQ_Ctx_check(L,1); - ptr1 = this1; - - lua_pushlightuserdata(L, ptr1); -@@ -2943,10 +6395,12 @@ static int ZMQ_Ctx__lightuserdata__meth(lua_State *L) { - - /* method: socket */ - static int ZMQ_Ctx__socket__meth(lua_State *L) { -- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_check(L,1); -- int type2 = luaL_checkinteger(L,2); -+ ZMQ_Ctx * this1; -+ int type2; - int rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN; - ZMQ_Socket * rc_zmq_socket1; -+ this1 = obj_type_ZMQ_Ctx_check(L,1); -+ type2 = luaL_checkinteger(L,2); - rc_zmq_socket1 = zmq_socket(this1, type2); - if((NULL == rc_zmq_socket1)) { - lua_pushnil(L); -@@ -2969,8 +6423,9 @@ static int ZMQ_StopWatch__start__meth(lua_State *L) { - /* method: stop */ - static int ZMQ_StopWatch__stop__meth(lua_State *L) { - int this_flags1 = 0; -- ZMQ_StopWatch * this1 = obj_type_ZMQ_StopWatch_delete(L,1,&(this_flags1)); -+ ZMQ_StopWatch * this1; - unsigned long usecs1 = 0; -+ this1 = obj_type_ZMQ_StopWatch_delete(L,1,&(this_flags1)); - if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } - usecs1 = zmq_stopwatch_stop(this1); - lua_pushinteger(L, usecs1); -@@ -2996,9 +6451,10 @@ static int zmq__version__func(lua_State *L) { - - /* method: init */ - static int zmq__init__func(lua_State *L) { -- int io_threads1 = luaL_checkinteger(L,1); -+ int io_threads1; - int rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN; - ZMQ_Ctx * rc_zmq_init1; -+ io_threads1 = luaL_optinteger(L,1,1); - rc_zmq_init1 = zmq_init(io_threads1); - if((NULL == rc_zmq_init1)) { - lua_pushnil(L); -@@ -3028,11 +6484,15 @@ static int zmq__init_ctx__func(lua_State *L) { - } - - /* method: device */ -+#if (VERSION_2_0) - static int zmq__device__func(lua_State *L) { -- int device1 = luaL_checkinteger(L,1); -- ZMQ_Socket * insock2 = obj_type_ZMQ_Socket_check(L,2); -- ZMQ_Socket * outsock3 = obj_type_ZMQ_Socket_check(L,3); -+ int device1; -+ ZMQ_Socket * insock2; -+ ZMQ_Socket * outsock3; - ZMQ_Error rc_zmq_device1 = 0; -+ device1 = luaL_checkinteger(L,1); -+ insock2 = obj_type_ZMQ_Socket_check(L,2); -+ outsock3 = obj_type_ZMQ_Socket_check(L,3); - rc_zmq_device1 = zmq_device(device1, insock2, outsock3); - /* check for error. */ - if((-1 == rc_zmq_device1)) { -@@ -3044,6 +6504,7 @@ static int zmq__device__func(lua_State *L) { - } - return 2; - } -+#endif - - /* method: stopwatch_start */ - static int zmq__stopwatch_start__func(lua_State *L) { -@@ -3056,32 +6517,452 @@ static int zmq__stopwatch_start__func(lua_State *L) { - - /* method: sleep */ - static int zmq__sleep__func(lua_State *L) { -- int seconds_1 = luaL_checkinteger(L,1); -+ int seconds_1; -+ seconds_1 = luaL_checkinteger(L,1); - zmq_sleep(seconds_1); - return 0; - } - --/* method: dump_ffi */ --static int zmq__dump_ffi__func(lua_State *L) { -- size_t ffi_code_len1 = 0; -- const char * ffi_code1 = NULL; -- ffi_code1 = zmq_ffi_lua_code; -- ffi_code_len1 = sizeof(zmq_ffi_lua_code) - 1; - -- if(ffi_code1 == NULL) lua_pushnil(L); else lua_pushlstring(L, ffi_code1,ffi_code_len1); -- return 1; --} - -+static const luaL_Reg obj_ZErrors_pub_funcs[] = { -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZErrors_methods[] = { -+ {"description", ZErrors__description__meth}, -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZErrors_metas[] = { -+ {"__index", ZErrors____index__meth}, -+ {NULL, NULL} -+}; -+ -+static const obj_const obj_ZErrors_constants[] = { -+#ifdef ELNRNG -+ {"ELNRNG", NULL, ELNRNG, CONST_NUMBER}, -+#endif -+#ifdef EPFNOSUPPORT -+ {"EPFNOSUPPORT", NULL, EPFNOSUPPORT, CONST_NUMBER}, -+#endif -+#ifdef EBADR -+ {"EBADR", NULL, EBADR, CONST_NUMBER}, -+#endif -+#ifdef ENOLINK -+ {"ENOLINK", NULL, ENOLINK, CONST_NUMBER}, -+#endif -+#ifdef ENOSTR -+ {"ENOSTR", NULL, ENOSTR, CONST_NUMBER}, -+#endif -+#ifdef ERESTART -+ {"ERESTART", NULL, ERESTART, CONST_NUMBER}, -+#endif -+#ifdef EUCLEAN -+ {"EUCLEAN", NULL, EUCLEAN, CONST_NUMBER}, -+#endif -+#ifdef ELIBSCN -+ {"ELIBSCN", NULL, ELIBSCN, CONST_NUMBER}, -+#endif -+#ifdef EROFS -+ {"EROFS", NULL, EROFS, CONST_NUMBER}, -+#endif -+#ifdef EBADE -+ {"EBADE", NULL, EBADE, CONST_NUMBER}, -+#endif -+#ifdef ENOTSOCK -+ {"ENOTSOCK", NULL, ENOTSOCK, CONST_NUMBER}, -+#endif -+#ifdef ENOTCONN -+ {"ENOTCONN", NULL, ENOTCONN, CONST_NUMBER}, -+#endif -+#ifdef EREMOTE -+ {"EREMOTE", NULL, EREMOTE, CONST_NUMBER}, -+#endif -+#ifdef ECOMM -+ {"ECOMM", NULL, ECOMM, CONST_NUMBER}, -+#endif -+#ifdef ENODATA -+ {"ENODATA", NULL, ENODATA, CONST_NUMBER}, -+#endif -+#ifdef EPERM -+ {"EPERM", NULL, EPERM, CONST_NUMBER}, -+#endif -+#ifdef EBADRQC -+ {"EBADRQC", NULL, EBADRQC, CONST_NUMBER}, -+#endif -+#ifdef ENOSR -+ {"ENOSR", NULL, ENOSR, CONST_NUMBER}, -+#endif -+#ifdef ELIBMAX -+ {"ELIBMAX", NULL, ELIBMAX, CONST_NUMBER}, -+#endif -+#ifdef EDOTDOT -+ {"EDOTDOT", NULL, EDOTDOT, CONST_NUMBER}, -+#endif -+#ifdef EFSM -+ {"EFSM", NULL, EFSM, CONST_NUMBER}, -+#endif -+#ifdef ENOPROTOOPT -+ {"ENOPROTOOPT", NULL, ENOPROTOOPT, CONST_NUMBER}, -+#endif -+#ifdef EBFONT -+ {"EBFONT", NULL, EBFONT, CONST_NUMBER}, -+#endif -+#ifdef ENOCOMPATPROTO -+ {"ENOCOMPATPROTO", NULL, ENOCOMPATPROTO, CONST_NUMBER}, -+#endif -+#ifdef EKEYREVOKED -+ {"EKEYREVOKED", NULL, EKEYREVOKED, CONST_NUMBER}, -+#endif -+#ifdef ESRMNT -+ {"ESRMNT", NULL, ESRMNT, CONST_NUMBER}, -+#endif -+#ifdef EOVERFLOW -+ {"EOVERFLOW", NULL, EOVERFLOW, CONST_NUMBER}, -+#endif -+#ifdef EDQUOT -+ {"EDQUOT", NULL, EDQUOT, CONST_NUMBER}, -+#endif -+#ifdef EFBIG -+ {"EFBIG", NULL, EFBIG, CONST_NUMBER}, -+#endif -+#ifdef EIDRM -+ {"EIDRM", NULL, EIDRM, CONST_NUMBER}, -+#endif -+#ifdef EDOM -+ {"EDOM", NULL, EDOM, CONST_NUMBER}, -+#endif -+#ifdef EPROTO -+ {"EPROTO", NULL, EPROTO, CONST_NUMBER}, -+#endif -+#ifdef EMULTIHOP -+ {"EMULTIHOP", NULL, EMULTIHOP, CONST_NUMBER}, -+#endif -+#ifdef ENOCSI -+ {"ENOCSI", NULL, ENOCSI, CONST_NUMBER}, -+#endif -+#ifdef EDEADLOCK -+ {"EDEADLOCK", NULL, EDEADLOCK, CONST_NUMBER}, -+#endif -+#ifdef ENOPKG -+ {"ENOPKG", NULL, ENOPKG, CONST_NUMBER}, -+#endif -+#ifdef EPIPE -+ {"EPIPE", NULL, EPIPE, CONST_NUMBER}, -+#endif -+#ifdef EADDRINUSE -+ {"EADDRINUSE", NULL, EADDRINUSE, CONST_NUMBER}, -+#endif -+#ifdef EFAULT -+ {"EFAULT", NULL, EFAULT, CONST_NUMBER}, -+#endif -+#ifdef EDEADLK -+ {"EDEADLK", NULL, EDEADLK, CONST_NUMBER}, -+#endif -+#ifdef ENFILE -+ {"ENFILE", NULL, ENFILE, CONST_NUMBER}, -+#endif -+#ifdef EAGAIN -+ {"EAGAIN", NULL, EAGAIN, CONST_NUMBER}, -+#endif -+#ifdef ECONNABORTED -+ {"ECONNABORTED", NULL, ECONNABORTED, CONST_NUMBER}, -+#endif -+#ifdef EMLINK -+ {"EMLINK", NULL, EMLINK, CONST_NUMBER}, -+#endif -+#ifdef EBADMSG -+ {"EBADMSG", NULL, EBADMSG, CONST_NUMBER}, -+#endif -+#ifdef ERFKILL -+ {"ERFKILL", NULL, ERFKILL, CONST_NUMBER}, -+#endif -+#ifdef ENOTTY -+ {"ENOTTY", NULL, ENOTTY, CONST_NUMBER}, -+#endif -+#ifdef ELIBACC -+ {"ELIBACC", NULL, ELIBACC, CONST_NUMBER}, -+#endif -+#ifdef ETIME -+ {"ETIME", NULL, ETIME, CONST_NUMBER}, -+#endif -+#ifdef ECHILD -+ {"ECHILD", NULL, ECHILD, CONST_NUMBER}, -+#endif -+#ifdef ENOTRECOVERABLE -+ {"ENOTRECOVERABLE", NULL, ENOTRECOVERABLE, CONST_NUMBER}, -+#endif -+#ifdef EISCONN -+ {"EISCONN", NULL, EISCONN, CONST_NUMBER}, -+#endif -+#ifdef ENAVAIL -+ {"ENAVAIL", NULL, ENAVAIL, CONST_NUMBER}, -+#endif -+#ifdef EDESTADDRREQ -+ {"EDESTADDRREQ", NULL, EDESTADDRREQ, CONST_NUMBER}, -+#endif -+#ifdef EREMOTEIO -+ {"EREMOTEIO", NULL, EREMOTEIO, CONST_NUMBER}, -+#endif -+#ifdef ESTALE -+ {"ESTALE", NULL, ESTALE, CONST_NUMBER}, -+#endif -+#ifdef ESTRPIPE -+ {"ESTRPIPE", NULL, ESTRPIPE, CONST_NUMBER}, -+#endif -+#ifdef EHOSTUNREACH -+ {"EHOSTUNREACH", NULL, EHOSTUNREACH, CONST_NUMBER}, -+#endif -+#ifdef ENOTBLK -+ {"ENOTBLK", NULL, ENOTBLK, CONST_NUMBER}, -+#endif -+#ifdef EEXIST -+ {"EEXIST", NULL, EEXIST, CONST_NUMBER}, -+#endif -+#ifdef ENOTDIR -+ {"ENOTDIR", NULL, ENOTDIR, CONST_NUMBER}, -+#endif -+#ifdef EWOULDBLOCK -+ {"EWOULDBLOCK", NULL, EWOULDBLOCK, CONST_NUMBER}, -+#endif -+#ifdef EREMCHG -+ {"EREMCHG", NULL, EREMCHG, CONST_NUMBER}, -+#endif -+#ifdef ELOOP -+ {"ELOOP", NULL, ELOOP, CONST_NUMBER}, -+#endif -+#ifdef ENOTUNIQ -+ {"ENOTUNIQ", NULL, ENOTUNIQ, CONST_NUMBER}, -+#endif -+#ifdef EMEDIUMTYPE -+ {"EMEDIUMTYPE", NULL, EMEDIUMTYPE, CONST_NUMBER}, -+#endif -+#ifdef ENOLCK -+ {"ENOLCK", NULL, ENOLCK, CONST_NUMBER}, -+#endif -+#ifdef EUNATCH -+ {"EUNATCH", NULL, EUNATCH, CONST_NUMBER}, -+#endif -+#ifdef EPROTONOSUPPORT -+ {"EPROTONOSUPPORT", NULL, EPROTONOSUPPORT, CONST_NUMBER}, -+#endif -+#ifdef EHOSTDOWN -+ {"EHOSTDOWN", NULL, EHOSTDOWN, CONST_NUMBER}, -+#endif -+#ifdef EINTR -+ {"EINTR", NULL, EINTR, CONST_NUMBER}, -+#endif -+#ifdef ETIMEDOUT -+ {"ETIMEDOUT", NULL, ETIMEDOUT, CONST_NUMBER}, -+#endif -+#ifdef EOWNERDEAD -+ {"EOWNERDEAD", NULL, EOWNERDEAD, CONST_NUMBER}, -+#endif -+#ifdef EL2HLT -+ {"EL2HLT", NULL, EL2HLT, CONST_NUMBER}, -+#endif -+#ifdef ETERM -+ {"ETERM", NULL, ETERM, CONST_NUMBER}, -+#endif -+#ifdef EBADSLT -+ {"EBADSLT", NULL, EBADSLT, CONST_NUMBER}, -+#endif -+#ifdef ESHUTDOWN -+ {"ESHUTDOWN", NULL, ESHUTDOWN, CONST_NUMBER}, -+#endif -+#ifdef EIO -+ {"EIO", NULL, EIO, CONST_NUMBER}, -+#endif -+#ifdef ENOANO -+ {"ENOANO", NULL, ENOANO, CONST_NUMBER}, -+#endif -+#ifdef EACCES -+ {"EACCES", NULL, EACCES, CONST_NUMBER}, -+#endif -+#ifdef EOPNOTSUPP -+ {"EOPNOTSUPP", NULL, EOPNOTSUPP, CONST_NUMBER}, -+#endif -+#ifdef EKEYREJECTED -+ {"EKEYREJECTED", NULL, EKEYREJECTED, CONST_NUMBER}, -+#endif -+#ifdef ESOCKTNOSUPPORT -+ {"ESOCKTNOSUPPORT", NULL, ESOCKTNOSUPPORT, CONST_NUMBER}, -+#endif -+#ifdef ENOKEY -+ {"ENOKEY", NULL, ENOKEY, CONST_NUMBER}, -+#endif -+#ifdef ELIBBAD -+ {"ELIBBAD", NULL, ELIBBAD, CONST_NUMBER}, -+#endif -+#ifdef ENODEV -+ {"ENODEV", NULL, ENODEV, CONST_NUMBER}, -+#endif -+#ifdef ECANCELED -+ {"ECANCELED", NULL, ECANCELED, CONST_NUMBER}, -+#endif -+#ifdef ENOBUFS -+ {"ENOBUFS", NULL, ENOBUFS, CONST_NUMBER}, -+#endif -+#ifdef ENETUNREACH -+ {"ENETUNREACH", NULL, ENETUNREACH, CONST_NUMBER}, -+#endif -+#ifdef EL3HLT -+ {"EL3HLT", NULL, EL3HLT, CONST_NUMBER}, -+#endif -+#ifdef ENXIO -+ {"ENXIO", NULL, ENXIO, CONST_NUMBER}, -+#endif -+#ifdef ENETRESET -+ {"ENETRESET", NULL, ENETRESET, CONST_NUMBER}, -+#endif -+#ifdef ENOENT -+ {"ENOENT", NULL, ENOENT, CONST_NUMBER}, -+#endif -+#ifdef ENOMSG -+ {"ENOMSG", NULL, ENOMSG, CONST_NUMBER}, -+#endif -+#ifdef EL3RST -+ {"EL3RST", NULL, EL3RST, CONST_NUMBER}, -+#endif -+#ifdef EMFILE -+ {"EMFILE", NULL, EMFILE, CONST_NUMBER}, -+#endif -+#ifdef ENOEXEC -+ {"ENOEXEC", NULL, ENOEXEC, CONST_NUMBER}, -+#endif -+#ifdef ENOTEMPTY -+ {"ENOTEMPTY", NULL, ENOTEMPTY, CONST_NUMBER}, -+#endif -+#ifdef EMTHREAD -+ {"EMTHREAD", NULL, EMTHREAD, CONST_NUMBER}, -+#endif -+#ifdef EISNAM -+ {"EISNAM", NULL, EISNAM, CONST_NUMBER}, -+#endif -+#ifdef EINVAL -+ {"EINVAL", NULL, EINVAL, CONST_NUMBER}, -+#endif -+#ifdef ERANGE -+ {"ERANGE", NULL, ERANGE, CONST_NUMBER}, -+#endif -+#ifdef E2BIG -+ {"E2BIG", NULL, E2BIG, CONST_NUMBER}, -+#endif -+#ifdef ENOTNAM -+ {"ENOTNAM", NULL, ENOTNAM, CONST_NUMBER}, -+#endif -+#ifdef ENONET -+ {"ENONET", NULL, ENONET, CONST_NUMBER}, -+#endif -+#ifdef EADDRNOTAVAIL -+ {"EADDRNOTAVAIL", NULL, EADDRNOTAVAIL, CONST_NUMBER}, -+#endif -+#ifdef ENOSYS -+ {"ENOSYS", NULL, ENOSYS, CONST_NUMBER}, -+#endif -+#ifdef EINPROGRESS -+ {"EINPROGRESS", NULL, EINPROGRESS, CONST_NUMBER}, -+#endif -+#ifdef EBUSY -+ {"EBUSY", NULL, EBUSY, CONST_NUMBER}, -+#endif -+#ifdef EBADFD -+ {"EBADFD", NULL, EBADFD, CONST_NUMBER}, -+#endif -+#ifdef EISDIR -+ {"EISDIR", NULL, EISDIR, CONST_NUMBER}, -+#endif -+#ifdef EADV -+ {"EADV", NULL, EADV, CONST_NUMBER}, -+#endif -+#ifdef ECONNRESET -+ {"ECONNRESET", NULL, ECONNRESET, CONST_NUMBER}, -+#endif -+#ifdef ENOSPC -+ {"ENOSPC", NULL, ENOSPC, CONST_NUMBER}, -+#endif -+#ifdef ETOOMANYREFS -+ {"ETOOMANYREFS", NULL, ETOOMANYREFS, CONST_NUMBER}, -+#endif -+#ifdef EXFULL -+ {"EXFULL", NULL, EXFULL, CONST_NUMBER}, -+#endif -+#ifdef EPROTOTYPE -+ {"EPROTOTYPE", NULL, EPROTOTYPE, CONST_NUMBER}, -+#endif -+#ifdef ESRCH -+ {"ESRCH", NULL, ESRCH, CONST_NUMBER}, -+#endif -+#ifdef EMSGSIZE -+ {"EMSGSIZE", NULL, EMSGSIZE, CONST_NUMBER}, -+#endif -+#ifdef EAFNOSUPPORT -+ {"EAFNOSUPPORT", NULL, EAFNOSUPPORT, CONST_NUMBER}, -+#endif -+#ifdef ESPIPE -+ {"ESPIPE", NULL, ESPIPE, CONST_NUMBER}, -+#endif -+#ifdef ENETDOWN -+ {"ENETDOWN", NULL, ENETDOWN, CONST_NUMBER}, -+#endif -+#ifdef ECHRNG -+ {"ECHRNG", NULL, ECHRNG, CONST_NUMBER}, -+#endif -+#ifdef ENOMEM -+ {"ENOMEM", NULL, ENOMEM, CONST_NUMBER}, -+#endif -+#ifdef ECONNREFUSED -+ {"ECONNREFUSED", NULL, ECONNREFUSED, CONST_NUMBER}, -+#endif -+#ifdef ETXTBSY -+ {"ETXTBSY", NULL, ETXTBSY, CONST_NUMBER}, -+#endif -+#ifdef EKEYEXPIRED -+ {"EKEYEXPIRED", NULL, EKEYEXPIRED, CONST_NUMBER}, -+#endif -+#ifdef ENOMEDIUM -+ {"ENOMEDIUM", NULL, ENOMEDIUM, CONST_NUMBER}, -+#endif -+#ifdef EUSERS -+ {"EUSERS", NULL, EUSERS, CONST_NUMBER}, -+#endif -+#ifdef EILSEQ -+ {"EILSEQ", NULL, EILSEQ, CONST_NUMBER}, -+#endif -+#ifdef ELIBEXEC -+ {"ELIBEXEC", NULL, ELIBEXEC, CONST_NUMBER}, -+#endif -+#ifdef EALREADY -+ {"EALREADY", NULL, EALREADY, CONST_NUMBER}, -+#endif -+#ifdef ENAMETOOLONG -+ {"ENAMETOOLONG", NULL, ENAMETOOLONG, CONST_NUMBER}, -+#endif -+#ifdef EXDEV -+ {"EXDEV", NULL, EXDEV, CONST_NUMBER}, -+#endif -+#ifdef EBADF -+ {"EBADF", NULL, EBADF, CONST_NUMBER}, -+#endif -+#ifdef EL2NSYNC -+ {"EL2NSYNC", NULL, EL2NSYNC, CONST_NUMBER}, -+#endif -+ {NULL, NULL, 0.0 , 0} -+}; - -+static const reg_impl obj_ZErrors_implements[] = { -+ {NULL, NULL} -+}; - --static const luaL_reg obj_zmq_msg_t_pub_funcs[] = { -+static const luaL_Reg obj_zmq_msg_t_pub_funcs[] = { - {"init", zmq_msg_t__init__meth}, - {"init_size", zmq_msg_t__init_size__meth}, - {"init_data", zmq_msg_t__init_data__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_zmq_msg_t_methods[] = { -+static const luaL_Reg obj_zmq_msg_t_methods[] = { - {"close", zmq_msg_t__close__meth}, - {"move", zmq_msg_t__move__meth}, - {"copy", zmq_msg_t__copy__meth}, -@@ -3092,7 +6973,7 @@ static const luaL_reg obj_zmq_msg_t_methods[] = { - {NULL, NULL} - }; - --static const luaL_reg obj_zmq_msg_t_metas[] = { -+static const luaL_Reg obj_zmq_msg_t_metas[] = { - {"__gc", zmq_msg_t__delete__meth}, - {"__tostring", zmq_msg_t____tostring__meth}, - {"__eq", obj_simple_udata_default_equal}, -@@ -3111,25 +6992,176 @@ static const obj_const obj_zmq_msg_t_constants[] = { - {NULL, NULL, 0.0 , 0} - }; - --static const luaL_reg obj_ZMQ_Socket_pub_funcs[] = { -+static const reg_impl obj_zmq_msg_t_implements[] = { -+ { "BufferIF", &(zmq_msg_t_Buffer) }, -+ -+ { "MutableBufferIF", &(zmq_msg_t_MutableBuffer) }, -+ -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZMQ_Socket_pub_funcs[] = { - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Socket_methods[] = { -+static const luaL_Reg obj_ZMQ_Socket_methods[] = { - {"close", ZMQ_Socket__close__meth}, - {"bind", ZMQ_Socket__bind__meth}, - {"connect", ZMQ_Socket__connect__meth}, - {"setopt", ZMQ_Socket__setopt__meth}, - {"getopt", ZMQ_Socket__getopt__meth}, -- {"events", ZMQ_Socket__events__meth}, - {"send_msg", ZMQ_Socket__send_msg__meth}, - {"send", ZMQ_Socket__send__meth}, - {"recv_msg", ZMQ_Socket__recv_msg__meth}, - {"recv", ZMQ_Socket__recv__meth}, -+#if (VERSION_2_0|VERSION_3_0) -+ {"hwm", ZMQ_Socket__hwm__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_hwm", ZMQ_Socket__set_hwm__meth}, -+#endif -+#if (VERSION_2_0) -+ {"swap", ZMQ_Socket__swap__meth}, -+#endif -+#if (VERSION_2_0) -+ {"set_swap", ZMQ_Socket__set_swap__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"affinity", ZMQ_Socket__affinity__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_affinity", ZMQ_Socket__set_affinity__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"identity", ZMQ_Socket__identity__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_identity", ZMQ_Socket__set_identity__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"subscribe", ZMQ_Socket__subscribe__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"unsubscribe", ZMQ_Socket__unsubscribe__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"rate", ZMQ_Socket__rate__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_rate", ZMQ_Socket__set_rate__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"recovery_ivl", ZMQ_Socket__recovery_ivl__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_recovery_ivl", ZMQ_Socket__set_recovery_ivl__meth}, -+#endif -+#if (VERSION_2_0) -+ {"mcast_loop", ZMQ_Socket__mcast_loop__meth}, -+#endif -+#if (VERSION_2_0) -+ {"set_mcast_loop", ZMQ_Socket__set_mcast_loop__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"sndbuf", ZMQ_Socket__sndbuf__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_sndbuf", ZMQ_Socket__set_sndbuf__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"rcvbuf", ZMQ_Socket__rcvbuf__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"set_rcvbuf", ZMQ_Socket__set_rcvbuf__meth}, -+#endif -+#if (VERSION_2_0|VERSION_3_0) -+ {"rcvmore", ZMQ_Socket__rcvmore__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"fd", ZMQ_Socket__fd__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"events", ZMQ_Socket__events__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"type", ZMQ_Socket__type__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"linger", ZMQ_Socket__linger__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"set_linger", ZMQ_Socket__set_linger__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"reconnect_ivl", ZMQ_Socket__reconnect_ivl__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"set_reconnect_ivl", ZMQ_Socket__set_reconnect_ivl__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"backlog", ZMQ_Socket__backlog__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"set_backlog", ZMQ_Socket__set_backlog__meth}, -+#endif -+#if (VERSION_2_1) -+ {"recovery_ivl_msec", ZMQ_Socket__recovery_ivl_msec__meth}, -+#endif -+#if (VERSION_2_1) -+ {"set_recovery_ivl_msec", ZMQ_Socket__set_recovery_ivl_msec__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"reconnect_ivl_max", ZMQ_Socket__reconnect_ivl_max__meth}, -+#endif -+#if (VERSION_2_1|VERSION_3_0) -+ {"set_reconnect_ivl_max", ZMQ_Socket__set_reconnect_ivl_max__meth}, -+#endif -+#if (VERSION_3_0) -+ {"maxmsgsize", ZMQ_Socket__maxmsgsize__meth}, -+#endif -+#if (VERSION_3_0) -+ {"set_maxmsgsize", ZMQ_Socket__set_maxmsgsize__meth}, -+#endif -+#if (VERSION_3_0) -+ {"sndhwm", ZMQ_Socket__sndhwm__meth}, -+#endif -+#if (VERSION_3_0) -+ {"set_sndhwm", ZMQ_Socket__set_sndhwm__meth}, -+#endif -+#if (VERSION_3_0) -+ {"rcvhwm", ZMQ_Socket__rcvhwm__meth}, -+#endif -+#if (VERSION_3_0) -+ {"set_rcvhwm", ZMQ_Socket__set_rcvhwm__meth}, -+#endif -+#if (VERSION_3_0) -+ {"multicast_hops", ZMQ_Socket__multicast_hops__meth}, -+#endif -+#if (VERSION_3_0) -+ {"set_multicast_hops", ZMQ_Socket__set_multicast_hops__meth}, -+#endif -+#if (VERSION_2_2|VERSION_3_0) -+ {"rcvtimeo", ZMQ_Socket__rcvtimeo__meth}, -+#endif -+#if (VERSION_2_2|VERSION_3_0) -+ {"set_rcvtimeo", ZMQ_Socket__set_rcvtimeo__meth}, -+#endif -+#if (VERSION_2_2|VERSION_3_0) -+ {"sndtimeo", ZMQ_Socket__sndtimeo__meth}, -+#endif -+#if (VERSION_2_2|VERSION_3_0) -+ {"set_sndtimeo", ZMQ_Socket__set_sndtimeo__meth}, -+#endif -+#if (VERSION_3_0) -+ {"ipv4only", ZMQ_Socket__ipv4only__meth}, -+#endif -+#if (VERSION_3_0) -+ {"set_ipv4only", ZMQ_Socket__set_ipv4only__meth}, -+#endif - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Socket_metas[] = { -+static const luaL_Reg obj_ZMQ_Socket_metas[] = { - {"__gc", ZMQ_Socket__close__meth}, - {"__tostring", obj_udata_default_tostring}, - {"__eq", obj_udata_default_equal}, -@@ -3148,23 +7180,27 @@ static const obj_const obj_ZMQ_Socket_constants[] = { - {NULL, NULL, 0.0 , 0} - }; - --static const luaL_reg obj_ZMQ_Poller_pub_funcs[] = { -+static const reg_impl obj_ZMQ_Socket_implements[] = { -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZMQ_Poller_pub_funcs[] = { - {"new", ZMQ_Poller__new__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Poller_methods[] = { -+static const luaL_Reg obj_ZMQ_Poller_methods[] = { - {"close", ZMQ_Poller__close__meth}, - {"add", ZMQ_Poller__add__meth}, - {"modify", ZMQ_Poller__modify__meth}, - {"remove", ZMQ_Poller__remove__meth}, - {"poll", ZMQ_Poller__poll__meth}, -- {"next_revents", ZMQ_Poller__next_revents__meth}, -+ {"next_revents_idx", ZMQ_Poller__next_revents_idx__meth}, - {"count", ZMQ_Poller__count__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Poller_metas[] = { -+static const luaL_Reg obj_ZMQ_Poller_metas[] = { - {"__gc", ZMQ_Poller__close__meth}, - {"__tostring", obj_simple_udata_default_tostring}, - {"__eq", obj_simple_udata_default_equal}, -@@ -3183,18 +7219,22 @@ static const obj_const obj_ZMQ_Poller_constants[] = { - {NULL, NULL, 0.0 , 0} - }; - --static const luaL_reg obj_ZMQ_Ctx_pub_funcs[] = { -+static const reg_impl obj_ZMQ_Poller_implements[] = { -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZMQ_Ctx_pub_funcs[] = { - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Ctx_methods[] = { -+static const luaL_Reg obj_ZMQ_Ctx_methods[] = { - {"term", ZMQ_Ctx__term__meth}, - {"lightuserdata", ZMQ_Ctx__lightuserdata__meth}, - {"socket", ZMQ_Ctx__socket__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_Ctx_metas[] = { -+static const luaL_Reg obj_ZMQ_Ctx_metas[] = { - {"__gc", ZMQ_Ctx__term__meth}, - {"__tostring", obj_udata_default_tostring}, - {"__eq", obj_udata_default_equal}, -@@ -3213,17 +7253,21 @@ static const obj_const obj_ZMQ_Ctx_constants[] = { - {NULL, NULL, 0.0 , 0} - }; - --static const luaL_reg obj_ZMQ_StopWatch_pub_funcs[] = { -+static const reg_impl obj_ZMQ_Ctx_implements[] = { -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg obj_ZMQ_StopWatch_pub_funcs[] = { - {"start", ZMQ_StopWatch__start__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_StopWatch_methods[] = { -+static const luaL_Reg obj_ZMQ_StopWatch_methods[] = { - {"stop", ZMQ_StopWatch__stop__meth}, - {NULL, NULL} - }; - --static const luaL_reg obj_ZMQ_StopWatch_metas[] = { -+static const luaL_Reg obj_ZMQ_StopWatch_metas[] = { - {"__gc", ZMQ_StopWatch__stop__meth}, - {"__tostring", obj_udata_default_tostring}, - {"__eq", obj_udata_default_equal}, -@@ -3242,87 +7286,217 @@ static const obj_const obj_ZMQ_StopWatch_constants[] = { - {NULL, NULL, 0.0 , 0} - }; - --static const luaL_reg zmq_function[] = { -+static const reg_impl obj_ZMQ_StopWatch_implements[] = { -+ {NULL, NULL} -+}; -+ -+static const luaL_Reg zmq_function[] = { - {"version", zmq__version__func}, - {"init", zmq__init__func}, - {"init_ctx", zmq__init_ctx__func}, -+#if (VERSION_2_0) - {"device", zmq__device__func}, -+#endif - {"stopwatch_start", zmq__stopwatch_start__func}, - {"sleep", zmq__sleep__func}, -- {"dump_ffi", zmq__dump_ffi__func}, - {NULL, NULL} - }; - - static const obj_const zmq_constants[] = { -- {"TYPE", NULL, 16, CONST_NUMBER}, -- {"RCVMORE", NULL, 13, CONST_NUMBER}, -- {"LINGER", NULL, 17, CONST_NUMBER}, -- {"SWAP", NULL, 3, CONST_NUMBER}, -- {"MSG_SHARED", NULL, 128, CONST_NUMBER}, -- {"SNDBUF", NULL, 11, CONST_NUMBER}, -- {"STREAMER", NULL, 1, CONST_NUMBER}, -- {"NOBLOCK", NULL, 1, CONST_NUMBER}, -- {"RCVBUF", NULL, 12, CONST_NUMBER}, -- {"FORWARDER", NULL, 2, CONST_NUMBER}, -- {"RATE", NULL, 8, CONST_NUMBER}, -- {"IDENTITY", NULL, 5, CONST_NUMBER}, -- {"SUB", NULL, 2, CONST_NUMBER}, -- {"FD", NULL, 14, CONST_NUMBER}, -- {"PUB", NULL, 1, CONST_NUMBER}, -- {"DELIMITER", NULL, 31, CONST_NUMBER}, -- {"BACKLOG", NULL, 19, CONST_NUMBER}, -- {"SNDMORE", NULL, 2, CONST_NUMBER}, -- {"POLLIN", NULL, 1, CONST_NUMBER}, -- {"REP", NULL, 4, CONST_NUMBER}, -- {"POLLERR", NULL, 4, CONST_NUMBER}, -- {"MAX_VSM_SIZE", NULL, 30, CONST_NUMBER}, -- {"PUSH", NULL, 8, CONST_NUMBER}, -- {"HWM", NULL, 1, CONST_NUMBER}, -- {"MSG_MORE", NULL, 1, CONST_NUMBER}, -- {"REQ", NULL, 3, CONST_NUMBER}, -- {"UNSUBSCRIBE", NULL, 7, CONST_NUMBER}, -- {"PULL", NULL, 7, CONST_NUMBER}, -- {"PAIR", NULL, 0, CONST_NUMBER}, -- {"QUEUE", NULL, 3, CONST_NUMBER}, -- {"EVENTS", NULL, 15, CONST_NUMBER}, -- {"XREQ", NULL, 5, CONST_NUMBER}, -- {"XREP", NULL, 6, CONST_NUMBER}, -- {"SUBSCRIBE", NULL, 6, CONST_NUMBER}, -- {"MCAST_LOOP", NULL, 10, CONST_NUMBER}, -- {"VSM", NULL, 32, CONST_NUMBER}, -- {"RECOVERY_IVL", NULL, 9, CONST_NUMBER}, -- {"RECONNECT_IVL", NULL, 18, CONST_NUMBER}, -- {"POLLOUT", NULL, 2, CONST_NUMBER}, -- {"AFFINITY", NULL, 4, CONST_NUMBER}, -+#ifdef ZMQ_TYPE -+ {"TYPE", NULL, ZMQ_TYPE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RCVMORE -+ {"RCVMORE", NULL, ZMQ_RCVMORE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_LINGER -+ {"LINGER", NULL, ZMQ_LINGER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_REP -+ {"REP", NULL, ZMQ_REP, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MSG_SHARED -+ {"MSG_SHARED", NULL, ZMQ_MSG_SHARED, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_XSUB -+ {"XSUB", NULL, ZMQ_XSUB, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_STREAMER -+ {"STREAMER", NULL, ZMQ_STREAMER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RECONNECT_IVL_MSEC -+ {"RECONNECT_IVL_MSEC", NULL, ZMQ_RECONNECT_IVL_MSEC, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MAX_VSM_SIZE -+ {"MAX_VSM_SIZE", NULL, ZMQ_MAX_VSM_SIZE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_PAIR -+ {"PAIR", NULL, ZMQ_PAIR, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_DEALER -+ {"DEALER", NULL, ZMQ_DEALER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_ROUTER -+ {"ROUTER", NULL, ZMQ_ROUTER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_NOBLOCK -+ {"NOBLOCK", NULL, ZMQ_NOBLOCK, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RCVBUF -+ {"RCVBUF", NULL, ZMQ_RCVBUF, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_FORWARDER -+ {"FORWARDER", NULL, ZMQ_FORWARDER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RATE -+ {"RATE", NULL, ZMQ_RATE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_IDENTITY -+ {"IDENTITY", NULL, ZMQ_IDENTITY, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MSG_MORE -+ {"MSG_MORE", NULL, ZMQ_MSG_MORE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MAXMSGSIZE -+ {"MAXMSGSIZE", NULL, ZMQ_MAXMSGSIZE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_PULL -+ {"PULL", NULL, ZMQ_PULL, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MULTICAST_HOPS -+ {"MULTICAST_HOPS", NULL, ZMQ_MULTICAST_HOPS, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RCVHWM -+ {"RCVHWM", NULL, ZMQ_RCVHWM, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SUB -+ {"SUB", NULL, ZMQ_SUB, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_UNSUBSCRIBE -+ {"UNSUBSCRIBE", NULL, ZMQ_UNSUBSCRIBE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_BACKLOG -+ {"BACKLOG", NULL, ZMQ_BACKLOG, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_XREQ -+ {"XREQ", NULL, ZMQ_XREQ, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_PUSH -+ {"PUSH", NULL, ZMQ_PUSH, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_PUB -+ {"PUB", NULL, ZMQ_PUB, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_DELIMITER -+ {"DELIMITER", NULL, ZMQ_DELIMITER, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_EVENTS -+ {"EVENTS", NULL, ZMQ_EVENTS, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SNDMORE -+ {"SNDMORE", NULL, ZMQ_SNDMORE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RCVLABEL -+ {"RCVLABEL", NULL, ZMQ_RCVLABEL, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SNDBUF -+ {"SNDBUF", NULL, ZMQ_SNDBUF, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_FD -+ {"FD", NULL, ZMQ_FD, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_POLLIN -+ {"POLLIN", NULL, ZMQ_POLLIN, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_XPUB -+ {"XPUB", NULL, ZMQ_XPUB, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_POLLERR -+ {"POLLERR", NULL, ZMQ_POLLERR, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RCVTIMEO -+ {"RCVTIMEO", NULL, ZMQ_RCVTIMEO, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SNDTIMEO -+ {"SNDTIMEO", NULL, ZMQ_SNDTIMEO, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_HWM -+ {"HWM", NULL, ZMQ_HWM, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SWAP -+ {"SWAP", NULL, ZMQ_SWAP, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_REQ -+ {"REQ", NULL, ZMQ_REQ, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RECONNECT_IVL_MAX -+ {"RECONNECT_IVL_MAX", NULL, ZMQ_RECONNECT_IVL_MAX, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_AFFINITY -+ {"AFFINITY", NULL, ZMQ_AFFINITY, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SNDLABEL -+ {"SNDLABEL", NULL, ZMQ_SNDLABEL, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_QUEUE -+ {"QUEUE", NULL, ZMQ_QUEUE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_VSM -+ {"VSM", NULL, ZMQ_VSM, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SNDHWM -+ {"SNDHWM", NULL, ZMQ_SNDHWM, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_XREP -+ {"XREP", NULL, ZMQ_XREP, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_SUBSCRIBE -+ {"SUBSCRIBE", NULL, ZMQ_SUBSCRIBE, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_MCAST_LOOP -+ {"MCAST_LOOP", NULL, ZMQ_MCAST_LOOP, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_DONTWAIT -+ {"DONTWAIT", NULL, ZMQ_DONTWAIT, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RECOVERY_IVL -+ {"RECOVERY_IVL", NULL, ZMQ_RECOVERY_IVL, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_RECONNECT_IVL -+ {"RECONNECT_IVL", NULL, ZMQ_RECONNECT_IVL, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_POLLOUT -+ {"POLLOUT", NULL, ZMQ_POLLOUT, CONST_NUMBER}, -+#endif -+#ifdef ZMQ_POLL_MSEC -+ {"POLL_MSEC", NULL, ZMQ_POLL_MSEC, CONST_NUMBER}, -+#endif - {NULL, NULL, 0.0 , 0} - }; - --static const ffi_export_symbol zmq_ffi_export[] = { --{ "get_zmq_strerror", get_zmq_strerror }, --{ "simple_zmq_send", simple_zmq_send }, --{ "poller_find_sock_item", poller_find_sock_item }, --{ "poller_find_fd_item", poller_find_fd_item }, --{ "poller_get_free_item", poller_get_free_item }, --{ "poller_poll", poller_poll }, --{ "poller_remove_item", poller_remove_item }, -- {NULL, NULL} --}; -- - - - static const reg_sub_module reg_sub_modules[] = { -- { &(obj_type_zmq_msg_t), 0, obj_zmq_msg_t_pub_funcs, obj_zmq_msg_t_methods, obj_zmq_msg_t_metas, obj_zmq_msg_t_bases, obj_zmq_msg_t_fields, obj_zmq_msg_t_constants}, -- { &(obj_type_ZMQ_Socket), 0, obj_ZMQ_Socket_pub_funcs, obj_ZMQ_Socket_methods, obj_ZMQ_Socket_metas, obj_ZMQ_Socket_bases, obj_ZMQ_Socket_fields, obj_ZMQ_Socket_constants}, -- { &(obj_type_ZMQ_Poller), 0, obj_ZMQ_Poller_pub_funcs, obj_ZMQ_Poller_methods, obj_ZMQ_Poller_metas, obj_ZMQ_Poller_bases, obj_ZMQ_Poller_fields, obj_ZMQ_Poller_constants}, -- { &(obj_type_ZMQ_Ctx), 0, obj_ZMQ_Ctx_pub_funcs, obj_ZMQ_Ctx_methods, obj_ZMQ_Ctx_metas, obj_ZMQ_Ctx_bases, obj_ZMQ_Ctx_fields, obj_ZMQ_Ctx_constants}, -- { &(obj_type_ZMQ_StopWatch), 0, obj_ZMQ_StopWatch_pub_funcs, obj_ZMQ_StopWatch_methods, obj_ZMQ_StopWatch_metas, obj_ZMQ_StopWatch_bases, obj_ZMQ_StopWatch_fields, obj_ZMQ_StopWatch_constants}, -- {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL} -+ { &(obj_type_ZErrors), REG_META, obj_ZErrors_pub_funcs, obj_ZErrors_methods, obj_ZErrors_metas, NULL, NULL, obj_ZErrors_constants, NULL, 0}, -+ { &(obj_type_zmq_msg_t), REG_OBJECT, obj_zmq_msg_t_pub_funcs, obj_zmq_msg_t_methods, obj_zmq_msg_t_metas, obj_zmq_msg_t_bases, obj_zmq_msg_t_fields, obj_zmq_msg_t_constants, obj_zmq_msg_t_implements, 0}, -+ { &(obj_type_ZMQ_Socket), REG_OBJECT, obj_ZMQ_Socket_pub_funcs, obj_ZMQ_Socket_methods, obj_ZMQ_Socket_metas, obj_ZMQ_Socket_bases, obj_ZMQ_Socket_fields, obj_ZMQ_Socket_constants, obj_ZMQ_Socket_implements, 0}, -+ { &(obj_type_ZMQ_Poller), REG_OBJECT, obj_ZMQ_Poller_pub_funcs, obj_ZMQ_Poller_methods, obj_ZMQ_Poller_metas, obj_ZMQ_Poller_bases, obj_ZMQ_Poller_fields, obj_ZMQ_Poller_constants, obj_ZMQ_Poller_implements, 0}, -+ { &(obj_type_ZMQ_Ctx), REG_OBJECT, obj_ZMQ_Ctx_pub_funcs, obj_ZMQ_Ctx_methods, obj_ZMQ_Ctx_metas, obj_ZMQ_Ctx_bases, obj_ZMQ_Ctx_fields, obj_ZMQ_Ctx_constants, obj_ZMQ_Ctx_implements, 0}, -+ { &(obj_type_ZMQ_StopWatch), REG_OBJECT, obj_ZMQ_StopWatch_pub_funcs, obj_ZMQ_StopWatch_methods, obj_ZMQ_StopWatch_metas, obj_ZMQ_StopWatch_bases, obj_ZMQ_StopWatch_fields, obj_ZMQ_StopWatch_constants, obj_ZMQ_StopWatch_implements, 0}, -+ {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0} - }; - - - - - -+#if LUAJIT_FFI -+static const ffi_export_symbol zmq_ffi_export[] = { -+ {NULL, { NULL } } -+}; -+#endif -+ -+ - - - static const luaL_Reg submodule_libs[] = { -@@ -3355,20 +7529,29 @@ LUA_NOBJ_API int luaopen_zmq(lua_State *L) { - const luaL_Reg *submodules = submodule_libs; - int priv_table = -1; - --#if LUAJIT_FFI -+ /* register interfaces */ -+ obj_register_interfaces(L, obj_interfaces); -+ - /* private table to hold reference to object metatables. */ - lua_newtable(L); - priv_table = lua_gettop(L); --#endif -+ lua_pushlightuserdata(L, obj_udata_private_key); -+ lua_pushvalue(L, priv_table); -+ lua_rawset(L, LUA_REGISTRYINDEX); /* store private table in registry. */ - - /* create object cache. */ - create_object_instance_cache(L); - - /* module table. */ -+#if REG_MODULES_AS_GLOBALS - luaL_register(L, "zmq", zmq_function); -+#else -+ lua_newtable(L); -+ luaL_setfuncs(L, zmq_function, 0); -+#endif - - /* register module constants. */ -- obj_type_register_constants(L, zmq_constants, -1); -+ obj_type_register_constants(L, zmq_constants, -1, 0); - - for(; submodules->func != NULL ; submodules++) { - lua_pushcfunction(L, submodules->func); -@@ -3389,9 +7572,19 @@ LUA_NOBJ_API int luaopen_zmq(lua_State *L) { - } - - #if LUAJIT_FFI -- nobj_try_loading_ffi(L, "zmq", zmq_ffi_lua_code, -- zmq_ffi_export, priv_table); -+ if(nobj_check_ffi_support(L)) { -+ nobj_try_loading_ffi(L, "zmq.nobj.ffi.lua", zmq_ffi_lua_code, -+ zmq_ffi_export, priv_table); -+ } - #endif -+ -+ /* Cache reference to zmq.ZErrors table for errno->string convertion. */ -+ lua_pushlightuserdata(L, zmq_ZErrors_key); -+ lua_getfield(L, -2, "ZErrors"); -+ lua_rawset(L, LUA_REGISTRYINDEX); -+ -+ -+ - return 1; - } - -diff --git a/src/socket.nobj.lua b/src/socket.nobj.lua -index 207f52b..ef7a0db 100644 ---- a/src/socket.nobj.lua -+++ b/src/socket.nobj.lua -@@ -18,21 +18,416 @@ - -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - -- THE SOFTWARE. - -+------------------------------------------------------------------------------------- -+-- -+-- Generate ZeroMQ socket option code customized for each version of zmq (2.0,2.1,3.x) -+-- -+------------------------------------------------------------------------------------- -+ -+local OPT_TYPES = { -+NONE = "NONE", -+INT = "int", -+UINT32 = "uint32_t", -+UINT64 = "uint64_t", -+INT64 = "int64_t", -+BLOB = "const char *", -+FD = "int", -+} -+local get_set_prefix = { -+rw = { c_get = "lzmq_socket_", get='', c_set = "lzmq_socket_set_", set='set_' }, -+r = { c_get = "lzmq_socket_", get='' }, -+w = { c_set = "lzmq_socket_", set='' }, -+} -+ -+local socket_options = { -+ { ver_def = 'VERSION_2_0', major = 2, minor = 0, -+ [1] = { name="hwm", otype="UINT64", mode="rw", ltype="int" }, -+ [2] = { }, -+ [3] = { name="swap", otype="INT64", mode="rw", ltype="int" }, -+ [4] = { name="affinity", otype="UINT64", mode="rw", ltype="uint64_t" }, -+ [5] = { name="identity", otype="BLOB", mode="rw", ltype="const char *" }, -+ [6] = { name="subscribe", otype="BLOB", mode="w", ltype="const char *" }, -+ [7] = { name="unsubscribe", otype="BLOB", mode="w", ltype="const char *" }, -+ [8] = { name="rate", otype="INT64", mode="rw", ltype="int" }, -+ [9] = { name="recovery_ivl", otype="INT64", mode="rw", ltype="int" }, -+ [10] = { name="mcast_loop", otype="INT64", mode="rw", ltype="int" }, -+ [11] = { name="sndbuf", otype="UINT64", mode="rw", ltype="int" }, -+ [12] = { name="rcvbuf", otype="UINT64", mode="rw", ltype="int" }, -+ [13] = { name="rcvmore", otype="INT64", mode="r", ltype="int" }, -+ }, -+ { ver_def = 'VERSION_2_1', major = 2, minor = 1, -+ [14] = { name="fd", otype="FD", mode="r", ltype="int" }, -+ [15] = { name="events", otype="UINT32", mode="r", ltype="int" }, -+ [16] = { name="type", otype="INT", mode="r", ltype="int" }, -+ [17] = { name="linger", otype="INT", mode="rw", ltype="int" }, -+ [18] = { name="reconnect_ivl", otype="INT", mode="rw", ltype="int" }, -+ [19] = { name="backlog", otype="INT", mode="rw", ltype="int" }, -+ [20] = { name="recovery_ivl_msec", otype="INT64", mode="rw", ltype="int64_t" }, -+ [21] = { name="reconnect_ivl_max", otype="INT", mode="rw", ltype="int" }, -+ }, -+ { ver_def = 'VERSION_2_2', major = 2, minor = 2, -+ [22] = { }, -+ [23] = { }, -+ [24] = { }, -+ [25] = { }, -+ [26] = { }, -+ [27] = { name="rcvtimeo", otype="INT", mode="rw", ltype="int" }, -+ [28] = { name="sndtimeo", otype="INT", mode="rw", ltype="int" }, -+ }, -+ { ver_def = 'VERSION_3_0', major = 3, minor = 0, -+ [1] = { name="hwm", otype="INT", mode="rw", -+custom = [[ -+ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { -+ int val; -+ int rc; -+ val = (int)value; -+ rc = zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); -+ if(-1 == rc) return rc; -+ val = (int)value; -+ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); -+} -+ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { -+ size_t val_len; -+ int rc; -+ val_len = sizeof(value); -+ rc = zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); -+ if(-1 == rc) return rc; -+ val_len = sizeof(value); -+ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); -+} -+ -+]] }, -+ [2] = { }, -+ [3] = { }, -+ [4] = { name="affinity", otype="UINT64", mode="rw", ltype="uint64_t" }, -+ [5] = { name="identity", otype="BLOB", mode="rw", ltype="const char *" }, -+ [6] = { name="subscribe", otype="BLOB", mode="w", ltype="const char *" }, -+ [7] = { name="unsubscribe", otype="BLOB", mode="w", ltype="const char *" }, -+ [8] = { name="rate", otype="INT", mode="rw", ltype="int" }, -+ [9] = { name="recovery_ivl", otype="INT", mode="rw", ltype="int" }, -+ [10] = { }, -+ [11] = { name="sndbuf", otype="INT", mode="rw", ltype="int" }, -+ [12] = { name="rcvbuf", otype="INT", mode="rw", ltype="int" }, -+ [13] = { name="rcvmore", otype="INT", mode="r", ltype="int" }, -+ [14] = { name="fd", otype="FD", mode="r", ltype="int" }, -+ [15] = { name="events", otype="INT", mode="r", ltype="int" }, -+ [16] = { name="type", otype="INT", mode="r", ltype="int" }, -+ [17] = { name="linger", otype="INT", mode="rw", ltype="int" }, -+ [18] = { name="reconnect_ivl", otype="INT", mode="rw", ltype="int" }, -+ [19] = { name="backlog", otype="INT", mode="rw", ltype="int" }, -+ [20] = { }, -+ [21] = { name="reconnect_ivl_max", otype="INT", mode="rw", ltype="int" }, -+ [22] = { name="maxmsgsize", otype="INT64", mode="rw", ltype="int64_t" }, -+ [23] = { name="sndhwm", otype="INT", mode="rw", ltype="int" }, -+ [24] = { name="rcvhwm", otype="INT", mode="rw", ltype="int" }, -+ [25] = { name="multicast_hops", otype="INT", mode="rw", ltype="int" }, -+ [26] = { }, -+ [27] = { name="rcvtimeo", otype="INT", mode="rw", ltype="int" }, -+ [28] = { name="sndtimeo", otype="INT", mode="rw", ltype="int" }, -+ [29] = { }, -+ [30] = { }, -+ [31] = { name="ipv4only", otype="INT", mode="rw", ltype="int" }, -+ }, -+} -+local max_options = 50 -+ -+local function foreach_opt(func) -+ for i=1,#socket_options do -+ local ver_opts = socket_options[i] -+ for num=1,max_options do -+ local opt = ver_opts[num] -+ if opt then -+ func(num, opt, ver_opts) -+ end -+ end -+ end -+end -+local add=function(t,val) return table.insert(t,val) end -+local function template(data, templ) -+ return templ:gsub("%${(.-)}", data) -+end -+ -+local socket_methods = {} -+local ffi_opt_names = {} -+local max_methods = 0 -+local function get_methods(opt, ver) -+ local num = opt.num -+ -- check if methods have been created -+ local methods = socket_methods[num] -+ -+ if not methods then -+ add(ffi_opt_names, "\t\t[".. num .. "] = '" .. opt.name .. "',\n") -+ -- need to create methods info. -+ methods = { -+ num=num, -+ name=opt.name, -+ get=opt.get, set=opt.set, c_get=opt.c_get, c_set=opt.c_set, -+ ltype=opt.ltype, otype=opt.otype, mode=opt.mode, -+ versions = {}, -+ } -+ -+ -- initialize all version as not-supported. -+ for i=1,#socket_options do -+ local ver_opts = socket_options[i] -+ methods[ver_opts.ver_def] = false -+ end -+ -+ if num > max_methods then max_methods = num end -+ -+ socket_methods[num] = methods -+ end -+ -+ -- mark this version as supporting the option. -+ methods[ver.ver_def] = true -+ add(methods.versions, ver) -+ -+ return methods -+end -+ -+-- do pre-processing of options. -+foreach_opt(function(num, opt, ver) -+ opt.num = num -+ if not opt.name then -+ opt.name = 'none' -+ opt.otype = 'NONE' -+ opt.DEF = 'unused' -+ return -+ end -+ -- track max option number for each version. -+ if not ver.max_opt or ver.max_opt < num then -+ ver.max_opt = num -+ end -+ opt.DEF = "ZMQ_" .. opt.name:upper() -+ -- ctype & ffi_type -+ local ctype = OPT_TYPES[opt.otype] -+ opt.ctype = ctype -+ if opt.otype == 'BLOB' then -+ opt.ffi_type = 'string' -+ opt.set_len_param = ', size_t value_len' -+ opt.set_val_name = 'value' -+ opt.set_len_name = 'value_len' -+ elseif ctype ~= 'NONE' then -+ opt.ffi_type = ctype .. '[1]' -+ opt.set_len_param = '' -+ opt.set_val_name = '&value' -+ opt.set_len_name = 'sizeof(value)' -+ end -+ -- getter/setter names -+ for meth,prefix in pairs(get_set_prefix[opt.mode]) do -+ opt[meth] = prefix .. opt.name -+ end -+ -- create common list of option get/set methods. -+ local methods = get_methods(opt, ver) -+end) -+ -+local options_c_code = {} -+local opt_types = {} -+ -+local function if_def(def) -+ local code = "#if " .. def .. "\n" -+ add(options_c_code, code) -+ add(opt_types, code) -+end -+local function endif(def) -+ local code = "#endif /* #if " .. def .. " */\n" -+ add(options_c_code, code) -+ add(opt_types, code) -+end -+ -+-- build C code for socket options setters/getters -+local last_ver -+foreach_opt(function(num, opt, ver) -+ if ver ~= last_ver then -+ if last_ver then -+ endif(last_ver.ver_def) -+ end -+ last_ver = ver -+ if_def(ver.ver_def) -+ add(opt_types, template(ver,[[ -+#define ${ver_def}_MAX_OPT ${max_opt} -+]])) -+ end -+ add(opt_types, template(opt,[[ -+ OPT_TYPE_${otype}, /* ${num} ${DEF} */ -+]])) -+ if opt.name == 'none' then return end -+ -- generate setter -+ local set = '' -+ local get = '' -+ if opt.c_set then -+ if opt.otype == 'BLOB' then -+ set = [[ -+LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, const char *value, size_t str_len) { -+ return zmq_setsockopt(sock, ${DEF}, value, str_len); -+]] -+ elseif opt.ctype == opt.ltype then -+ set = [[ -+LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, ${ltype} value) { -+ return zmq_setsockopt(sock, ${DEF}, &value, sizeof(value)); -+]] -+ else -+ set = [[ -+LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, ${ltype} value) { -+ ${ctype} val = (${ctype})value; -+ return zmq_setsockopt(sock, ${DEF}, &val, sizeof(val)); -+]] -+ end -+ set = set .. "}\n\n" -+ end -+ -- generate getter -+ if opt.c_get then -+ if opt.otype == 'BLOB' then -+ get = [[ -+LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, char *value, size_t *len) { -+ return zmq_getsockopt(sock, ${DEF}, value, len); -+]] -+ elseif opt.ctype == opt.ltype then -+ get = [[ -+LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, ${ltype} *value) { -+ size_t val_len = sizeof(${ltype}); -+ return zmq_getsockopt(sock, ${DEF}, value, &val_len); -+]] -+ else -+ get = [[ -+LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, ${ltype} *value) { -+ ${ctype} val; -+ size_t val_len = sizeof(val); -+ int rc = zmq_getsockopt(sock, ${DEF}, &val, &val_len); -+ *value = (${ltype})val; -+ return rc; -+]] -+ end -+ get = get .. "}\n\n" -+ end -+ local templ -+ if opt.custom then -+ templ = opt.custom -+ else -+ templ = set .. get -+ end -+ add(options_c_code, template(opt,templ)) -+end) -+endif(last_ver.ver_def) -+ -+add(opt_types, [[ -+#if VERSION_3_0 -+# define MAX_OPTS VERSION_3_0_MAX_OPT -+#else -+# if VERSION_2_2 -+# define MAX_OPTS VERSION_2_2_MAX_OPT -+# elif VERSION_2_1 -+# define MAX_OPTS VERSION_2_1_MAX_OPT -+# else -+# define MAX_OPTS VERSION_2_0_MAX_OPT -+# endif -+#endif -+}; -+ -+]]) -+ -+options_c_code = table.concat(options_c_code) -+opt_types = table.concat(opt_types) -+ffi_opt_names = table.concat(ffi_opt_names) -+ -+local function tunpack(tab, idx, max) -+ if idx == max then return tab[idx] end -+ return tab[idx], tunpack(tab, idx + 1, max) -+end -+ -+local function build_meth_if_def(meth) -+ local v = {} -+ for i=1,#socket_options do -+ local ver_opts = socket_options[i] -+ if meth[ver_opts.ver_def] then -+ v[#v+1] = ver_opts.ver_def -+ end -+ end -+ return v -+end -+ -+local function build_option_methods() -+ local m = {} -+ -+ for i=1,max_methods do -+ local meth = socket_methods[i] -+ if meth then -+ local ltype = meth.ltype -+ local name -+ -- get list of version defs for this method. -+ local if_defs = build_meth_if_def(meth) -+ -- generate getter method. -+ name = meth.get -+ if name then -+ local args = { ltype, "&value" } -+ local val_out = { ltype, "&value" } -+ if meth.otype == 'BLOB' then -+ val_out = { 'char *', "value", has_length = true } -+ args = { 'char *', "value", "size_t", "&#value" } -+ end -+ m[#m+1] = method (name) { if_defs = if_defs, -+ var_out(val_out), -+ c_export_method_call "ZMQ_Error" (meth.c_get) (args), -+ } -+ end -+ -- generate setter method. -+ name = meth.set -+ if name then -+ local args = { ltype, "value" } -+ if meth.otype == 'BLOB' then -+ args = { ltype, "value", "size_t", "#value" } -+ end -+ m[#m+1] = method (name) { if_defs = if_defs, -+ c_export_method_call "ZMQ_Error" (meth.c_set) (args), -+ } -+ end -+ end -+ end -+ -+ return tunpack(m, 1, #m) -+end -+ -+------------------------------------------------------------------------------------- -+-- -+-- ZeroMQ socket object. -+-- -+------------------------------------------------------------------------------------- -+ - object "ZMQ_Socket" { - error_on_null = "get_zmq_strerror()", -- c_source [[ --/* detect zmq version >= 2.1.0 */ --#define VERSION_2_1 0 --#if defined(ZMQ_VERSION) --#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0)) --#undef VERSION_2_1 --#define VERSION_2_1 1 --#endif --#endif -+ ffi_source "ffi_pre_cdef" [[ -+ -+-- detect zmq version -+local VERSION_2_0 = true -+local VERSION_2_1 = false -+local VERSION_2_2 = false -+local VERSION_3_0 = false -+local zver = _M.version() -+if zver[1] == 3 then -+ VERSION_2_0 = false -+ VERSION_3_0 = true -+elseif zver[1] == 2 and zver[2] == 2 then -+ VERSION_2_2 = true -+ VERSION_2_1 = true -+elseif zver[1] == 2 and zver[2] == 1 then -+ VERSION_2_1 = true -+end -+ -+if VERSION_2_0 then -+ ffi.cdef[==[ -+typedef int ZMQ_Error; -+typedef struct ZMQ_Socket ZMQ_Socket; -+typedef struct zmq_msg_t zmq_msg_t; -+ -+ZMQ_Error zmq_sendmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__("zmq_send"); -+ZMQ_Error zmq_recvmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__("zmq_recv"); -+]==] -+end -+]], -+ c_source ([[ - - /* detect really old ZeroMQ 2.0.x series. */ - #if !defined(ZMQ_RCVMORE) --#error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" -+# error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" - #endif - - typedef struct ZMQ_Socket ZMQ_Socket; -@@ -44,47 +439,23 @@ typedef SOCKET socket_t; - typedef int socket_t; - #endif - -+#if VERSION_2_0 -+# define zmq_sendmsg zmq_send -+# define zmq_recvmsg zmq_recv -+#endif -+ - /* socket option types. */ - #define OPT_TYPE_NONE 0 - #define OPT_TYPE_INT 1 - #define OPT_TYPE_UINT32 2 - #define OPT_TYPE_UINT64 3 - #define OPT_TYPE_INT64 4 --#define OPT_TYPE_STR 5 -+#define OPT_TYPE_BLOB 5 - #define OPT_TYPE_FD 6 - - static const int opt_types[] = { -- OPT_TYPE_NONE, /* 0 unused */ -- OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ -- OPT_TYPE_NONE, /* 2 unused */ -- OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ -- OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ -- OPT_TYPE_STR, /* 5 ZMQ_IDENTITY */ -- OPT_TYPE_STR, /* 6 ZMQ_SUBSCRIBE */ -- OPT_TYPE_STR, /* 7 ZMQ_UNSUBSCRIBE */ -- OPT_TYPE_INT64, /* 8 ZMQ_RATE */ -- OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ -- OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ -- OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ -- OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ -- OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ -- --#if VERSION_2_1 -- OPT_TYPE_FD, /* 14 ZMQ_FD */ -- OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ -- OPT_TYPE_INT, /* 16 ZMQ_TYPE */ -- OPT_TYPE_INT, /* 17 ZMQ_LINGER */ -- OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ -- OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ --#endif --}; --#if VERSION_2_1 --#define MAX_OPTS ZMQ_BACKLOG --#else --#define MAX_OPTS ZMQ_RCVMORE --#endif -- --]], -+ OPT_TYPE_NONE, /* 0 unused */ -+]] .. opt_types .. options_c_code), - - destructor "close" { - c_method_call "ZMQ_Error" "zmq_close" {} -@@ -99,37 +470,32 @@ static const int opt_types[] = { - int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); - int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); - ]], -- ffi_source[[ --local option_types = { --[zmq.HWM] = 'uint64_t[1]', --[zmq.SWAP] = 'int64_t[1]', --[zmq.AFFINITY] = 'uint64_t[1]', --[zmq.IDENTITY] = 'string', --[zmq.SUBSCRIBE] = 'string', --[zmq.UNSUBSCRIBE] = 'string', --[zmq.RATE] = 'int64_t[1]', --[zmq.RECOVERY_IVL] = 'int64_t[1]', --[zmq.MCAST_LOOP] = 'int64_t[1]', --[zmq.SNDBUF] = 'uint64_t[1]', --[zmq.RCVBUF] = 'uint64_t[1]', --[zmq.RCVMORE] = 'int64_t[1]', --[zmq.FD] = 'int[1]', --[zmq.EVENTS] = 'uint32_t[1]', --[zmq.TYPE] = 'int[1]', --[zmq.LINGER] = 'int[1]', --[zmq.RECONNECT_IVL] = 'int[1]', --[zmq.BACKLOG] = 'int[1]', --} --local option_len = {} --local option_tmps = {} --for k,v in pairs(option_types) do -- if v ~= 'string' then -- option_len[k] = ffi.sizeof(v) -- option_tmps[k] = ffi.new(v, 0) -- end -+ ffi_source([[ -+local option_gets = {} -+local option_sets = {} -+ -+do -+ local opt_name -+ local methods = _meth.${object_name} -+ setmetatable(option_gets,{__index = function(tab,opt) -+ local opt_name = opt_name[opt] -+ if not opt_name then return nil end -+ local method = methods[opt_name] -+ rawset(tab, opt, method) -+ return method -+ end}) -+ setmetatable(option_sets,{__index = function(tab,opt) -+ local opt_name = opt_name[opt] -+ if not opt_name then return nil end -+ local method = methods['set_' .. opt_name] or methods[opt_name] -+ rawset(tab, opt, method) -+ return method -+ end}) -+ opt_name = { -+]] .. ffi_opt_names .. [[} - end - --]], -+]]), - method "setopt" { - var_in{ "uint32_t", "opt" }, - var_in{ "", "val" }, -@@ -138,7 +504,7 @@ end - size_t val_len; - const void *val; - --#if VERSION_2_1 -+#if defined(VERSION_2_1) || defined(VERSION_3_0) - socket_t fd_val; - #endif - int int_val; -@@ -146,12 +512,26 @@ end - uint64_t uint64_val; - int64_t int64_val; - -+#if VERSION_3_0 -+ /* 3.0 backwards compatibility support for HWM. */ -+ if(${opt} == ZMQ_HWM) { -+ int_val = luaL_checklong(L, ${val::idx}); -+ val = &int_val; -+ val_len = sizeof(int_val); -+ ${err} = zmq_setsockopt(${this}, ZMQ_SNDHWM, val, val_len); -+ if(-1 != ${err}) { -+ ${err} = zmq_setsockopt(${this}, ZMQ_RCVHWM, val, val_len); -+ } -+ goto finished; -+ } -+#endif -+ - if(${opt} > MAX_OPTS) { - return luaL_argerror(L, ${opt::idx}, "Invalid socket option."); - } - - switch(opt_types[${opt}]) { --#if VERSION_2_1 -+#if defined(VERSION_2_1) || defined(VERSION_3_0) - case OPT_TYPE_FD: - fd_val = luaL_checklong(L, ${val::idx}); - val = &fd_val; -@@ -178,7 +558,7 @@ end - val = &int64_val; - val_len = sizeof(int64_val); - break; -- case OPT_TYPE_STR: -+ case OPT_TYPE_BLOB: - val = luaL_checklstring(L, ${val::idx}, &(val_len)); - break; - default: -@@ -187,20 +567,15 @@ end - break; - } - ${err} = zmq_setsockopt(${this}, ${opt}, val, val_len); -+finished: - ]], - ffi_source[[ -- local ctype = option_types[${opt}] -- local tval -- local tval_len = 0 -- if ctype == 'string' then -- tval = tostring(${val}) -- tval_len = #${val} -+ local set = option_sets[${opt}] -+ if set then -+ return set(${this},${val}) - else -- tval = option_tmps[${opt}] -- tval[0] = ${val} -- tval_len = option_len[${opt}] -+ error("Invalid socket option.") - end -- ${err} = C.zmq_setsockopt(${this}, ${opt}, tval, tval_len) - ]], - }, - ffi_source[[ -@@ -213,7 +588,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) - c_source[[ - size_t val_len; - --#if VERSION_2_1 -+#if defined(VERSION_2_1) || defined(VERSION_3_0) - socket_t fd_val; - #endif - int int_val; -@@ -230,7 +605,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) - } - - switch(opt_types[${opt}]) { --#if VERSION_2_1 -+#if defined(VERSION_2_1) || defined(VERSION_3_0) - case OPT_TYPE_FD: - val_len = sizeof(fd_val); - ${err} = zmq_getsockopt(${this}, ${opt}, &fd_val, &val_len); -@@ -272,7 +647,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) - return 1; - } - break; -- case OPT_TYPE_STR: -+ case OPT_TYPE_BLOB: - val_len = STR_MAX; - ${err} = zmq_getsockopt(${this}, ${opt}, str_val, &val_len); - if(0 == ${err}) { -@@ -289,62 +664,23 @@ local tmp_val_len = ffi.new('size_t[1]', 4) - lua_pushnil(L); - ]], - ffi_source[[ -- local ctype = option_types[${opt}] -- local val -- local val_len = tmp_val_len -- if ctype == 'string' then -- val_len[0] = 255 -- val = ffi.new('uint8_t[?]', val_len[0]) -- ffi.fill(val, val_len[0]) -+ local get = option_gets[${opt}] -+ if get then -+ return get(${this}) - else -- val = option_tmps[${opt}] -- val[0] = 0 -- val_len[0] = option_len[${opt}] -- end -- ${err} = C.zmq_getsockopt(${this}, ${opt}, val, val_len) -- if ${err} == 0 then -- if ctype == 'string' then -- val_len = val_len[0] -- return ffi.string(val, val_len) -- else -- return tonumber(val[0]) -- end -+ error("Invalid socket option.") - end - ]], - }, -- ffi_source[[ ---- temp. values for 'events' function. --local events_tmp = ffi.new('uint32_t[1]', 0) --local events_tmp_size = ffi.sizeof('uint32_t') --local events_tmp_len = ffi.new('size_t[1]', events_tmp_size) --local ZMQ_EVENTS = _M.EVENTS --]], -- method "events" { -- var_out{ "uint32_t", "events" }, -- var_out{ "ZMQ_Error", "err" }, -- c_source[[ --#if VERSION_2_1 -- size_t val_len = sizeof(${events}); -- ${err} = zmq_getsockopt(${this}, ZMQ_EVENTS, &(${events}), &val_len); --#else -- luaL_error(L, "'events' method only supported in 0MQ version >= 2.1"); --#endif --]], -- ffi_source[[ -- events_tmp_len[0] = events_tmp_size -- ${err} = C.zmq_getsockopt(${this}, ZMQ_EVENTS, events_tmp, events_tmp_len); -- ${events} = events_tmp[0] --]], -- }, - -- - -- zmq_send - -- - method "send_msg" { -- c_method_call "ZMQ_Error" "zmq_send" { "zmq_msg_t *", "msg", "int", "flags?" }, -+ c_method_call "ZMQ_Error" "zmq_sendmsg" { "zmq_msg_t *", "msg", "int", "flags?" }, - }, - -- create helper function for `zmq_send` - c_source[[ --static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { -+LUA_NOBJ_API ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { - ZMQ_Error err; - zmq_msg_t msg; - /* initialize message */ -@@ -353,32 +689,22 @@ static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data - /* fill message */ - memcpy(zmq_msg_data(&msg), data, data_len); - /* send message */ -- err = zmq_send(sock, &msg, flags); -+ err = zmq_sendmsg(sock, &msg, flags); - /* close message */ - zmq_msg_close(&msg); - } - return err; - } - ]], -- -- export helper function. -- ffi_export_function "ZMQ_Error" "simple_zmq_send" -- "(ZMQ_Socket *sock, const char *data, size_t data_len, int flags)", - method "send" { -- var_in{ "const char *", "data" }, -- var_in{ "int", "flags?" }, -- var_out{ "ZMQ_Error", "err" }, -- c_source[[ -- ${err} = simple_zmq_send(${this}, ${data}, ${data_len}, ${flags}); --]], -- ffi_source[[ -- ${err} = simple_zmq_send(${this}, ${data}, ${data_len}, ${flags}); --]], -+ c_export_method_call "ZMQ_Error" "simple_zmq_send" -+ { "const char *", "data", "size_t", "#data", "int", "flags?"} - }, - -- - -- zmq_recv - -- - method "recv_msg" { -- c_method_call "ZMQ_Error" "zmq_recv" { "zmq_msg_t *", "msg", "int", "flags?" }, -+ c_method_call "ZMQ_Error" "zmq_recvmsg" { "zmq_msg_t *", "msg", "int", "flags?" }, - }, - ffi_source[[ - local tmp_msg = ffi.new('zmq_msg_t') -@@ -393,8 +719,8 @@ local tmp_msg = ffi.new('zmq_msg_t') - ${err} = zmq_msg_init(&msg); - if(0 == ${err}) { - /* receive message */ -- ${err} = zmq_recv(${this}, &msg, ${flags}); -- if(0 == ${err}) { -+ ${err} = zmq_recvmsg(${this}, &msg, ${flags}); -+ if(${err} >= 0) { - ${data} = zmq_msg_data(&msg); - ${data_len} = zmq_msg_size(&msg); - } -@@ -412,8 +738,8 @@ local tmp_msg = ffi.new('zmq_msg_t') - end - - -- receive message -- ${err} = C.zmq_recv(${this}, msg, ${flags}) -- if 0 == ${err} then -+ ${err} = C.zmq_recvmsg(${this}, msg, ${flags}) -+ if ${err} >= 0 then - local data = ffi.string(C.zmq_msg_data(msg), C.zmq_msg_size(msg)) - -- close message - C.zmq_msg_close(msg) -@@ -425,5 +751,8 @@ local tmp_msg = ffi.new('zmq_msg_t') - C.zmq_msg_close(msg) - ]], - }, -+ -+ -- build option set/get methods. THIS MUST BE LAST. -+ build_option_methods(), - } - -diff --git a/src/threads.lua b/src/threads.lua -index 99257ea..e37838a 100644 ---- a/src/threads.lua -+++ b/src/threads.lua -@@ -85,26 +85,28 @@ local function new_thread(ctx, action, action_arg, ...) - }, thread_mt) - end - --module(...) -+local M = {} - --function set_bootstrap_prelude(code) -+function M.set_bootstrap_prelude(code) - bootstrap_code = bootstrap_pre .. code .. bootstrap_post - end - --function runfile(ctx, file, ...) -+function M.runfile(ctx, file, ...) - return new_thread(ctx, 'runfile', file, ...) - end - --function runstring(ctx, code, ...) -+function M.runstring(ctx, code, ...) - return new_thread(ctx, 'runstring', code, ...) - end - - local parent_ctx = nil --function set_parent_ctx(ctx) -+function M.set_parent_ctx(ctx) - parent_ctx = ctx - end - --function get_parent_ctx(ctx) -+function M.get_parent_ctx(ctx) - return parent_ctx - end - -+zmq.threads = M -+return M -diff --git a/ws/LICENSE_GPL.txt b/ws/LICENSE_GPL.txt -new file mode 100644 -index 0000000..94a9ed0 ---- /dev/null -+++ b/ws/LICENSE_GPL.txt -@@ -0,0 +1,674 @@ -+ GNU GENERAL PUBLIC LICENSE -+ Version 3, 29 June 2007 -+ -+ Copyright (C) 2007 Free Software Foundation, Inc. -+ Everyone is permitted to copy and distribute verbatim copies -+ of this license document, but changing it is not allowed. -+ -+ Preamble -+ -+ The GNU General Public License is a free, copyleft license for -+software and other kinds of works. -+ -+ The licenses for most software and other practical works are designed -+to take away your freedom to share and change the works. By contrast, -+the GNU General Public License is intended to guarantee your freedom to -+share and change all versions of a program--to make sure it remains free -+software for all its users. We, the Free Software Foundation, use the -+GNU General Public License for most of our software; it applies also to -+any other work released this way by its authors. You can apply it to -+your programs, too. -+ -+ When we speak of free software, we are referring to freedom, not -+price. Our General Public Licenses are designed to make sure that you -+have the freedom to distribute copies of free software (and charge for -+them if you wish), that you receive source code or can get it if you -+want it, that you can change the software or use pieces of it in new -+free programs, and that you know you can do these things. -+ -+ To protect your rights, we need to prevent others from denying you -+these rights or asking you to surrender the rights. Therefore, you have -+certain responsibilities if you distribute copies of the software, or if -+you modify it: responsibilities to respect the freedom of others. -+ -+ For example, if you distribute copies of such a program, whether -+gratis or for a fee, you must pass on to the recipients the same -+freedoms that you received. You must make sure that they, too, receive -+or can get the source code. And you must show them these terms so they -+know their rights. -+ -+ Developers that use the GNU GPL protect your rights with two steps: -+(1) assert copyright on the software, and (2) offer you this License -+giving you legal permission to copy, distribute and/or modify it. -+ -+ For the developers' and authors' protection, the GPL clearly explains -+that there is no warranty for this free software. For both users' and -+authors' sake, the GPL requires that modified versions be marked as -+changed, so that their problems will not be attributed erroneously to -+authors of previous versions. -+ -+ Some devices are designed to deny users access to install or run -+modified versions of the software inside them, although the manufacturer -+can do so. This is fundamentally incompatible with the aim of -+protecting users' freedom to change the software. The systematic -+pattern of such abuse occurs in the area of products for individuals to -+use, which is precisely where it is most unacceptable. Therefore, we -+have designed this version of the GPL to prohibit the practice for those -+products. If such problems arise substantially in other domains, we -+stand ready to extend this provision to those domains in future versions -+of the GPL, as needed to protect the freedom of users. -+ -+ Finally, every program is threatened constantly by software patents. -+States should not allow patents to restrict development and use of -+software on general-purpose computers, but in those that do, we wish to -+avoid the special danger that patents applied to a free program could -+make it effectively proprietary. To prevent this, the GPL assures that -+patents cannot be used to render the program non-free. -+ -+ The precise terms and conditions for copying, distribution and -+modification follow. -+ -+ TERMS AND CONDITIONS -+ -+ 0. Definitions. -+ -+ "This License" refers to version 3 of the GNU General Public License. -+ -+ "Copyright" also means copyright-like laws that apply to other kinds of -+works, such as semiconductor masks. -+ -+ "The Program" refers to any copyrightable work licensed under this -+License. Each licensee is addressed as "you". "Licensees" and -+"recipients" may be individuals or organizations. -+ -+ To "modify" a work means to copy from or adapt all or part of the work -+in a fashion requiring copyright permission, other than the making of an -+exact copy. The resulting work is called a "modified version" of the -+earlier work or a work "based on" the earlier work. -+ -+ A "covered work" means either the unmodified Program or a work based -+on the Program. -+ -+ To "propagate" a work means to do anything with it that, without -+permission, would make you directly or secondarily liable for -+infringement under applicable copyright law, except executing it on a -+computer or modifying a private copy. Propagation includes copying, -+distribution (with or without modification), making available to the -+public, and in some countries other activities as well. -+ -+ To "convey" a work means any kind of propagation that enables other -+parties to make or receive copies. Mere interaction with a user through -+a computer network, with no transfer of a copy, is not conveying. -+ -+ An interactive user interface displays "Appropriate Legal Notices" -+to the extent that it includes a convenient and prominently visible -+feature that (1) displays an appropriate copyright notice, and (2) -+tells the user that there is no warranty for the work (except to the -+extent that warranties are provided), that licensees may convey the -+work under this License, and how to view a copy of this License. If -+the interface presents a list of user commands or options, such as a -+menu, a prominent item in the list meets this criterion. -+ -+ 1. Source Code. -+ -+ The "source code" for a work means the preferred form of the work -+for making modifications to it. "Object code" means any non-source -+form of a work. -+ -+ A "Standard Interface" means an interface that either is an official -+standard defined by a recognized standards body, or, in the case of -+interfaces specified for a particular programming language, one that -+is widely used among developers working in that language. -+ -+ The "System Libraries" of an executable work include anything, other -+than the work as a whole, that (a) is included in the normal form of -+packaging a Major Component, but which is not part of that Major -+Component, and (b) serves only to enable use of the work with that -+Major Component, or to implement a Standard Interface for which an -+implementation is available to the public in source code form. A -+"Major Component", in this context, means a major essential component -+(kernel, window system, and so on) of the specific operating system -+(if any) on which the executable work runs, or a compiler used to -+produce the work, or an object code interpreter used to run it. -+ -+ The "Corresponding Source" for a work in object code form means all -+the source code needed to generate, install, and (for an executable -+work) run the object code and to modify the work, including scripts to -+control those activities. However, it does not include the work's -+System Libraries, or general-purpose tools or generally available free -+programs which are used unmodified in performing those activities but -+which are not part of the work. For example, Corresponding Source -+includes interface definition files associated with source files for -+the work, and the source code for shared libraries and dynamically -+linked subprograms that the work is specifically designed to require, -+such as by intimate data communication or control flow between those -+subprograms and other parts of the work. -+ -+ The Corresponding Source need not include anything that users -+can regenerate automatically from other parts of the Corresponding -+Source. -+ -+ The Corresponding Source for a work in source code form is that -+same work. -+ -+ 2. Basic Permissions. -+ -+ All rights granted under this License are granted for the term of -+copyright on the Program, and are irrevocable provided the stated -+conditions are met. This License explicitly affirms your unlimited -+permission to run the unmodified Program. The output from running a -+covered work is covered by this License only if the output, given its -+content, constitutes a covered work. This License acknowledges your -+rights of fair use or other equivalent, as provided by copyright law. -+ -+ You may make, run and propagate covered works that you do not -+convey, without conditions so long as your license otherwise remains -+in force. You may convey covered works to others for the sole purpose -+of having them make modifications exclusively for you, or provide you -+with facilities for running those works, provided that you comply with -+the terms of this License in conveying all material for which you do -+not control copyright. Those thus making or running the covered works -+for you must do so exclusively on your behalf, under your direction -+and control, on terms that prohibit them from making any copies of -+your copyrighted material outside their relationship with you. -+ -+ Conveying under any other circumstances is permitted solely under -+the conditions stated below. Sublicensing is not allowed; section 10 -+makes it unnecessary. -+ -+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law. -+ -+ No covered work shall be deemed part of an effective technological -+measure under any applicable law fulfilling obligations under article -+11 of the WIPO copyright treaty adopted on 20 December 1996, or -+similar laws prohibiting or restricting circumvention of such -+measures. -+ -+ When you convey a covered work, you waive any legal power to forbid -+circumvention of technological measures to the extent such circumvention -+is effected by exercising rights under this License with respect to -+the covered work, and you disclaim any intention to limit operation or -+modification of the work as a means of enforcing, against the work's -+users, your or third parties' legal rights to forbid circumvention of -+technological measures. -+ -+ 4. Conveying Verbatim Copies. -+ -+ You may convey verbatim copies of the Program's source code as you -+receive it, in any medium, provided that you conspicuously and -+appropriately publish on each copy an appropriate copyright notice; -+keep intact all notices stating that this License and any -+non-permissive terms added in accord with section 7 apply to the code; -+keep intact all notices of the absence of any warranty; and give all -+recipients a copy of this License along with the Program. -+ -+ You may charge any price or no price for each copy that you convey, -+and you may offer support or warranty protection for a fee. -+ -+ 5. Conveying Modified Source Versions. -+ -+ You may convey a work based on the Program, or the modifications to -+produce it from the Program, in the form of source code under the -+terms of section 4, provided that you also meet all of these conditions: -+ -+ a) The work must carry prominent notices stating that you modified -+ it, and giving a relevant date. -+ -+ b) The work must carry prominent notices stating that it is -+ released under this License and any conditions added under section -+ 7. This requirement modifies the requirement in section 4 to -+ "keep intact all notices". -+ -+ c) You must license the entire work, as a whole, under this -+ License to anyone who comes into possession of a copy. This -+ License will therefore apply, along with any applicable section 7 -+ additional terms, to the whole of the work, and all its parts, -+ regardless of how they are packaged. This License gives no -+ permission to license the work in any other way, but it does not -+ invalidate such permission if you have separately received it. -+ -+ d) If the work has interactive user interfaces, each must display -+ Appropriate Legal Notices; however, if the Program has interactive -+ interfaces that do not display Appropriate Legal Notices, your -+ work need not make them do so. -+ -+ A compilation of a covered work with other separate and independent -+works, which are not by their nature extensions of the covered work, -+and which are not combined with it such as to form a larger program, -+in or on a volume of a storage or distribution medium, is called an -+"aggregate" if the compilation and its resulting copyright are not -+used to limit the access or legal rights of the compilation's users -+beyond what the individual works permit. Inclusion of a covered work -+in an aggregate does not cause this License to apply to the other -+parts of the aggregate. -+ -+ 6. Conveying Non-Source Forms. -+ -+ You may convey a covered work in object code form under the terms -+of sections 4 and 5, provided that you also convey the -+machine-readable Corresponding Source under the terms of this License, -+in one of these ways: -+ -+ a) Convey the object code in, or embodied in, a physical product -+ (including a physical distribution medium), accompanied by the -+ Corresponding Source fixed on a durable physical medium -+ customarily used for software interchange. -+ -+ b) Convey the object code in, or embodied in, a physical product -+ (including a physical distribution medium), accompanied by a -+ written offer, valid for at least three years and valid for as -+ long as you offer spare parts or customer support for that product -+ model, to give anyone who possesses the object code either (1) a -+ copy of the Corresponding Source for all the software in the -+ product that is covered by this License, on a durable physical -+ medium customarily used for software interchange, for a price no -+ more than your reasonable cost of physically performing this -+ conveying of source, or (2) access to copy the -+ Corresponding Source from a network server at no charge. -+ -+ c) Convey individual copies of the object code with a copy of the -+ written offer to provide the Corresponding Source. This -+ alternative is allowed only occasionally and noncommercially, and -+ only if you received the object code with such an offer, in accord -+ with subsection 6b. -+ -+ d) Convey the object code by offering access from a designated -+ place (gratis or for a charge), and offer equivalent access to the -+ Corresponding Source in the same way through the same place at no -+ further charge. You need not require recipients to copy the -+ Corresponding Source along with the object code. If the place to -+ copy the object code is a network server, the Corresponding Source -+ may be on a different server (operated by you or a third party) -+ that supports equivalent copying facilities, provided you maintain -+ clear directions next to the object code saying where to find the -+ Corresponding Source. Regardless of what server hosts the -+ Corresponding Source, you remain obligated to ensure that it is -+ available for as long as needed to satisfy these requirements. -+ -+ e) Convey the object code using peer-to-peer transmission, provided -+ you inform other peers where the object code and Corresponding -+ Source of the work are being offered to the general public at no -+ charge under subsection 6d. -+ -+ A separable portion of the object code, whose source code is excluded -+from the Corresponding Source as a System Library, need not be -+included in conveying the object code work. -+ -+ A "User Product" is either (1) a "consumer product", which means any -+tangible personal property which is normally used for personal, family, -+or household purposes, or (2) anything designed or sold for incorporation -+into a dwelling. In determining whether a product is a consumer product, -+doubtful cases shall be resolved in favor of coverage. For a particular -+product received by a particular user, "normally used" refers to a -+typical or common use of that class of product, regardless of the status -+of the particular user or of the way in which the particular user -+actually uses, or expects or is expected to use, the product. A product -+is a consumer product regardless of whether the product has substantial -+commercial, industrial or non-consumer uses, unless such uses represent -+the only significant mode of use of the product. -+ -+ "Installation Information" for a User Product means any methods, -+procedures, authorization keys, or other information required to install -+and execute modified versions of a covered work in that User Product from -+a modified version of its Corresponding Source. The information must -+suffice to ensure that the continued functioning of the modified object -+code is in no case prevented or interfered with solely because -+modification has been made. -+ -+ If you convey an object code work under this section in, or with, or -+specifically for use in, a User Product, and the conveying occurs as -+part of a transaction in which the right of possession and use of the -+User Product is transferred to the recipient in perpetuity or for a -+fixed term (regardless of how the transaction is characterized), the -+Corresponding Source conveyed under this section must be accompanied -+by the Installation Information. But this requirement does not apply -+if neither you nor any third party retains the ability to install -+modified object code on the User Product (for example, the work has -+been installed in ROM). -+ -+ The requirement to provide Installation Information does not include a -+requirement to continue to provide support service, warranty, or updates -+for a work that has been modified or installed by the recipient, or for -+the User Product in which it has been modified or installed. Access to a -+network may be denied when the modification itself materially and -+adversely affects the operation of the network or violates the rules and -+protocols for communication across the network. -+ -+ Corresponding Source conveyed, and Installation Information provided, -+in accord with this section must be in a format that is publicly -+documented (and with an implementation available to the public in -+source code form), and must require no special password or key for -+unpacking, reading or copying. -+ -+ 7. Additional Terms. -+ -+ "Additional permissions" are terms that supplement the terms of this -+License by making exceptions from one or more of its conditions. -+Additional permissions that are applicable to the entire Program shall -+be treated as though they were included in this License, to the extent -+that they are valid under applicable law. If additional permissions -+apply only to part of the Program, that part may be used separately -+under those permissions, but the entire Program remains governed by -+this License without regard to the additional permissions. -+ -+ When you convey a copy of a covered work, you may at your option -+remove any additional permissions from that copy, or from any part of -+it. (Additional permissions may be written to require their own -+removal in certain cases when you modify the work.) You may place -+additional permissions on material, added by you to a covered work, -+for which you have or can give appropriate copyright permission. -+ -+ Notwithstanding any other provision of this License, for material you -+add to a covered work, you may (if authorized by the copyright holders of -+that material) supplement the terms of this License with terms: -+ -+ a) Disclaiming warranty or limiting liability differently from the -+ terms of sections 15 and 16 of this License; or -+ -+ b) Requiring preservation of specified reasonable legal notices or -+ author attributions in that material or in the Appropriate Legal -+ Notices displayed by works containing it; or -+ -+ c) Prohibiting misrepresentation of the origin of that material, or -+ requiring that modified versions of such material be marked in -+ reasonable ways as different from the original version; or -+ -+ d) Limiting the use for publicity purposes of names of licensors or -+ authors of the material; or -+ -+ e) Declining to grant rights under trademark law for use of some -+ trade names, trademarks, or service marks; or -+ -+ f) Requiring indemnification of licensors and authors of that -+ material by anyone who conveys the material (or modified versions of -+ it) with contractual assumptions of liability to the recipient, for -+ any liability that these contractual assumptions directly impose on -+ those licensors and authors. -+ -+ All other non-permissive additional terms are considered "further -+restrictions" within the meaning of section 10. If the Program as you -+received it, or any part of it, contains a notice stating that it is -+governed by this License along with a term that is a further -+restriction, you may remove that term. If a license document contains -+a further restriction but permits relicensing or conveying under this -+License, you may add to a covered work material governed by the terms -+of that license document, provided that the further restriction does -+not survive such relicensing or conveying. -+ -+ If you add terms to a covered work in accord with this section, you -+must place, in the relevant source files, a statement of the -+additional terms that apply to those files, or a notice indicating -+where to find the applicable terms. -+ -+ Additional terms, permissive or non-permissive, may be stated in the -+form of a separately written license, or stated as exceptions; -+the above requirements apply either way. -+ -+ 8. Termination. -+ -+ You may not propagate or modify a covered work except as expressly -+provided under this License. Any attempt otherwise to propagate or -+modify it is void, and will automatically terminate your rights under -+this License (including any patent licenses granted under the third -+paragraph of section 11). -+ -+ However, if you cease all violation of this License, then your -+license from a particular copyright holder is reinstated (a) -+provisionally, unless and until the copyright holder explicitly and -+finally terminates your license, and (b) permanently, if the copyright -+holder fails to notify you of the violation by some reasonable means -+prior to 60 days after the cessation. -+ -+ Moreover, your license from a particular copyright holder is -+reinstated permanently if the copyright holder notifies you of the -+violation by some reasonable means, this is the first time you have -+received notice of violation of this License (for any work) from that -+copyright holder, and you cure the violation prior to 30 days after -+your receipt of the notice. -+ -+ Termination of your rights under this section does not terminate the -+licenses of parties who have received copies or rights from you under -+this License. If your rights have been terminated and not permanently -+reinstated, you do not qualify to receive new licenses for the same -+material under section 10. -+ -+ 9. Acceptance Not Required for Having Copies. -+ -+ You are not required to accept this License in order to receive or -+run a copy of the Program. Ancillary propagation of a covered work -+occurring solely as a consequence of using peer-to-peer transmission -+to receive a copy likewise does not require acceptance. However, -+nothing other than this License grants you permission to propagate or -+modify any covered work. These actions infringe copyright if you do -+not accept this License. Therefore, by modifying or propagating a -+covered work, you indicate your acceptance of this License to do so. -+ -+ 10. Automatic Licensing of Downstream Recipients. -+ -+ Each time you convey a covered work, the recipient automatically -+receives a license from the original licensors, to run, modify and -+propagate that work, subject to this License. You are not responsible -+for enforcing compliance by third parties with this License. -+ -+ An "entity transaction" is a transaction transferring control of an -+organization, or substantially all assets of one, or subdividing an -+organization, or merging organizations. If propagation of a covered -+work results from an entity transaction, each party to that -+transaction who receives a copy of the work also receives whatever -+licenses to the work the party's predecessor in interest had or could -+give under the previous paragraph, plus a right to possession of the -+Corresponding Source of the work from the predecessor in interest, if -+the predecessor has it or can get it with reasonable efforts. -+ -+ You may not impose any further restrictions on the exercise of the -+rights granted or affirmed under this License. For example, you may -+not impose a license fee, royalty, or other charge for exercise of -+rights granted under this License, and you may not initiate litigation -+(including a cross-claim or counterclaim in a lawsuit) alleging that -+any patent claim is infringed by making, using, selling, offering for -+sale, or importing the Program or any portion of it. -+ -+ 11. Patents. -+ -+ A "contributor" is a copyright holder who authorizes use under this -+License of the Program or a work on which the Program is based. The -+work thus licensed is called the contributor's "contributor version". -+ -+ A contributor's "essential patent claims" are all patent claims -+owned or controlled by the contributor, whether already acquired or -+hereafter acquired, that would be infringed by some manner, permitted -+by this License, of making, using, or selling its contributor version, -+but do not include claims that would be infringed only as a -+consequence of further modification of the contributor version. For -+purposes of this definition, "control" includes the right to grant -+patent sublicenses in a manner consistent with the requirements of -+this License. -+ -+ Each contributor grants you a non-exclusive, worldwide, royalty-free -+patent license under the contributor's essential patent claims, to -+make, use, sell, offer for sale, import and otherwise run, modify and -+propagate the contents of its contributor version. -+ -+ In the following three paragraphs, a "patent license" is any express -+agreement or commitment, however denominated, not to enforce a patent -+(such as an express permission to practice a patent or covenant not to -+sue for patent infringement). To "grant" such a patent license to a -+party means to make such an agreement or commitment not to enforce a -+patent against the party. -+ -+ If you convey a covered work, knowingly relying on a patent license, -+and the Corresponding Source of the work is not available for anyone -+to copy, free of charge and under the terms of this License, through a -+publicly available network server or other readily accessible means, -+then you must either (1) cause the Corresponding Source to be so -+available, or (2) arrange to deprive yourself of the benefit of the -+patent license for this particular work, or (3) arrange, in a manner -+consistent with the requirements of this License, to extend the patent -+license to downstream recipients. "Knowingly relying" means you have -+actual knowledge that, but for the patent license, your conveying the -+covered work in a country, or your recipient's use of the covered work -+in a country, would infringe one or more identifiable patents in that -+country that you have reason to believe are valid. -+ -+ If, pursuant to or in connection with a single transaction or -+arrangement, you convey, or propagate by procuring conveyance of, a -+covered work, and grant a patent license to some of the parties -+receiving the covered work authorizing them to use, propagate, modify -+or convey a specific copy of the covered work, then the patent license -+you grant is automatically extended to all recipients of the covered -+work and works based on it. -+ -+ A patent license is "discriminatory" if it does not include within -+the scope of its coverage, prohibits the exercise of, or is -+conditioned on the non-exercise of one or more of the rights that are -+specifically granted under this License. You may not convey a covered -+work if you are a party to an arrangement with a third party that is -+in the business of distributing software, under which you make payment -+to the third party based on the extent of your activity of conveying -+the work, and under which the third party grants, to any of the -+parties who would receive the covered work from you, a discriminatory -+patent license (a) in connection with copies of the covered work -+conveyed by you (or copies made from those copies), or (b) primarily -+for and in connection with specific products or compilations that -+contain the covered work, unless you entered into that arrangement, -+or that patent license was granted, prior to 28 March 2007. -+ -+ Nothing in this License shall be construed as excluding or limiting -+any implied license or other defenses to infringement that may -+otherwise be available to you under applicable patent law. -+ -+ 12. No Surrender of Others' Freedom. -+ -+ If conditions are imposed on you (whether by court order, agreement or -+otherwise) that contradict the conditions of this License, they do not -+excuse you from the conditions of this License. If you cannot convey a -+covered work so as to satisfy simultaneously your obligations under this -+License and any other pertinent obligations, then as a consequence you may -+not convey it at all. For example, if you agree to terms that obligate you -+to collect a royalty for further conveying from those to whom you convey -+the Program, the only way you could satisfy both those terms and this -+License would be to refrain entirely from conveying the Program. -+ -+ 13. Use with the GNU Affero General Public License. -+ -+ Notwithstanding any other provision of this License, you have -+permission to link or combine any covered work with a work licensed -+under version 3 of the GNU Affero General Public License into a single -+combined work, and to convey the resulting work. The terms of this -+License will continue to apply to the part which is the covered work, -+but the special requirements of the GNU Affero General Public License, -+section 13, concerning interaction through a network will apply to the -+combination as such. -+ -+ 14. Revised Versions of this License. -+ -+ The Free Software Foundation may publish revised and/or new versions of -+the GNU General Public License from time to time. Such new versions will -+be similar in spirit to the present version, but may differ in detail to -+address new problems or concerns. -+ -+ Each version is given a distinguishing version number. If the -+Program specifies that a certain numbered version of the GNU General -+Public License "or any later version" applies to it, you have the -+option of following the terms and conditions either of that numbered -+version or of any later version published by the Free Software -+Foundation. If the Program does not specify a version number of the -+GNU General Public License, you may choose any version ever published -+by the Free Software Foundation. -+ -+ If the Program specifies that a proxy can decide which future -+versions of the GNU General Public License can be used, that proxy's -+public statement of acceptance of a version permanently authorizes you -+to choose that version for the Program. -+ -+ Later license versions may give you additional or different -+permissions. However, no additional obligations are imposed on any -+author or copyright holder as a result of your choosing to follow a -+later version. -+ -+ 15. Disclaimer of Warranty. -+ -+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -+ALL NECESSARY SERVICING, REPAIR OR CORRECTION. -+ -+ 16. Limitation of Liability. -+ -+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -+SUCH DAMAGES. -+ -+ 17. Interpretation of Sections 15 and 16. -+ -+ If the disclaimer of warranty and limitation of liability provided -+above cannot be given local legal effect according to their terms, -+reviewing courts shall apply local law that most closely approximates -+an absolute waiver of all civil liability in connection with the -+Program, unless a warranty or assumption of liability accompanies a -+copy of the Program in return for a fee. -+ -+ END OF TERMS AND CONDITIONS -+ -+ How to Apply These Terms to Your New Programs -+ -+ If you develop a new program, and you want it to be of the greatest -+possible use to the public, the best way to achieve this is to make it -+free software which everyone can redistribute and change under these terms. -+ -+ To do so, attach the following notices to the program. It is safest -+to attach them to the start of each source file to most effectively -+state the exclusion of warranty; and each file should have at least -+the "copyright" line and a pointer to where the full notice is found. -+ -+ -+ Copyright (C) -+ -+ This program is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+ -+Also add information on how to contact you by electronic and paper mail. -+ -+ If the program does terminal interaction, make it output a short -+notice like this when it starts in an interactive mode: -+ -+ Copyright (C) -+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -+ This is free software, and you are welcome to redistribute it -+ under certain conditions; type `show c' for details. -+ -+The hypothetical commands `show w' and `show c' should show the appropriate -+parts of the General Public License. Of course, your program's commands -+might be different; for a GUI interface, you would use an "about box". -+ -+ You should also get your employer (if you work as a programmer) or school, -+if any, to sign a "copyright disclaimer" for the program, if necessary. -+For more information on this, and how to apply and follow the GNU GPL, see -+. -+ -+ The GNU General Public License does not permit incorporating your program -+into proprietary programs. If your program is a subroutine library, you -+may consider it more useful to permit linking proprietary applications with -+the library. If this is what you want to do, use the GNU Lesser General -+Public License instead of this License. But first, please read -+. -diff --git a/ws/dissector.lua b/ws/dissector.lua -new file mode 100644 -index 0000000..0431c67 ---- /dev/null -+++ b/ws/dissector.lua -@@ -0,0 +1,306 @@ -+-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. -+ -+-- cache globals to local for speed. -+local format=string.format -+local tostring=tostring -+local tonumber=tonumber -+local sqrt=math.sqrt -+local pairs=pairs -+ -+-- wireshark API globals -+local Pref = Pref -+local Proto = Proto -+local ProtoField = ProtoField -+local DissectorTable = DissectorTable -+local ByteArray = ByteArray -+local PI_MALFORMED = PI_MALFORMED -+local PI_ERROR = PI_ERROR -+ -+-- zmq protocol example -+-- declare our protocol -+local zmq_proto = Proto("zmq","ZMQ","ZeroMQ Protocol") -+ -+-- setup preferences -+zmq_proto.prefs["tcp_port_start"] = -+ Pref.string("TCP port range start", "5555", "First TCP port to decode as this protocol") -+zmq_proto.prefs["tcp_port_end"] = -+ Pref.string("TCP port range end", "5555", "Last TCP port to decode as this protocol") -+-- current preferences settings. -+local current_settings = { -+tcp_port_start = -1, -+tcp_port_end = -1, -+} -+ -+-- setup protocol fields. -+zmq_proto.fields = {} -+local fds = zmq_proto.fields -+fds.frame = ProtoField.new("Frame", "zmq.frame", "FT_BYTES", nil, "BASE_NONE") -+fds.length = ProtoField.new("Frame Length", "zmq.frame.len", "FT_UINT64", nil, "BASE_DEC") -+fds.length8 = ProtoField.new("Frame 8bit Length", "zmq.frame.len8", "FT_UINT8", nil, "BASE_DEC") -+fds.length64 = ProtoField.new("Frame 64bit Length", "zmq.frame.len64", "FT_UINT64", nil, "BASE_DEC") -+fds.flags = ProtoField.new("Frame Flags", "zmq.frame.flags", "FT_UINT8", nil, "BASE_HEX", "0xFF") -+fds.flags_more = ProtoField.new("More", "zmq.frame.flags.more", "FT_UINT8", nil, "BASE_HEX", "0x01") -+fds.body = ProtoField.new("Frame body", "zmq.frame.body", "FT_BYTES", nil, "BASE_NONE") -+ -+-- un-register zmq to handle tcp port range -+local function unregister_tcp_port_range(start_port, end_port) -+ if not start_port or start_port <= 0 or not end_port or end_port <= 0 then -+ return -+ end -+ local tcp_port_table = DissectorTable.get("tcp.port") -+ for port = start_port,end_port do -+ tcp_port_table:remove(port,zmq_proto) -+ end -+end -+ -+-- register zmq to handle tcp port range -+local function register_tcp_port_range(start_port, end_port) -+ if not start_port or start_port <= 0 or not end_port or end_port <= 0 then -+ return -+ end -+ local tcp_port_table = DissectorTable.get("tcp.port") -+ for port = start_port,end_port do -+ tcp_port_table:add(port,zmq_proto) -+ end -+end -+ -+-- handle preferences changes. -+function zmq_proto.init(arg1, arg2) -+ local old_start, old_end -+ local new_start, new_end -+ -- check if preferences have changed. -+ for pref_name,old_v in pairs(current_settings) do -+ local new_v = zmq_proto.prefs[pref_name] -+ if new_v ~= old_v then -+ if pref_name == "tcp_port_start" then -+ old_start = old_v -+ new_start = new_v -+ elseif pref_name == "tcp_port_end" then -+ old_end = old_v -+ new_end = new_v -+ end -+ -- save new value. -+ current_settings[pref_name] = new_v -+ end -+ end -+ -- un-register old port range -+ if old_start and old_end then -+ unregister_tcp_port_range(tonumber(old_start), tonumber(old_end)) -+ end -+ -- register new port range. -+ if new_start and new_end then -+ register_tcp_port_range(tonumber(new_start), tonumber(new_end)) -+ end -+end -+ -+-- parse flag bits. -+local BITS = { -+ MORE = 0x01, -+ RESERVED = 0x7E, -+} -+local flag_names = {"MORE"} -+local bits_lookup = {} -+local bits_list = { -+ {}, -+ {MORE = true}, -+ {MORE = true, RESERVED = true}, -+ {RESERVED = true}, -+} -+local function parse_flags(flags) -+ return bits_lookup[flags] or bits_lookup[1] -+end -+ -+-- make bits object -+local function make_bits(bits) -+ local proxy = newproxy(true) -+ local meta = getmetatable(proxy) -+ meta.__index = bits -+ meta.__tostring = function() -+ return bits.flags -+ end -+ -- combind bits into string description. -+ local flags = nil -+ for i=1,#flag_names do -+ local name = flag_names[i] -+ if bits[name] then -+ if flags then -+ flags = flags .. ',' .. name -+ else -+ flags = name -+ end -+ end -+ end -+ -- combind bits into one byte value. -+ local byte = 0x00 -+ for k,v in pairs(bits) do -+ local bit = assert(BITS[k], "Invalid bit name.") -+ byte = byte + BITS[k] -+ end -+ bits.flags = flags or '' -+ bits.byte = byte -+ return proxy -+end -+-- make bits objects in bis_lookup -+for i=1,#bits_list do -+ local bits = bits_list[i] -+ bits = make_bits(bits) -+ bits_lookup[bits.byte] = bits -+end -+ -+local function zmq_dissect_frame(buffer, pinfo, frame_tree, tap) -+ local rang,offset -+ -- Frame length -+ offset = 0 -+ local len_off = offset -+ local len8_rang = buffer(offset,1) -+ local len_rang = len8_rang -+ local frame_len = len8_rang:uint() -+ -- 8bit length field -+ local ti = frame_tree:add(fds.length8, len8_rang) -+ ti:set_hidden() -+ offset = offset + 1 -+ if frame_len == 255 then -+ local len64_rang = buffer(offset, 8) -+ len_rang = buffer(len_off, 9) -+ frame_len = tonumber(tostring(len64_rang:uint64())) -+ -- 64bit length field. -+ local ti = frame_tree:add(fds.length64, len64_rang) -+ ti:set_hidden() -+ offset = offset + 8 -+ local ti = frame_tree:add(fds.length, len_rang) -+ ti:set_text(format("Frame Length: %d", frame_length)) -+ else -+ frame_tree:add(fds.length, len_rang) -+ end -+ -- Frame flags -+ rang = buffer(offset,1) -+ local flags = rang:uint() -+ local flags_bits = parse_flags(flags) -+ local flags_list = flags_bits.flags -+ local flags_tree = frame_tree:add(fds.flags, rang) -+ flags_tree:set_text(format('Flags: 0x%02X (%s)', flags, flags_list)) -+ flags_tree:add(fds.flags_more, rang) -+ offset = offset + 1 -+ if flags_bits.MORE then -+ tap.more = tap.more + 1 -+ else -+ -- if the 'more' flag is not set then this is the last frame in a message. -+ tap.msgs = tap.msgs + 1 -+ end -+ -- Frame body -+ local body_len = frame_len - 1 -+ local body = '' -+ if body_len > 0 then -+ tap.body_bytes = tap.body_bytes + body_len -+ rang = buffer(offset, body_len) -+ local ti = frame_tree:add_le(fds.body, rang) -+ if body_len <= 4 then -+ body = format("%08x", rang:uint()) -+ else -+ body = tostring(rang) -+ end -+ ti:set_text(format("%s", body)) -+ end -+ offset = offset + body_len -+ -- frame summary -+ if body_len > 0 then -+ if flags_bits.MORE then -+ frame_tree:set_text(format("Frame: [MORE] Body[%u]=%s", body_len, body)) -+ else -+ frame_tree:set_text(format("Frame: Body[%u]=%s", body_len, body)) -+ end -+ else -+ if flags_bits.MORE then -+ frame_tree:set_text(format("Frame: [MORE] No data")) -+ else -+ frame_tree:set_text(format("Frame: No data")) -+ end -+ end -+end -+ -+local DESEGMENT_ONE_MORE_SEGMENT = 0x0fffffff -+local DESEGMENT_UNTIL_FIN = 0x0ffffffe -+ -+-- packet dissector -+function zmq_proto.dissector(tvb,pinfo,tree) -+ local offset = 0 -+ local tvb_length = tvb:len() -+ local reported_length = tvb:reported_len() -+ local length_remaining -+ local zmq_tree -+ local rang -+ local frames = 0 -+ local tap = {} -+ -+ tap.frames = 0 -+ tap.msgs = 0 -+ tap.more = 0 -+ tap.body_bytes = 0 -+ -+ while(offset < reported_length and offset < tvb_length) do -+ length_remaining = tvb_length - offset -+ -- check for fixed part of PDU -+ if length_remaining < 2 then -+ pinfo.desegment_offset = offset -+ pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT -+ break -+ end -+ -- decode frame length -+ -- decode single byte frame length -+ rang = tvb(offset, 1) -+ local frame_len = rang:le_uint() -+ local pdu_len = frame_len + 1 -+ if frame_len == 255 then -+ -- make sure there is enough bytes -+ if length_remaining < 10 then -+ pinfo.desegment_offset = offset -+ pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT -+ break -+ end -+ -- decode extra long frame length. -+ rang = tvb(offset + 1, 8) -+ frame_len = tonumber(tostring(rang:uint64())) -+ pdu_len = frame_len + 9 -+ end -+ -- provide hints to tcp -+ if not pinfo.visited then -+ local remaining_bytes = reported_length - offset -+ if pdu_len > remaining_bytes then -+ pinfo.want_pdu_tracking = 2 -+ pinfo.bytes_until_next_pdu = pdu_len - remaining_bytes -+ end -+ end -+ -- check if we need more bytes to dissect this frame. -+ if length_remaining < pdu_len then -+ pinfo.desegment_offset = offset -+ pinfo.desegment_len = (pdu_len - length_remaining) -+ break -+ end -+ -- dissect zmq frame -+ if not zmq_tree then -+ zmq_tree = tree:add(zmq_proto,tvb(),"ZMQ frames") -+ end -+ rang = tvb(offset, pdu_len) -+ local frame_tree = zmq_tree:add(fds.frame, rang) -+ zmq_dissect_frame(rang:tvb(), pinfo, frame_tree, tap) -+ frames = frames + 1 -+ -- step to next frame. -+ local offset_before = offset -+ offset = offset + pdu_len -+ if offset < offset_before then break end -+ end -+ if zmq_tree then -+ zmq_tree:set_text(format("ZMQ frames=%u", frames)) -+ end -+ if frames > 0 then -+ tap.frames = frames -+ pinfo.tap_data = tap -+ end -+ -- Info column -+ pinfo.cols.protocol = "ZMQ" -+ pinfo.cols.info = format('ZMQ frames=%u',frames) -+end -+ -+-- register zmq to handle tcp ports 5550-5560 -+register_tcp_port_range(5550,5560) -+ -diff --git a/ws/init.lua b/ws/init.lua -new file mode 100644 -index 0000000..0282fba ---- /dev/null -+++ b/ws/init.lua -@@ -0,0 +1,16 @@ -+ -+local prequire = function(name) -+ local status, result1 = pcall(require, name) -+ if not status then -+ debug("Failed to load " .. name .. ": " .. result1) -+ end -+ return result1 -+end -+ -+prequire("zmq.ws.dissector") -+ -+-- if running from wireshark, register all taps. -+if gui_enabled() then -+ prequire("zmq.ws.stats_tap") -+end -+ -diff --git a/ws/stats_tap.lua b/ws/stats_tap.lua -new file mode 100644 -index 0000000..1d39f16 ---- /dev/null -+++ b/ws/stats_tap.lua -@@ -0,0 +1,58 @@ -+-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. -+ -+local tap = require"zmq.ws.tap" -+ -+local format = string.format -+ -+local stats_tap_mt = {} -+stats_tap_mt.__index = stats_tap_mt -+ -+function stats_tap_mt:packet(pinfo, tvb, tree, data) -+ -- count all ZeroMQ packets -+ self.count = self.count + 1 -+ data = data or pinfo.tap_data -+ if not data then -+ return -+ end -+ -- frames -+ self.frames = self.frames + (data.frames or 0) -+ -- frames with more flag set -+ self.more = self.more + (data.more or 0) -+ -- whole messages. -+ self.msgs = self.msgs + (data.msgs or 0) -+ -- total bytes in frame bodies. -+ self.body_bytes = self.body_bytes + (data.body_bytes or 0) -+end -+ -+function stats_tap_mt:draw() -+ return format([[ -+ZeroMQ Packets: %d -+Frames: %d -+Messages: %d -+Flags: More: %d -+Payload bytes: %d -+]], -+ self.count, -+ self.frames, -+ self.msgs, -+ self.more, -+ self.body_bytes) -+end -+ -+function stats_tap_mt:reset() -+ self.count = 0 -+ self.frames = 0 -+ self.msgs = 0 -+ self.more = 0 -+ self.body_bytes = 0 -+end -+ -+local function create_stats_tap() -+ local tap = setmetatable({}, stats_tap_mt) -+ -+ tap:reset() -- initialize tap. -+ return tap, 'zmq', 'lua' -+end -+ -+tap("ZeroMQ stats tap", create_stats_tap) -+ -diff --git a/ws/tap.lua b/ws/tap.lua -new file mode 100644 -index 0000000..096332d ---- /dev/null -+++ b/ws/tap.lua -@@ -0,0 +1,84 @@ -+-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. -+ -+local gui_enabled = gui_enabled -+local register_menu = register_menu -+local MENU_TOOLS_UNSORTED = MENU_TOOLS_UNSORTED -+ -+local win_instances = 0 -+ -+local function create_window_tap(name, create) -+ win_instances = win_instances + 1 -+ -+ local td, tap_filter, tap_type = create() -+ -+ -- tap's output window. -+ local win = TextWindow.new(name .. " " .. win_instances) -+ -+ -- this tap will be local to the menu_function that called it -+ local tap = Listener.new(tap_type, tap_filter) -+ -+ -- callback to remove the tap when the text window closes -+ function remove_tap() -+ if tap and tap.remove then -+ tap:remove() -+ end -+ end -+ -+ -- make sure the tap doesn't hang around after the window was closed -+ win:set_atclose(remove_tap) -+ -+ -- this function will be called for every packet -+ function tap.packet(pinfo,tvb, tree, tapdata) -+ return td:packet(pinfo, tvb, tree, tapdata) -+ end -+ -+ -- this function will be called once every few seconds to redraw the window -+ function tap.draw() -+ local text = td:draw() -+ win:set(text) -+ end -+ -+ -- this function will be called at the end of the capture run. -+ function tap.reset() -+ return td:reset() -+ end -+end -+ -+local function create_tshark_tap(name, create) -+ -+ local td, tap_filter, tap_type = create() -+ -+ -- this tap will be local to the menu_function that called it -+ local tap = Listener.new(tap_type, tap_filter) -+ -+ -- this function will be called for every packet -+ function tap.packet(pinfo,tvb,tapdata) -+ return td:packet(pinfo, tvb, tapdata) -+ end -+ -+ -- this function will be called once every few seconds to redraw the window -+ function tap.draw() -+ local text = td:draw() -+ debug(name .. " results:\n" .. text) -+ end -+ -+ -- this function will be called at the end of the capture run. -+ function tap.reset() -+ return td:reset() -+ end -+end -+ -+return function (name, create) -+ if gui_enabled() then -+ -- menu callback. -+ local create_tap = function() -+ create_window_tap(name, create) -+ end -+ -- register menu item if running from wireshark -+ register_menu(name, create_tap, MENU_TOOLS_UNSORTED) -+ else -+ -- we are running from tshark, create a non-gui tap now. -+ create_tshark_tap(name, create) -+ end -+end -+ -diff --git a/zmq.nobj.lua b/zmq.nobj.lua -index 83c0aa5..3be6e76 100644 ---- a/zmq.nobj.lua -+++ b/zmq.nobj.lua -@@ -23,110 +23,157 @@ set_variable_format "%s%d" - - c_module "zmq" { - -- module settings. -+module_globals = true, -- support old code that doesn't do: local zmq = require"zmq" - use_globals = false, - hide_meta_info = true, - luajit_ffi = true, -- --sys_include "string.h", --include "zmq.h", -+-- needed for functions exported from module. -+luajit_ffi_load_cmodule = true, - - ffi_load { - "zmq", -- default lib name. - Windows = "libzmq", -- lib name for on windows. - }, - --c_source[[ --/* -- * This wrapper function is to make the EAGAIN/ETERM error messages more like -- * what is returned by LuaSocket. -- */ --static const char *get_zmq_strerror() { -- int err = zmq_errno(); -- switch(err) { -- case EAGAIN: -- return "timeout"; -- break; --#if defined(ETERM) -- case ETERM: -- return "closed"; -- break; -+sys_include "string.h", -+include "zmq.h", -+ -+c_source "typedefs" [[ -+/* detect zmq version */ -+#define VERSION_2_0 1 -+#define VERSION_2_1 0 -+#define VERSION_2_2 0 -+#define VERSION_3_0 0 -+#if defined(ZMQ_VERSION_MAJOR) -+# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 2) -+# undef VERSION_2_2 -+# define VERSION_2_2 1 -+# undef VERSION_2_1 -+# define VERSION_2_1 1 -+# endif -+# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 1) -+# undef VERSION_2_1 -+# define VERSION_2_1 1 -+# endif -+# if (ZMQ_VERSION_MAJOR == 3) -+# undef VERSION_2_0 -+# define VERSION_2_0 0 -+# undef VERSION_3_0 -+# define VERSION_3_0 1 -+# endif - #endif -- default: -- break; -- } -- return zmq_strerror(err); --} - --]], -+/* make sure ZMQ_DONTWAIT & ZMQ_NOBLOCK are both defined. */ -+#ifndef ZMQ_DONTWAIT -+# define ZMQ_DONTWAIT ZMQ_NOBLOCK -+#endif -+#ifndef ZMQ_NOBLOCK -+# define ZMQ_NOBLOCK ZMQ_DONTWAIT -+#endif - ---- export helper function 'get_zmq_strerror' to FFI code. --ffi_export_function "const char *" "get_zmq_strerror" "()", --ffi_source[[ --local C_get_zmq_strerror = get_zmq_strerror ---- make nicer wrapper for exported error function. --local function get_zmq_strerror() -- return ffi.string(C_get_zmq_strerror()) --end -+/* make sure DEALER/ROUTER & XREQ/XREP are all defined. */ -+#ifndef ZMQ_DEALER -+# define ZMQ_DEALER ZMQ_XREQ -+#endif -+#ifndef ZMQ_ROUTER -+# define ZMQ_ROUTER ZMQ_XREP -+#endif -+#ifndef ZMQ_XREQ -+# define ZMQ_XREQ ZMQ_DEALER -+#endif -+#ifndef ZMQ_XREP -+# define ZMQ_XREP ZMQ_ROUTER -+#endif -+ -+#if VERSION_2_0 -+# define ZMQ_POLL_MSEC 1000 // zmq_poll is usec -+#elif VERSION_3_0 -+# define ZMQ_POLL_MSEC 1 // zmq_poll is msec -+# ifndef ZMQ_HWM -+# define ZMQ_HWM 1 // backwards compatibility -+# endif -+#endif - ]], - - -- - -- Module constants - -- --constants { --MAX_VSM_SIZE = 30, -+export_definitions { -+MAX_VSM_SIZE = "ZMQ_MAX_VSM_SIZE", - - -- message types --DELIMITER = 31, --VSM = 32, -+DELIMITER = "ZMQ_DELIMITER", -+VSM = "ZMQ_VSM", - - -- message flags --MSG_MORE = 1, --MSG_SHARED = 128, -+MSG_MORE = "ZMQ_MSG_MORE", -+MSG_SHARED = "ZMQ_MSG_SHARED", - - -- socket types --PAIR = 0, --PUB = 1, --SUB = 2, --REQ = 3, --REP = 4, --XREQ = 5, --XREP = 6, --PULL = 7, --PUSH = 8, -+PAIR = "ZMQ_PAIR", -+PUB = "ZMQ_PUB", -+SUB = "ZMQ_SUB", -+REQ = "ZMQ_REQ", -+REP = "ZMQ_REP", -+PULL = "ZMQ_PULL", -+PUSH = "ZMQ_PUSH", -+ -+DEALER = "ZMQ_DEALER", -+ROUTER = "ZMQ_ROUTER", -+XREQ = "ZMQ_XREQ", -+XREP = "ZMQ_XREP", -+ -+-- new 3.1 socket types -+XPUB = "ZMQ_XPUB", -+XSUB = "ZMQ_XSUB", - - -- socket options --HWM = 1, --SWAP = 3, --AFFINITY = 4, --IDENTITY = 5, --SUBSCRIBE = 6, --UNSUBSCRIBE = 7, --RATE = 8, --RECOVERY_IVL = 9, --MCAST_LOOP = 10, --SNDBUF = 11, --RCVBUF = 12, --RCVMORE = 13, --FD = 14, --EVENTS = 15, --TYPE = 16, --LINGER = 17, --RECONNECT_IVL = 18, --BACKLOG = 19, -+HWM = "ZMQ_HWM", -+SWAP = "ZMQ_SWAP", -+AFFINITY = "ZMQ_AFFINITY", -+IDENTITY = "ZMQ_IDENTITY", -+SUBSCRIBE = "ZMQ_SUBSCRIBE", -+UNSUBSCRIBE = "ZMQ_UNSUBSCRIBE", -+RATE = "ZMQ_RATE", -+RECOVERY_IVL = "ZMQ_RECOVERY_IVL", -+MCAST_LOOP = "ZMQ_MCAST_LOOP", -+SNDBUF = "ZMQ_SNDBUF", -+RCVBUF = "ZMQ_RCVBUF", -+RCVMORE = "ZMQ_RCVMORE", -+FD = "ZMQ_FD", -+EVENTS = "ZMQ_EVENTS", -+TYPE = "ZMQ_TYPE", -+LINGER = "ZMQ_LINGER", -+RECONNECT_IVL = "ZMQ_RECONNECT_IVL", -+RECONNECT_IVL_MSEC= "ZMQ_RECONNECT_IVL_MSEC", -+BACKLOG = "ZMQ_BACKLOG", -+RECONNECT_IVL_MAX = "ZMQ_RECONNECT_IVL_MAX", -+MAXMSGSIZE = "ZMQ_MAXMSGSIZE", -+SNDHWM = "ZMQ_SNDHWM", -+RCVHWM = "ZMQ_RCVHWM", -+MULTICAST_HOPS = "ZMQ_MULTICAST_HOPS", -+RCVTIMEO = "ZMQ_RCVTIMEO", -+SNDTIMEO = "ZMQ_SNDTIMEO", -+RCVLABEL = "ZMQ_RCVLABEL", - - -- send/recv flags --NOBLOCK = 1, --SNDMORE = 2, -+NOBLOCK = "ZMQ_NOBLOCK", -+DONTWAIT = "ZMQ_DONTWAIT", -+SNDMORE = "ZMQ_SNDMORE", -+SNDLABEL = "ZMQ_SNDLABEL", - - -- poll events --POLLIN = 1, --POLLOUT = 2, --POLLERR = 4, -+POLLIN = "ZMQ_POLLIN", -+POLLOUT = "ZMQ_POLLOUT", -+POLLERR = "ZMQ_POLLERR", -+ -+-- poll milliseconds. -+POLL_MSEC = "ZMQ_POLL_MSEC", - - -- devices --STREAMER = 1, --FORWARDER = 2, --QUEUE = 3, -+STREAMER = "ZMQ_STREAMER", -+FORWARDER = "ZMQ_FORWARDER", -+QUEUE = "ZMQ_QUEUE", - }, - - -@@ -159,6 +206,7 @@ c_function "version" { - ]], - }, - c_function "init" { -+ var_in{ "int", "io_threads?", default = "1" }, - c_call "!ZMQ_Ctx *" "zmq_init" { "int", "io_threads" }, - }, - c_function "init_ctx" { -@@ -174,15 +222,15 @@ c_function "init_ctx" { - ffi_source[[ - local p_type = type(${ptr}) - if p_type == 'userdata' then -- ${ctx} = ffi.cast('void *', ${ptr}); -- elseif p_type == 'cdata' then -- ${ctx} = ${ptr}; -+ ${ctx} = ffi.cast('ZMQ_Ctx *', ${ptr}); -+ elseif p_type == 'cdata' and ffi.istype('void *', ${ptr}) then -+ ${ctx} = ffi.cast('ZMQ_Ctx *', ${ptr}); - else - return error("expected lightuserdata/cdata"); - end - ]], - }, --c_function "device" { -+c_function "device" { if_defs = "VERSION_2_0", - c_call "ZMQ_Error" "zmq_device" - { "int", "device", "ZMQ_Socket *", "insock", "ZMQ_Socket *", "outsock" }, - }, -@@ -197,16 +245,5 @@ c_function "stopwatch_start" { - c_function "sleep" { - c_call "void" "zmq_sleep" { "int", "seconds_" }, - }, ---- ---- This dump function is for getting a copy of the FFI-based bindings code and is ---- only for debugging. ---- --c_function "dump_ffi" { -- var_out{ "const char *", "ffi_code", has_length = true, }, -- c_source[[ -- ${ffi_code} = ${module_c_name}_ffi_lua_code; -- ${ffi_code_len} = sizeof(${module_c_name}_ffi_lua_code) - 1; --]], --}, - } - diff --git a/main/lua-zmq/git-20130709.patch b/main/lua-zmq/git-20130709.patch new file mode 100644 index 000000000..fce538bc4 --- /dev/null +++ b/main/lua-zmq/git-20130709.patch @@ -0,0 +1,14529 @@ +diff --git a/.travis.yml b/.travis.yml +new file mode 100644 +index 0000000..9a579b2 +--- /dev/null ++++ b/.travis.yml +@@ -0,0 +1,68 @@ ++language: c ++ ++env: ++ matrix: ++ - LUA=lua5.1 LIBLUA=liblua5.1-dev LUA_INCDIR=/usr/include/lua5.1 LUA_LIB=lua5.1 ++ - LUA=lua5.2 LIBLUA=liblua5.2-dev LUA_INCDIR=/usr/include/lua5.2 LUA_LIB=lua5.2 ++ - LUA=luajit LIBLUA=libluajit-5.1-dev LUA_INCDIR=/usr/include/luajit-2.0 LUA_LIB=luajit-5.1 ++ ++branches: ++ only: ++ - master ++ ++compiler: ++ - gcc ++ ++before_install: ++ - if [ $LUA = "luajit" ]; then ++ sudo add-apt-repository ppa:mwild1/ppa -y && sudo apt-get update -y; ++ fi ++ ++install: ++ - sudo apt-get install libzmq3-dev -y ++ - sudo apt-get install $LUA -y ++ - sudo apt-get install $LIBLUA -y ++ - LUA_LIBDIR=`pkg-config $LUA --variable=libdir` ++ - INSTALL_LMOD=`pkg-config $LUA --variable=INSTALL_LMOD` ++ - INSTALL_CMOD=`pkg-config $LUA --variable=INSTALL_CMOD` ++ ## make sure there is a 'lua' command. ++ - if [ ! -x /usr/bin/lua ]; then ++ sudo ln -s `which $LUA` /usr/bin/lua; ++ fi ++ ## install lua-llthreads ++ - git clone git://github.com/Neopallium/lua-llthreads.git ++ - cd lua-llthreads ; mkdir build ; cd build ++ - cmake .. -DLUA_LIBRARIES=$LUA_LIBDIR -DLUA_INCLUDE_DIR=$LUA_INCDIR ++ -DINSTALL_LMOD=$INSTALL_LMOD -DINSTALL_CMOD=$INSTALL_CMOD ++ - make ++ - sudo make install ++ - cd ../.. ++ ++script: ++ #### build using pre-generated bindings. ++ - mkdir build; cd build ++ - cmake .. -DLUA_LIBRARIES=$LUA_LIBDIR -DLUA_INCLUDE_DIR=$LUA_INCDIR ++ -DINSTALL_LMOD=$INSTALL_LMOD -DINSTALL_CMOD=$INSTALL_CMOD ++ - make ++ - sudo make install ++ # Run tests. ++ - $LUA ../tests/test_inproc.lua ++ - $LUA ../perf/thread_lat.lua 1 1000 ++ - cd .. ; rm -rf build ++ #### Re-Generate bindings. ++ - git clone git://github.com/Neopallium/LuaNativeObjects.git; ++ - mkdir build; cd build ++ - cmake .. -DLUA_LIBRARIES=$LUA_LIBDIR -DLUA_INCLUDE_DIR=$LUA_INCDIR ++ -DLUA_NATIVE_OBJECTS_PATH=$TRAVIS_BUILD_DIR/LuaNativeObjects ++ -DUSE_PRE_GENERATED_BINDINGS=OFF -DGENERATE_LUADOCS=OFF ++ -DINSTALL_LMOD=$INSTALL_LMOD -DINSTALL_CMOD=$INSTALL_CMOD ++ - make ++ - sudo make install ++ # Run tests. ++ - $LUA ../tests/test_inproc.lua ++ - $LUA ../perf/thread_lat.lua 1 1000 ++ ++notifications: ++ email: ++ on_failure: always ++ on_success: change +diff --git a/API.md b/API.md +index f15da79..9cdcb8e 100644 +--- a/API.md ++++ b/API.md +@@ -147,6 +147,14 @@ See [zmq_msg_copy(3)](http://api.zeromq.org/zmq_msg_copy.html). + + msg1:copy(msg2) -- copy contents from msg2 -> msg1 + ++## set_size(size) ++ ++Re-initialize the message with a new size. The current contents will be lost. ++See [zmq_msg_init_size(3)](http://api.zeromq.org/zmq_msg_init_size.html). ++ ++ msg:set_size(size) -- re-initialize message if size is different from current size. ++ local buf = msg:data() -- get buffer to fill message with new contents. ++ + ## set_data(data) + + Change the message contents. +@@ -156,7 +164,7 @@ See [zmq_msg_data(3)](http://api.zeromq.org/zmq_msg_data.html). + + ## data() + +-Get the message contents. ++Get a lightuserdata pointer to the message contents. + See [zmq_msg_data(3)](http://api.zeromq.org/zmq_msg_data.html). + + local data = msg:data() -- get the message contents +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 6c3ed78..6471a17 100755 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -9,12 +9,10 @@ set(BUILD_SHARED_LIBS TRUE) + + set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +-set(INSTALL_LMOD share/lua/5.1 CACHE PATH "Directory to install Lua source modules (configure lua via LUA_PATH)") +-set(INSTALL_CMOD lib/lua/5.1 CACHE PATH "Directory to install Lua binary modules (configure lua via LUA_CPATH)") +-set(LUA_NATIVE_OBJECTS_PATH ../LuaNativeObjects CACHE PATH +- "Directory to LuaNativeObjects bindings generator.") +-set(USE_PRE_GENERATED_BINDINGS TRUE CACHE BOOL +- "Set this to FALSE to re-generate bindings using LuaNativeObjects") ++set(INSTALL_LMOD ${CMAKE_INSTALL_PREFIX}/share/lua/5.1 CACHE PATH ++ "Directory to install Lua source modules (configure lua via LUA_PATH)") ++set(INSTALL_CMOD ${CMAKE_INSTALL_PREFIX}/lib/lua/5.1 CACHE PATH ++ "Directory to install Lua binary modules (configure lua via LUA_CPATH)") + set(ZMQ_PATH "" CACHE PATH + "Directory to libzmq. (by default use pkg-config to detect path)") + +@@ -27,6 +25,17 @@ include(FindLua51) + if(NOT ${LUA51_FOUND}) + message(FATAL_ERROR "The FindLua51 module could not find lua :-(") + endif() ++if(WIN32) ++ set(COMMON_CFLAGS "${COMMON_CFLAGS} -I${LUA_INCLUDE_DIR}") ++ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} ${LUA_LIBRARY}") ++ if(NOT MSVC) ++ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -Wl,--export-all-symbols") ++ endif() ++endif() ++## MAC OSX needs extra linker flags ++if(APPLE) ++ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -undefined dynamic_lookup") ++endif() + + ## LibZMQ + if(WIN32) +@@ -38,8 +47,13 @@ if(WIN32) + endif() + if(IS_DIRECTORY ${ZMQ_PATH}) + set(COMMON_CFLAGS "${COMMON_CFLAGS} -I${ZMQ_PATH}/include") +- set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -L${ZMQ_PATH}/lib") +- set(COMMON_LIBS "${COMMON_LIBS};zmq") ++ if(MSVC) ++ set(COMMON_LIBS "${COMMON_LIBS};libzmq") ++ else() ++ set(COMMON_LDFLAGS "${COMMON_LDFLAGS} -L${ZMQ_PATH}/lib") ++ set(COMMON_LIBS "${COMMON_LIBS};zmq") ++ endif() ++ link_directories(${ZMQ_PATH}/lib) + else() + ## fallback to using pkg-config + include(FindPkgConfig) +@@ -51,13 +65,12 @@ endif() + + ## LuaNativeObjects + include(LuaNativeObjects) ++include(CustomMacros) + + include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${LUA_INCLUDE_DIR}) + +-link_directories(${ZMQ_LIBRARY_DIRS}) +- + ## LuaZMQ + set(LUA_ZMQ_SRC + zmq.nobj.lua +@@ -79,8 +92,8 @@ endif() + add_library(lua-zmq MODULE ${LUA_ZMQ_SRC}) + target_link_libraries(lua-zmq ${COMMON_LIBS}) + set_target_properties(lua-zmq PROPERTIES PREFIX "") +-set_target_properties(lua-zmq PROPERTIES COMPILE_FLAGS "${COMMON_CFLAGS}") +-set_target_properties(lua-zmq PROPERTIES LINK_FLAGS "${COMMON_LDFLAGS}") ++add_target_properties(lua-zmq COMPILE_FLAGS "${COMMON_CFLAGS}") ++add_target_properties(lua-zmq LINK_FLAGS "${LD_FLAGS} ${COMMON_LDFLAGS}") + set_target_properties(lua-zmq PROPERTIES OUTPUT_NAME zmq) + + install(TARGETS lua-zmq +diff --git a/COPYRIGHT b/COPYRIGHT +new file mode 100644 +index 0000000..9840d93 +--- /dev/null ++++ b/COPYRIGHT +@@ -0,0 +1,19 @@ ++Copyright (c) 2011 by Robert G. Jakabosky ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy ++of this software and associated documentation files (the "Software"), to deal ++in the Software without restriction, including without limitation the rights ++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++copies of the Software, and to permit persons to whom the Software is ++furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in ++all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++THE SOFTWARE. +diff --git a/README.md b/README.md +index eac5f5f..0b3b15d 100644 +--- a/README.md ++++ b/README.md +@@ -1,8 +1,15 @@ + About + ===== + ++[![travis-ci status](https://secure.travis-ci.org/Neopallium/lua-zmq.png?branch=master)](http://travis-ci.org/Neopallium/lua-zmq/builds) ++ + Lua bindings to zeromq2. Check out the [ZeroMQ Guide with Lua examples](http://zguide.zeromq.org/lua:all). + ++Windows ++======= ++ ++Download a compiled version of [LuaJIT 2.0.0-beta11 + lua-zmq + zeromq2.2.0](https://github.com/downloads/Neopallium/lua-zmq/luajit2.0_beta11_zmq2.2_llthreads.zip) 32bit & 64bit. ++ + API + === + +@@ -12,7 +19,7 @@ See [API.md](https://github.com/Neopallium/lua-zmq/blob/master/API.md) and + Requirements + ============ + +-* ZeroMQ version 2.1.x. ++* ZeroMQ version 2.1, 2.2 or 3.2. + * Might work with some 2.0.x versions (2.0.6 and lower are not supported). + + For Ubuntu 10.10 users: +@@ -22,7 +29,7 @@ For Ubuntu 10.10 users: + Installation + ============ + +-It is recommended to either compile Lua with the "-pthread" flag or preload libpthread.so on Linux when using this module ([See this glibc bug report](http://sourceware.org/bugzilla/show_bug.cgi?id=10652): ++It is recommended to either compile Lua with the "-pthread" flag or preload libpthread.so on Linux when using this module ([see this glibc bug report](http://sourceware.org/bugzilla/show_bug.cgi?id=10652)): + + $ LD_PRELOAD=/lib/libpthread.so lua + +@@ -45,12 +52,12 @@ Latest Git revision + + With LuaRocks 2.0.4.1: + +- $ sudo luarocks install https://github.com/Neopallium/lua-zmq/raw/master/rockspecs/lua-zmq-scm-1.rockspec ++ $ sudo luarocks install https://raw.github.com/Neopallium/lua-zmq/master/rockspecs/lua-zmq-scm-1.rockspec + + For threads support: + +- $ sudo luarocks install https://github.com/Neopallium/lua-llthreads/raw/master/rockspecs/lua-llthreads-scm-0.rockspec +- $ sudo luarocks install https://github.com/Neopallium/lua-zmq/raw/master/rockspecs/lua-zmq-threads-scm-0.rockspec ++ $ sudo luarocks install https://raw.github.com/Neopallium/lua-llthreads/master/rockspecs/lua-llthreads-scm-0.rockspec ++ $ sudo luarocks install https://raw.github.com/Neopallium/lua-zmq/master/rockspecs/lua-zmq-threads-scm-0.rockspec + + With CMake: + +diff --git a/README.regenerate.md b/README.regenerate.md +new file mode 100644 +index 0000000..e3b288e +--- /dev/null ++++ b/README.regenerate.md +@@ -0,0 +1,13 @@ ++To re-generating the bindings ++----------------------------- ++ ++You will need to install LuaNativeObjects and set the CMake variable `USE_PRE_GENERATED_BINDINGS` to FALSE. ++By default CMake will use the pre-generated bindings that are include in the project. ++ ++Build Dependencies ++------------------ ++ ++Optional dependency for re-generating Lua bindings from `*.nobj.lua` files: ++ ++* [LuaNativeObjects](https://github.com/Neopallium/LuaNativeObjects), this is the bindings generator used to convert the `*.nobj.lua` files into a native Lua module. ++ +diff --git a/cmake/CustomMacros.cmake b/cmake/CustomMacros.cmake +new file mode 100644 +index 0000000..312eeff +--- /dev/null ++++ b/cmake/CustomMacros.cmake +@@ -0,0 +1,61 @@ ++## Orignal Macros copied from lighttpd 2.0 ++ ++## modules are without the "lib" prefix ++ ++macro(setup_static_modules TARGET) ++ file(WRITE ${TARGET}_builtins.h "/* auto-generated by CMake build do not edit */\n\n") ++endmacro(setup_static_modules) ++ ++macro(add_module TARGET MODNAME) ++ set(_static_mod ${BUILD_STATIC}) ++ ++ ## create list of module source files. ++ set(_srcfiles) ++ set(_def_module_src ${CMAKE_CURRENT_SOURCE_DIR}/modules/${MODNAME}.c) ++ if(EXISTS ${_def_module_src}) ++ set(_srcfiles ${_def_module_src}) ++ endif(EXISTS ${_def_module_src}) ++ foreach(_srcfile ${ARGN}) ++ if(_srcfile STREQUAL "STATIC") ++ set(_static_mod TRUE) ++ else(_srcfile STREQUAL "STATIC") ++ set(_srcfiles ${_srcfiles} ${_srcfile}) ++ endif(_srcfile STREQUAL "STATIC") ++ endforeach(_srcfile) ++ ++ if(_static_mod) ++ set(STATIC_MODULE_SRC ${STATIC_MODULE_SRC} ${_srcfiles}) ++ file(APPEND ${TARGET}_builtins.h "STATIC_MOD(${MODNAME})\n") ++ else(_static_mod) ++ add_library(${MODNAME} MODULE ${_srcfiles}) ++ set(MODULE_TARGETS ${MODULE_TARGETS} ${MODNAME}) ++ ++ add_target_properties(${MODNAME} LINK_FLAGS ${COMMON_LDFLAGS}) ++ add_target_properties(${MODNAME} COMPILE_FLAGS ${COMMON_CFLAGS}) ++ set_target_properties(${MODNAME} PROPERTIES CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) ++ ++ ## Windows likes to link it this way back to app! ++ if(WIN32) ++ set_target_properties(${MODNAME} PROPERTIES LINK_FLAGS ${TARGET}.lib) ++ endif(WIN32) ++ ++ if(APPLE) ++ set_target_properties(${MODNAME} PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress") ++ endif(APPLE) ++ endif(_static_mod) ++endmacro(add_module) ++ ++macro(add_target_properties _target _name) ++ set(_properties) ++ foreach(_prop ${ARGN}) ++ set(_properties "${_properties} ${_prop}") ++ endforeach(_prop) ++ get_target_property(_old_properties ${_target} ${_name}) ++ ##message(STATUS "adding property to ${_target} ${_name}:" ${_properties}) ++ if(NOT _old_properties) ++ # in case it's NOTFOUND ++ set(_old_properties) ++ endif(NOT _old_properties) ++ set_target_properties(${_target} PROPERTIES ${_name} "${_old_properties} ${_properties}") ++endmacro(add_target_properties) ++ +diff --git a/cmake/LuaNativeObjects.cmake b/cmake/LuaNativeObjects.cmake +index a1b0e2d..e9e47de 100644 +--- a/cmake/LuaNativeObjects.cmake ++++ b/cmake/LuaNativeObjects.cmake +@@ -1,19 +1,39 @@ + # + # Lua Native Objects + # ++ ++set(LUA_NATIVE_OBJECTS_PATH ${CMAKE_SOURCE_DIR}/../LuaNativeObjects CACHE PATH ++ "Directory to LuaNativeObjects bindings generator.") ++set(USE_PRE_GENERATED_BINDINGS TRUE CACHE BOOL ++ "Set this to FALSE to re-generate bindings using LuaNativeObjects") ++ ++set(GENERATE_LUADOCS TRUE CACHE BOOL ++ "Set this to FALSE to avoid generation of docs using LuaDoc") ++ + macro(GenLuaNativeObjects _src_files_var) + set(_new_src_files) + foreach(_src_file ${${_src_files_var}}) + if(_src_file MATCHES ".nobj.lua") + string(REGEX REPLACE ".nobj.lua" ".nobj.c" _src_file_out ${_src_file}) +- string(REGEX REPLACE ".nobj.lua" ".nobj.h" _header_file_out ${_src_file}) +- add_custom_command(OUTPUT ${_src_file_out} ${_header_file_out} ++ string(REGEX REPLACE ".nobj.lua" ".nobj.ffi.lua" _ffi_file_out ${_src_file}) ++ add_custom_command(OUTPUT ${_src_file_out} ${_ffi_file_out} + COMMAND lua ${LUA_NATIVE_OBJECTS_PATH}/native_objects.lua -outpath ${CMAKE_CURRENT_BINARY_DIR} -gen lua ${_src_file} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${_src_file} + ) + set_source_files_properties(${_src_file_out} PROPERTIES GENERATED TRUE) +- set_source_files_properties(${_header_file_out} PROPERTIES GENERATED TRUE) ++ set_source_files_properties(${_ffi_file_out} PROPERTIES GENERATED TRUE) ++ if (${GENERATE_LUADOCS}) ++ string(REGEX REPLACE ".nobj.lua" "" _doc_base ${_src_file}) ++ string(REGEX REPLACE ".nobj.lua" ".luadoc" _doc_file_out ${_src_file}) ++ add_custom_target(${_doc_file_out} ALL ++ COMMAND lua ${LUA_NATIVE_OBJECTS_PATH}/native_objects.lua -outpath docs -gen luadoc ${_src_file} ++ COMMAND luadoc -nofiles -d docs docs ++ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ++ DEPENDS ${_src_file} ++ ) ++ endif() ++ set_source_files_properties(${_doc_file_out} PROPERTIES GENERATED TRUE) + set(_new_src_files ${_new_src_files} ${_src_file_out}) + else(_src_file MATCHES ".nobj.lua") + set(_new_src_files ${_new_src_files} ${_src_file}) +diff --git a/examples/client.lua b/examples/client.lua +index 682a549..5e9849c 100644 +--- a/examples/client.lua ++++ b/examples/client.lua +@@ -18,15 +18,24 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + +-require("zmq") ++local zmq = require"zmq" + +-local ctx = zmq.init(1) ++local N=tonumber(arg[1] or 100) ++ ++local ctx = zmq.init() + local s = ctx:socket(zmq.REQ) + + s:connect("tcp://localhost:5555") + +-s:send("SELECT * FROM mytable") +-print(s:recv()) ++for i=1,N do ++ s:send("SELECT * FROM mytable") ++ local data, err = s:recv() ++ if data then ++ print(data) ++ else ++ print("s:recv() error:", err) ++ end ++end + + s:close() + ctx:term() +diff --git a/examples/client_multipart.lua b/examples/client_multipart.lua +index e82ca26..4f10c58 100644 +--- a/examples/client_multipart.lua ++++ b/examples/client_multipart.lua +@@ -18,17 +18,26 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + +-require("zmq") ++local zmq = require"zmq" + +-local ctx = zmq.init(1) ++local N=tonumber(arg[1] or 100) ++ ++local ctx = zmq.init() + local s = ctx:socket(zmq.REQ) + + s:connect("tcp://localhost:5555") + +-s:send("SELECT * FROM mytable ", zmq.SNDMORE) +-s:send("WHERE library = 'zmq'") ++for i=1,N do ++ s:send("SELECT * FROM mytable ", zmq.SNDMORE) ++ s:send("WHERE library = 'zmq'") + +-print(s:recv()) ++ local data, err = s:recv() ++ if data then ++ print(data) ++ else ++ print("s:recv() error:", err) ++ end ++end + + s:close() + ctx:term() +diff --git a/examples/client_poll.lua b/examples/client_poll.lua +new file mode 100644 +index 0000000..c49af9b +--- /dev/null ++++ b/examples/client_poll.lua +@@ -0,0 +1,108 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local poller = require"examples.poller" ++local poll = poller.new() ++ ++local zmq = require"zmq" ++local z_NOBLOCK = zmq.NOBLOCK ++local z_EVENTS = zmq.EVENTS ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++ ++local N=tonumber(arg[1] or 100) ++ ++local ctx = zmq.init() ++local s = ctx:socket(zmq.REQ) ++local s_FD = s:getopt(zmq.FD) ++ ++s:connect("tcp://localhost:5555") ++ ++-- current socket state ++local blocked_state ++local blocked_event ++local on_sock_recv ++local on_sock_send ++ ++-- IO event callback when socket was blocked ++local function on_sock_io() ++ local events = s:getopt(z_EVENTS) ++ local unblocked = false ++ if events == blocked_event then ++ -- got the event the socket was blocked on. ++ unblocked = true ++ elseif events == z_POLLIN_OUT then ++ -- got both in & out events ++ unblocked = true ++ end ++ if unblocked then ++ -- got the event we are blocked on resume. ++ blocked_event = nil ++ blocked_state() ++ -- check if blocked event was processed. ++ if not blocked_event then ++ poll:remove_read(s_FD) ++ end ++ end ++end ++local function sock_blocked(state, event) ++ if not blocked_event then ++ -- need to register socket's fd with event loop ++ poll:add_read(s_FD, on_sock_io) ++ end ++ blocked_state = state ++ blocked_event = event ++end ++ ++-- sock state functions ++function on_sock_send() ++ N = N - 1 ++ if N == 0 then ++ return poll:stop() ++ end ++ local sent, err = s:send("SELECT * FROM mytable", z_NOBLOCK) ++ if not sent then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_send, z_POLLOUT) ++ end ++ -- yield back to event loop ++ poll:add_work(on_sock_recv) ++end ++ ++function on_sock_recv() ++ local data, err = s:recv(z_NOBLOCK) ++ if not data then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_recv, z_POLLIN) ++ end ++ print(data) ++ return on_sock_send() ++end ++ ++-- start processing of the socket. ++poll:add_work(on_sock_send) ++ ++-- start event loop ++poll:start() ++ ++s:close() ++ctx:term() ++ +diff --git a/examples/ev_subscriber.lua b/examples/ev_subscriber.lua +deleted file mode 100644 +index 876a0ea..0000000 +--- a/examples/ev_subscriber.lua ++++ /dev/null +@@ -1,92 +0,0 @@ +--- Copyright (c) 2010 Aleksey Yeschenko +--- +--- Permission is hereby granted, free of charge, to any person obtaining a copy +--- of this software and associated documentation files (the "Software"), to deal +--- in the Software without restriction, including without limitation the rights +--- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +--- copies of the Software, and to permit persons to whom the Software is +--- furnished to do so, subject to the following conditions: +--- +--- The above copyright notice and this permission notice shall be included in +--- all copies or substantial portions of the Software. +--- +--- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +--- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +--- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +--- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +--- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +--- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +--- THE SOFTWARE. +- +-require("zmq") +-local ev = require'ev' +-local loop = ev.Loop.default +- +--- define a sub_worker class +-local sub_worker_mt = {} +-function sub_worker_mt:close(...) +- self.s_io_idle:stop(self.loop) +- self.s_io_read:stop(self.loop) +- return self.socket:close(...) +-end +-function sub_worker_mt:bind(...) +- return self.socket:bind(...) +-end +-function sub_worker_mt:connect(...) +- return self.socket:connect(...) +-end +-function sub_worker_mt:sub(topic) +- return self.socket:setopt(zmq.SUBSCRIBE, topic) +-end +-function sub_worker_mt:unsub(topic) +- return self.socket:setopt(zmq.UNSUBSCRIBE, topic) +-end +-sub_worker_mt.__index = sub_worker_mt +- +-local function sub_worker(loop, ctx, msg_cb) +- local s = ctx:socket(zmq.SUB) +- local self = { loop = loop, socket = s, msg_cb = msg_cb } +- setmetatable(self, sub_worker_mt) +- -- create ev callbacks for recving data. +- -- need idle watcher since ZeroMQ sockets are edge-triggered instead of level-triggered +- local s_io_idle +- local s_io_read +- s_io_idle = ev.Idle.new(function() +- local msg, err = s:recv(zmq.NOBLOCK) +- if err == 'timeout' then +- -- need to block on read IO +- s_io_idle:stop(loop) +- s_io_read:start(loop) +- return +- end +- self:msg_cb(msg) +- end) +- s_io_idle:start(loop) +- s_io_read = ev.IO.new(function() +- s_io_idle:start(loop) +- s_io_read:stop(loop) +- end, s:getopt(zmq.FD), ev.READ) +- self.s_io_idle = s_io_idle +- self.s_io_read = s_io_read +- return self +-end +- +-local ctx = zmq.init(1) +- +--- message handling function. +-local function handle_msg(worker, msg) +- local msg_id = tonumber(msg) +- if math.mod(msg_id, 10000) == 0 then print(worker.id, msg_id) end +-end +- +-local sub1 = sub_worker(loop, ctx, handle_msg) +-sub1.id = 'sub1' +-sub1:sub('') +-sub1:connect("tcp://localhost:5555") +-local sub2 = sub_worker(loop, ctx, handle_msg) +-sub2.id = 'sub2' +-sub2:sub('') +-sub2:connect("tcp://localhost:5555") +- +-loop:loop() +- +diff --git a/examples/forward_poll.lua b/examples/forward_poll.lua +new file mode 100644 +index 0000000..25e1e4f +--- /dev/null ++++ b/examples/forward_poll.lua +@@ -0,0 +1,39 @@ ++local zmq = require'zmq' ++local poller = require"examples.poller" ++local poll_zsock = require"examples.poll_zsock" ++ ++local poll = poller.new() ++poll_zsock.set_poller(poll) ++ ++local c = zmq.init(1) ++local xreq = poll_zsock(c:socket(zmq.XREQ)) ++xreq:bind('tcp://127.0.0.1:13333') ++local xrep = poll_zsock(c:socket(zmq.XREP)) ++xrep:bind('tcp://127.0.0.1:13334') ++ ++local max_recv = 10 ++ ++local function forward_io(src,dst) ++ src.on_data = function() ++ for i=1,max_recv do ++ repeat ++ local data, err = src:recv(zmq.NOBLOCK) ++ if not data then ++ if err == 'timeout' then ++ return ++ else ++ error("socket recv error:" .. err) ++ end ++ end ++ local more = src:getopt(zmq.RCVMORE) > 0 ++ dst:send(data,more and zmq.SNDMORE or 0) ++ until not more ++ end ++ end ++end ++ ++forward_io(xrep,xreq) ++forward_io(xreq,xrep) ++ ++poll:start() ++ +diff --git a/examples/poll_zsock.lua b/examples/poll_zsock.lua +new file mode 100644 +index 0000000..5d2ca04 +--- /dev/null ++++ b/examples/poll_zsock.lua +@@ -0,0 +1,177 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local zmq = require"zmq" ++ ++local z_EVENTS = zmq.EVENTS ++ ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++ ++local poll ++ ++local meths = {} ++local zsock_mt = { __index=meths } ++ ++local function zsock_check_events(self) ++ if not self.check_enabled then ++ -- enable 'on_work' callback to handle checking for socket events. ++ self.check_enabled = true ++ poll:add_work(self.on_work) ++ end ++end ++ ++function meths:events() ++ zsock_check_events(self) ++ return self.sock:events() ++end ++ ++function meths:getopt(opt) ++ if (opt == z_EVENTS) then ++ zsock_check_events(self) ++ end ++ return self.sock:getopt(opt) ++end ++ ++function meths:setopt(opt,val) ++ return self.sock:setopt(opt,val) ++end ++ ++function meths:sub(topic) ++ return self.sock:sub(topic) ++end ++ ++function meths:unsub(topic) ++ return self.sock:unsub(topic) ++end ++ ++function meths:identity(id) ++ return self.sock:identity(id) ++end ++ ++function meths:bind(addr) ++ return self.sock:bind(addr) ++end ++ ++function meths:connect(addr) ++ return self.sock:connect(addr) ++end ++ ++function meths:close() ++ return self.sock:close() ++end ++ ++function meths:send(msg, flags) ++ zsock_check_events(self) ++ local sent, err = self.sock:send(msg, flags) ++ if not sent and err == 'timeout' then ++ self.send_blocked = true ++ end ++ return sent, err ++end ++ ++function meths:send_msg(msg, flags) ++ zsock_check_events(self) ++ local sent, err = self.sock:send_msg(msg, flags) ++ if not sent and err == 'timeout' then ++ self.send_blocked = true ++ end ++ return sent, err ++end ++ ++function meths:recv(flags) ++ zsock_check_events(self) ++ local msg, err = self.sock:recv(flags) ++ if not msg and err == 'timeout' then ++ self.recv_blocked = true ++ end ++ return msg, err ++end ++ ++function meths:recv_msg(msg, flags) ++ zsock_check_events(self) ++ local stat, err = self.sock:recv_msg(msg, flags) ++ if not stat and err == 'timeout' then ++ self.recv_blocked = true ++ end ++ return stat, err ++end ++ ++local function nil_cb() ++end ++ ++local function wrap_zsock(sock, on_data, on_drain) ++ local self = setmetatable({ ++ sock = sock, ++ on_data = on_data or nil_cb, ++ on_drain = on_drain or nil_cb, ++ recv_blocked = false, ++ send_blocked = false, ++ check_enabled = false, ++ }, zsock_mt) ++ ++ local function on_work() ++ self.check_enabled = false ++ local events = sock:events() ++ local read = false ++ local write = false ++ if events == z_POLLIN_OUT then ++ read = true ++ write = true ++ elseif events == z_POLLIN then ++ read = true ++ elseif events == z_POLLOUT then ++ write = true ++ else ++ return ++ end ++ if read then ++ self.recv_blocked = false ++ self:on_data(sock) ++ -- there might be more messages to read. ++ if not self.recv_blocked then ++ zsock_check_events(self) ++ end ++ end ++ if write and self.send_blocked then ++ self:on_drain(sock) ++ end ++ end ++ self.on_work = on_work ++ ++ -- listen for read events to enable socket. ++ poll:add_read(sock:fd(), function() ++ on_work() ++ end) ++ ++ zsock_check_events(self) ++ return self ++end ++ ++return setmetatable({ ++set_poller = function(poller) ++ local old = poll ++ poll = poller ++ return old ++end, ++wrap_zsock = wrap_zsock, ++}, { __call = function(tab, ...) return wrap_zsock(...) end}) ++ +diff --git a/examples/poller.lua b/examples/poller.lua +new file mode 100644 +index 0000000..90bee0a +--- /dev/null ++++ b/examples/poller.lua +@@ -0,0 +1,45 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++-- safe require. ++local require = require ++local function safe_require(...) ++ return pcall(require, ...) ++end ++ ++local mod_name = ... ++ ++local backends = { ++ "epoll", ++ "ev", ++} ++ ++for i=1,#backends do ++ local backend = backends[i] ++ local name = mod_name .. '.' .. backend ++ local status, mod = safe_require(name) ++ if status then ++ --print("Loaded backend:", name) ++ return mod ++ end ++end ++ ++error("Failed to load backend for: " .. mod_name) ++ +diff --git a/examples/poller/epoll.lua b/examples/poller/epoll.lua +new file mode 100644 +index 0000000..d79597c +--- /dev/null ++++ b/examples/poller/epoll.lua +@@ -0,0 +1,121 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local epoll = require"epoll" ++local EPOLLIN = epoll.EPOLLIN ++local EPOLLOUT = epoll.EPOLLOUT ++ ++local poller_meths = {} ++local poller_mt = {__index = poller_meths} ++ ++local function poller_new() ++ local reads = {} ++ -- create closure for epoll io_event callback. ++ local function do_io_event(fd, ev) ++ local cb = reads[fd] ++ return cb(fd, ev) ++ end ++ ++ return setmetatable({ ++ work_cur = {}, ++ work_last = {}, ++ reads = reads, ++ io_events = 0, ++ do_io_event = do_io_event, ++ poller = epoll.new(), ++ }, poller_mt) ++end ++ ++function poller_meths:add_work(task) ++ -- add task to current work queue. ++ self.work_cur[#self.work_cur + 1] = task ++end ++ ++function poller_meths:add_read(fd, cb) ++ -- make sure read event hasn't been registered yet. ++ if not self.reads[fd] then ++ self.io_events = self.io_events + 1 ++ self.reads[fd] = cb ++ return self.poller:add(fd, EPOLLIN, fd) ++ else ++ -- update read callback? ++ self.reads[fd] = cb ++ end ++end ++ ++function poller_meths:remove_read(fd) ++ -- make sure there was a read event registered. ++ if self.reads[fd] then ++ self.io_events = self.io_events - 1 ++ self.reads[fd] = nil ++ return self.poller:del(fd) ++ end ++end ++ ++local function poller_do_work(self) ++ local tasks = #self.work_cur ++ -- check if there is any work ++ if tasks > 0 then ++ -- swap work queues. ++ local last, cur = self.work_cur, self.work_last ++ self.work_cur, self.work_last = cur, last ++ for i=1,tasks do ++ local task = last[i] ++ last[i] = nil ++ task() ++ end ++ -- return new work queue length. ++ return #cur ++ end ++ return tasks ++end ++ ++function poller_meths:start() ++ local do_io_event = self.do_io_event ++ local poller = self.poller ++ self.is_running = true ++ while self.is_running do ++ -- run work task ++ local new_work = poller_do_work(self) ++ -- wait == 0, if there is work to do, else wait == -1 ++ local wait = (new_work > 0) and 0 or -1 ++ -- poll for fd events, if there are events to poll for. ++--print("poller:step()", new_work, self.io_events) ++ if self.io_events > 0 then ++ assert(poller:wait_callback(do_io_event, wait)) ++ else ++ -- no io events to poll, do we still have work? ++ if #self.work_cur == 0 then ++ -- nothing to do, exit event loop ++ self.is_running = false ++ return ++ end ++ end ++ end ++end ++ ++function poller_meths:stop() ++ self.is_running = false ++end ++ ++-- module only exports a 'new' function. ++return { ++new = poller_new, ++} +diff --git a/examples/poller/ev.lua b/examples/poller/ev.lua +new file mode 100644 +index 0000000..f8b1733 +--- /dev/null ++++ b/examples/poller/ev.lua +@@ -0,0 +1,119 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local ev = require'ev' ++local ev_READ = ev.READ ++local ev_WRITE = ev.WRITE ++local loop = ev.Loop.default ++ ++assert(ev.Idle,"Need version > 1.3 of lua-ev that supports Idle watchers.") ++ ++local poller_meths = {} ++local poller_mt = {__index = poller_meths} ++ ++local function poller_new() ++ local self = { ++ work_cur = {}, ++ work_last = {}, ++ io_events = 0, ++ reads = {}, ++ idle_enabled = false, ++ } ++ ++ self.idle = ev.Idle.new(function() ++ local tasks = #self.work_cur ++ -- check if there is any work ++ if tasks > 0 then ++ -- swap work queues. ++ local last, cur = self.work_cur, self.work_last ++ self.work_cur, self.work_last = cur, last ++ for i=1,tasks do ++ local task = last[i] ++ last[i] = nil ++ task() ++ end ++ -- check if there is more work. ++ if #cur > 0 then ++ return -- don't disable idle watcher, when we have work. ++ end ++ end ++--print("STOP IDLE:", #self.work_cur, #self.work_last) ++ -- stop idle watcher, no work. ++ self.idle_enabled = false ++ self.idle:stop(loop) ++ end) ++ -- set priority to max, to make sure the work queue is processed on each loop. ++ self.idle:priority(ev.MAXPRI) ++ ++ return setmetatable(self, poller_mt) ++end ++ ++function poller_meths:add_work(task) ++ local idx = #self.work_cur + 1 ++ -- add task to current work queue. ++ self.work_cur[idx] = task ++ -- make sure the idle watcher is enabled. ++ if not self.idle_enabled then ++ self.idle_enabled = true ++ self.idle:start(loop) ++ end ++end ++ ++function poller_meths:add_read(fd, cb) ++ local io_read = self.reads[fd] ++ -- make sure read event hasn't been registered yet. ++ if not io_read then ++ self.io_events = self.io_events + 1 ++ io_read = ev.IO.new(function() ++ cb(fd) ++ end, fd, ev_READ) ++ self.reads[fd] = io_read ++ io_read:start(loop) ++ else ++ -- update read callback? ++ io_read:callback(cb) ++ -- need to re-start watcher? ++ if not io_read:is_active() then ++ io_read:start(loop) ++ end ++ end ++end ++ ++function poller_meths:remove_read(fd) ++ local io_read = self.reads[fd] ++ -- make sure there was a read event registered. ++ if io_read then ++ self.io_events = self.io_events - 1 ++ io_read:stop(loop) ++ end ++end ++ ++function poller_meths:start() ++ return loop:loop() ++end ++ ++function poller_meths:stop() ++ return loop:unloop() ++end ++ ++-- module only exports a 'new' function. ++return { ++new = poller_new, ++} +diff --git a/examples/publiser.lua b/examples/publiser.lua +deleted file mode 100644 +index 12e240e..0000000 +--- a/examples/publiser.lua ++++ /dev/null +@@ -1,32 +0,0 @@ +--- Copyright (c) 2010 Aleksey Yeschenko +--- +--- Permission is hereby granted, free of charge, to any person obtaining a copy +--- of this software and associated documentation files (the "Software"), to deal +--- in the Software without restriction, including without limitation the rights +--- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +--- copies of the Software, and to permit persons to whom the Software is +--- furnished to do so, subject to the following conditions: +--- +--- The above copyright notice and this permission notice shall be included in +--- all copies or substantial portions of the Software. +--- +--- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +--- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +--- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +--- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +--- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +--- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +--- THE SOFTWARE. +- +-require("zmq") +- +-local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PUB) +- +-s:bind("tcp://lo:5555") +- +-local msg_id = 1 +-while true do +- s:send(tostring(msg_id)) +- msg_id = msg_id + 1 +-end +diff --git a/examples/publisher.lua b/examples/publisher.lua +new file mode 100644 +index 0000000..a5f943e +--- /dev/null ++++ b/examples/publisher.lua +@@ -0,0 +1,32 @@ ++-- Copyright (c) 2010 Aleksey Yeschenko ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local zmq = require"zmq" ++ ++local ctx = zmq.init() ++local s = ctx:socket(zmq.PUB) ++ ++s:bind("tcp://lo:5555") ++ ++local msg_id = 1 ++while true do ++ s:send(tostring(msg_id)) ++ msg_id = msg_id + 1 ++end +diff --git a/examples/publisher_poll.lua b/examples/publisher_poll.lua +new file mode 100644 +index 0000000..0cfbe79 +--- /dev/null ++++ b/examples/publisher_poll.lua +@@ -0,0 +1,95 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local poller = require"examples.poller" ++local poll = poller.new() ++ ++local zmq = require"zmq" ++local z_NOBLOCK = zmq.NOBLOCK ++local z_EVENTS = zmq.EVENTS ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++ ++local ctx = zmq.init() ++local s = ctx:socket(zmq.PUB) ++local s_FD = s:getopt(zmq.FD) ++ ++s:bind("tcp://lo:5555") ++ ++-- current socket state ++local blocked_state ++local blocked_event ++local on_sock_recv ++local on_sock_send ++ ++-- IO event callback when socket was blocked ++local function on_sock_io() ++ local events = s:getopt(z_EVENTS) ++ local unblocked = false ++ if events == blocked_event then ++ -- got the event the socket was blocked on. ++ unblocked = true ++ elseif events == z_POLLIN_OUT then ++ -- got both in & out events ++ unblocked = true ++ end ++ if unblocked then ++ -- got the event we are blocked on resume. ++ blocked_event = nil ++ blocked_state() ++ -- check if blocked event was processed. ++ if not blocked_event then ++ poll:remove_read(s_FD) ++ end ++ end ++end ++local function sock_blocked(state, event) ++ if not blocked_event then ++ -- need to register socket's fd with event loop ++ poll:add_read(s_FD, on_sock_io) ++ end ++ blocked_state = state ++ blocked_event = event ++end ++ ++-- sock state functions ++local msg_id = 1 ++function on_sock_send() ++ local sent, err = s:send(tostring(msg_id), z_NOBLOCK) ++ if not sent then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_send, z_POLLOUT) ++ end ++ -- message sent, inc. id ++ msg_id = msg_id + 1 ++ -- yield back to event loop ++ poll:add_work(on_sock_send) ++end ++ ++-- start processing of the socket. ++poll:add_work(on_sock_send) ++ ++-- start event loop ++poll:start() ++ ++s:close() ++ctx:term() ++ +diff --git a/examples/server.lua b/examples/server.lua +index 57bb278..3423c4e 100644 +--- a/examples/server.lua ++++ b/examples/server.lua +@@ -18,14 +18,14 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + +-require("zmq") ++local zmq = require"zmq" + +-local ctx = zmq.init(1) ++local ctx = zmq.init() + local s = ctx:socket(zmq.REP) + + s:bind("tcp://lo:5555") + + while true do +- print(string.format("Received query: '%s'", s:recv())) +- s:send("OK") ++ print(string.format("Received query: '%s'", s:recv())) ++ s:send("OK") + end +diff --git a/examples/server_multipart.lua b/examples/server_multipart.lua +index 663c3f7..c26e3e0 100644 +--- a/examples/server_multipart.lua ++++ b/examples/server_multipart.lua +@@ -18,18 +18,18 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + +-require("zmq") ++local zmq = require"zmq" + +-local ctx = zmq.init(1) ++local ctx = zmq.init() + local s = ctx:socket(zmq.REP) + + s:bind("tcp://lo:5555") + + while true do +- local query = s:recv() +- while s:getopt(zmq.RCVMORE) == 1 do +- query = query .. s:recv() +- end +- print(string.format("Received query: '%s'", query)) +- s:send("OK") ++ local query = s:recv() ++ while s:getopt(zmq.RCVMORE) == 1 do ++ query = query .. s:recv() ++ end ++ print(string.format("Received query: '%s'", query)) ++ s:send("OK") + end +diff --git a/examples/server_poll.lua b/examples/server_poll.lua +new file mode 100644 +index 0000000..42c8862 +--- /dev/null ++++ b/examples/server_poll.lua +@@ -0,0 +1,102 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local poller = require"examples.poller" ++local poll = poller.new() ++ ++local zmq = require"zmq" ++local z_NOBLOCK = zmq.NOBLOCK ++local z_EVENTS = zmq.EVENTS ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++ ++local ctx = zmq.init() ++local s = ctx:socket(zmq.REP) ++local s_FD = s:getopt(zmq.FD) ++ ++s:bind("tcp://lo:5555") ++ ++-- current socket state ++local blocked_state ++local blocked_event ++local on_sock_recv ++local on_sock_send ++ ++-- IO event callback when socket was blocked ++local function on_sock_io() ++ local events = s:getopt(z_EVENTS) ++ local unblocked = false ++ if events == blocked_event then ++ -- got the event the socket was blocked on. ++ unblocked = true ++ elseif events == z_POLLIN_OUT then ++ -- got both in & out events ++ unblocked = true ++ end ++ if unblocked then ++ -- got the event we are blocked on resume. ++ blocked_event = nil ++ blocked_state() ++ -- check if blocked event was processed. ++ if not blocked_event then ++ poll:remove_read(s_FD) ++ end ++ end ++end ++local function sock_blocked(state, event) ++ if not blocked_event then ++ -- need to register socket's fd with event loop ++ poll:add_read(s_FD, on_sock_io) ++ end ++ blocked_state = state ++ blocked_event = event ++end ++ ++-- sock state functions ++function on_sock_recv() ++ local data, err = s:recv(z_NOBLOCK) ++ if not data then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_recv, z_POLLIN) ++ end ++ print(string.format("Received query: '%s'", data)) ++ return on_sock_send() ++end ++ ++function on_sock_send() ++ local sent, err = s:send("OK", z_NOBLOCK) ++ if not sent then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_send, z_POLLOUT) ++ end ++ -- yield back to event loop ++ poll:add_work(on_sock_recv) ++end ++ ++-- start processing of the socket. ++poll:add_work(on_sock_recv) ++ ++-- start event loop ++poll:start() ++ ++s:close() ++ctx:term() ++ +diff --git a/examples/subscriber.lua b/examples/subscriber.lua +index 370b7dc..41434c7 100644 +--- a/examples/subscriber.lua ++++ b/examples/subscriber.lua +@@ -18,14 +18,14 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + +-require("zmq") ++local zmq = require"zmq" + +-local ctx = zmq.init(1) ++local ctx = zmq.init() + local s = ctx:socket(zmq.SUB) + s:setopt(zmq.SUBSCRIBE, "") + s:connect("tcp://localhost:5555") + while true do +- local msg = s:recv() +- local msg_id = tonumber(msg) +- if math.mod(msg_id, 10000) == 0 then print(msg_id) end ++ local msg = s:recv() ++ local msg_id = tonumber(msg) ++ if math.mod(msg_id, 10000) == 0 then print(msg_id) end + end +diff --git a/examples/subscriber_ev.lua b/examples/subscriber_ev.lua +new file mode 100644 +index 0000000..ae8506c +--- /dev/null ++++ b/examples/subscriber_ev.lua +@@ -0,0 +1,113 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local zmq = require"zmq" ++local z_NOBLOCK = zmq.NOBLOCK ++local z_EVENTS = zmq.EVENTS ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++local ev = require'ev' ++local loop = ev.Loop.default ++ ++-- define a sub_worker class ++local sub_worker_mt = {} ++function sub_worker_mt:close(...) ++ self.s_io_idle:stop(self.loop) ++ self.s_io_read:stop(self.loop) ++ return self.socket:close(...) ++end ++function sub_worker_mt:bind(...) ++ return self.socket:bind(...) ++end ++function sub_worker_mt:connect(...) ++ return self.socket:connect(...) ++end ++function sub_worker_mt:sub(topic) ++ return self.socket:setopt(zmq.SUBSCRIBE, topic) ++end ++function sub_worker_mt:unsub(topic) ++ return self.socket:setopt(zmq.UNSUBSCRIBE, topic) ++end ++sub_worker_mt.__index = sub_worker_mt ++ ++local function sub_worker(loop, ctx, msg_cb) ++ local s = ctx:socket(zmq.SUB) ++ local self = { loop = loop, socket = s, msg_cb = msg_cb } ++ setmetatable(self, sub_worker_mt) ++ -- create ev callbacks for recving data. ++ -- need idle watcher since ZeroMQ sockets are edge-triggered instead of level-triggered ++ local s_io_idle ++ local s_io_read ++ local max_recvs = 10 ++ local function s_recv(recv_cnt) ++ local msg, err = s:recv(z_NOBLOCK) ++ if err == 'timeout' then ++ -- need to block on read IO ++ return false ++ end ++ self:msg_cb(msg) ++ if recv_cnt > 1 then ++ return s_recv(recv_cnt - 1) ++ end ++ return true ++ end ++ s_io_idle = ev.Idle.new(function() ++ if not s_recv(max_recvs) then ++ -- need to block on read IO ++ s_io_idle:stop(loop) ++ s_io_read:start(loop) ++ end ++ end) ++ s_io_idle:start(loop) ++ s_io_read = ev.IO.new(function() ++ local events = s:getopt(z_EVENTS) ++ if events == z_POLLIN or events == z_POLLIN_OUT then ++ if s_recv(max_recvs) then ++ -- read IO is not block, enable idle watcher to handle reads. ++ s_io_idle:start(loop) ++ s_io_read:stop(loop) ++ end ++ end ++ end, s:getopt(zmq.FD), ev.READ) ++ self.s_io_idle = s_io_idle ++ self.s_io_read = s_io_read ++ return self ++end ++ ++local ctx = zmq.init() ++ ++-- message handling function. ++local function handle_msg(worker, msg) ++ local msg_id = tonumber(msg) ++ if math.mod(msg_id, 10000) == 0 then print(worker.id, msg_id) end ++end ++ ++local sub1 = sub_worker(loop, ctx, handle_msg) ++sub1.id = 'sub1' ++sub1:sub('') ++sub1:connect("tcp://localhost:5555") ++local sub2 = sub_worker(loop, ctx, handle_msg) ++sub2.id = 'sub2' ++sub2:sub('') ++sub2:connect("tcp://localhost:5555") ++ ++loop:loop() ++ +diff --git a/examples/subscriber_poll.lua b/examples/subscriber_poll.lua +new file mode 100644 +index 0000000..1be24b2 +--- /dev/null ++++ b/examples/subscriber_poll.lua +@@ -0,0 +1,96 @@ ++-- Copyright (c) 2012 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++local poller = require"examples.poller" ++local poll = poller.new() ++ ++local zmq = require"zmq" ++local z_NOBLOCK = zmq.NOBLOCK ++local z_EVENTS = zmq.EVENTS ++local z_POLLIN = zmq.POLLIN ++local z_POLLOUT = zmq.POLLOUT ++local z_POLLIN_OUT = z_POLLIN + z_POLLOUT ++ ++local N=tonumber(arg[1] or 100) ++ ++local ctx = zmq.init() ++local s = ctx:socket(zmq.SUB) ++local s_FD = s:getopt(zmq.FD) ++ ++s:setopt(zmq.SUBSCRIBE, "") ++s:connect("tcp://localhost:5555") ++ ++-- current socket state ++local blocked_state ++local blocked_event ++local on_sock_recv ++local on_sock_send ++ ++-- IO event callback when socket was blocked ++local function on_sock_io() ++ local events = s:getopt(z_EVENTS) ++ local unblocked = false ++ if events == blocked_event then ++ -- got the event the socket was blocked on. ++ unblocked = true ++ elseif events == z_POLLIN_OUT then ++ -- got both in & out events ++ unblocked = true ++ end ++ if unblocked then ++ -- got the event we are blocked on resume. ++ blocked_event = nil ++ blocked_state() ++ -- check if blocked event was processed. ++ if not blocked_event then ++ poll:remove_read(s_FD) ++ end ++ end ++end ++local function sock_blocked(state, event) ++ if not blocked_event then ++ -- need to register socket's fd with event loop ++ poll:add_read(s_FD, on_sock_io) ++ end ++ blocked_state = state ++ blocked_event = event ++end ++ ++-- sock state functions ++function on_sock_recv() ++ local data, err = s:recv(z_NOBLOCK) ++ if not data then ++ assert(err == 'timeout', "Bad error on zmq socket.") ++ return sock_blocked(on_sock_recv, z_POLLIN) ++ end ++ local msg_id = tonumber(data) ++ if (msg_id % 10000) == 0 then print(data) end ++ return on_sock_recv() ++end ++ ++-- start processing of the socket. ++poll:add_work(on_sock_recv) ++ ++-- start event loop ++poll:start() ++ ++s:close() ++ctx:term() ++ +diff --git a/perf/local_lat.lua b/perf/local_lat.lua +index d6a4ec1..4417c46 100644 +--- a/perf/local_lat.lua ++++ b/perf/local_lat.lua +@@ -30,16 +30,31 @@ local roundtrip_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.REP) +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.REP)) ++assert(s:bind(bind_to)) + + local msg = zmq.zmq_msg_t() + ++local timer ++ + for i = 1, roundtrip_count do + assert(s:recv_msg(msg)) ++ if not timer then ++ timer = zmq.stopwatch_start() ++ end + assert(msg:size() == message_size, "Invalid message size") + assert(s:send_msg(msg)) + end + ++local elapsed = timer:stop() ++ + s:close() + ctx:term() ++ ++local latency = elapsed / roundtrip_count / 2 ++ ++print(string.format("mean latency: %.3f [us]", latency)) ++local secs = elapsed / (1000 * 1000) ++print(string.format("elapsed = %f", secs)) ++print(string.format("msg/sec = %f", roundtrip_count / secs)) ++ +diff --git a/perf/local_multipart.lua b/perf/local_multipart.lua +index 7d3ab99..69955dd 100644 +--- a/perf/local_multipart.lua ++++ b/perf/local_multipart.lua +@@ -30,9 +30,9 @@ local message_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PULL) ++local s = assert(ctx:socket(zmq.PULL)) + --s:setopt(zmq.SUBSCRIBE, ""); +-s:bind(bind_to) ++assert(s:bind(bind_to)) + + local function recv_msg(s,msg) + assert(s:recv_msg(msg)) +diff --git a/perf/local_pull.lua b/perf/local_pull.lua +index a515f60..2d52b1e 100644 +--- a/perf/local_pull.lua ++++ b/perf/local_pull.lua +@@ -30,8 +30,8 @@ local message_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PULL) +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.PULL)) ++assert(s:bind(bind_to)) + + print(string.format("message size: %i [B]", message_size)) + print(string.format("message count: %i", message_count)) +diff --git a/perf/local_thr.lua b/perf/local_thr.lua +index 572c4e0..c7ede4c 100644 +--- a/perf/local_thr.lua ++++ b/perf/local_thr.lua +@@ -30,9 +30,9 @@ local message_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.SUB) +-s:setopt(zmq.SUBSCRIBE, ""); +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.SUB)) ++assert(s:setopt(zmq.SUBSCRIBE, "")) ++assert(s:bind(bind_to)) + + print(string.format("message size: %i [B]", message_size)) + print(string.format("message count: %i", message_count)) +diff --git a/perf/local_thr_poll.lua b/perf/local_thr_poll.lua +new file mode 100644 +index 0000000..2c3b7a4 +--- /dev/null ++++ b/perf/local_thr_poll.lua +@@ -0,0 +1,77 @@ ++-- Copyright (c) 2010 Aleksey Yeschenko ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++if not arg[3] then ++ print("usage: lua local_thr.lua ") ++ os.exit() ++end ++ ++local bind_to = arg[1] ++local message_size = tonumber(arg[2]) ++local message_count = tonumber(arg[3]) ++ ++local zmq = require"zmq" ++local z_poller = require"zmq.poller" ++local z_NOBLOCK = zmq.NOBLOCK ++ ++local poller = z_poller(64) ++ ++local ctx = zmq.init(1) ++local s = assert(ctx:socket(zmq.SUB)) ++assert(s:setopt(zmq.SUBSCRIBE, "")) ++assert(s:bind(bind_to)) ++ ++print(string.format("message size: %i [B]", message_size)) ++print(string.format("message count: %i", message_count)) ++ ++local msg ++msg = zmq.zmq_msg_t() ++ ++local cnt = 0 ++ ++poller:add(s, zmq.POLLIN, function(sock) ++ while s:recv_msg(msg, z_NOBLOCK) do ++ --assert(msg:size() == message_size, "Invalid message size") ++ cnt = cnt + 1 ++ if cnt == message_count then ++ poller:stop() ++ end ++ end ++end) ++ ++-- wait for first message ++assert(s:recv_msg(msg)) ++cnt = 1 ++ ++local timer = zmq.stopwatch_start() ++poller:start() ++local elapsed = timer:stop() ++ ++s:close() ++ctx:term() ++ ++if elapsed == 0 then elapsed = 1 end ++ ++local throughput = message_count / (elapsed / 1000000) ++local megabits = throughput * message_size * 8 / 1000000 ++ ++print(string.format("mean throughput: %i [msg/s]", throughput)) ++print(string.format("mean throughput: %.3f [Mb/s]", megabits)) ++ +diff --git a/perf/local_thr_push_pull.lua b/perf/local_thr_push_pull.lua +new file mode 100644 +index 0000000..727c94c +--- /dev/null ++++ b/perf/local_thr_push_pull.lua +@@ -0,0 +1,62 @@ ++-- Copyright (c) 2010 Aleksey Yeschenko ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++if not arg[3] then ++ print("usage: lua local_thr.lua ") ++ os.exit() ++end ++ ++local bind_to = arg[1] ++local message_size = tonumber(arg[2]) ++local message_count = tonumber(arg[3]) ++ ++local zmq = require"zmq" ++ ++local ctx = zmq.init(1) ++local s = assert(ctx:socket(zmq.PULL)) ++assert(s:bind(bind_to)) ++ ++print(string.format("message size: %i [B]", message_size)) ++print(string.format("message count: %i", message_count)) ++ ++local msg ++msg = zmq.zmq_msg_t() ++assert(s:recv_msg(msg)) ++ ++local timer = zmq.stopwatch_start() ++ ++for i = 1, message_count - 1 do ++ assert(s:recv_msg(msg)) ++ assert(msg:size() == message_size, "Invalid message size") ++end ++ ++local elapsed = timer:stop() ++ ++s:close() ++ctx:term() ++ ++if elapsed == 0 then elapsed = 1 end ++ ++local throughput = message_count / (elapsed / 1000000) ++local megabits = throughput * message_size * 8 / 1000000 ++ ++print(string.format("mean throughput: %i [msg/s]", throughput)) ++print(string.format("mean throughput: %.3f [Mb/s]", megabits)) ++ +diff --git a/perf/remote_lat.lua b/perf/remote_lat.lua +index 4376f60..c426279 100644 +--- a/perf/remote_lat.lua ++++ b/perf/remote_lat.lua +@@ -30,8 +30,8 @@ local roundtrip_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.REQ) +-s:connect(connect_to) ++local s = assert(ctx:socket(zmq.REQ)) ++assert(s:connect(connect_to)) + + local data = ("0"):rep(message_size) + local msg = zmq.zmq_msg_t.init_size(message_size) +@@ -54,3 +54,4 @@ local latency = elapsed / roundtrip_count / 2 + print(string.format("message size: %i [B]", message_size)) + print(string.format("roundtrip count: %i", roundtrip_count)) + print(string.format("mean latency: %.3f [us]", latency)) ++ +diff --git a/perf/remote_multipart.lua b/perf/remote_multipart.lua +index f071555..004120e 100644 +--- a/perf/remote_multipart.lua ++++ b/perf/remote_multipart.lua +@@ -31,8 +31,8 @@ local zmq = require"zmq" + local z_SNDMORE = zmq.SNDMORE + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PUSH) +-s:connect(connect_to) ++local s = assert(ctx:socket(zmq.PUSH)) ++assert(s:connect(connect_to)) + + local data = ("0"):rep(message_size/2) + local msg = zmq.zmq_msg_t.init_size(message_size/2) +diff --git a/perf/remote_push.lua b/perf/remote_push.lua +index a37a189..ff26903 100644 +--- a/perf/remote_push.lua ++++ b/perf/remote_push.lua +@@ -30,8 +30,8 @@ local message_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PUSH) +-s:connect(connect_to) ++local s = assert(ctx:socket(zmq.PUSH)) ++assert(s:connect(connect_to)) + + local data = ("0"):rep(message_size) + local msg = zmq.zmq_msg_t.init_size(message_size) +diff --git a/perf/remote_thr.lua b/perf/remote_thr.lua +index 967e08b..74cccb4 100644 +--- a/perf/remote_thr.lua ++++ b/perf/remote_thr.lua +@@ -30,8 +30,12 @@ local message_count = tonumber(arg[3]) + local zmq = require"zmq" + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PUB) +-s:connect(connect_to) ++local s = assert(ctx:socket(zmq.PUB)) ++-- for ZeroMQ 3.x need to change HWM option. ++assert(s:set_hwm(0)) ++assert(s:connect(connect_to)) ++ ++zmq.sleep(1) + + local data = ("0"):rep(message_size) + local msg_data = zmq.zmq_msg_t.init_data(data) +@@ -42,7 +46,6 @@ for i = 1, message_count do + assert(s:send_msg(msg)) + end + +---os.execute("sleep " .. 10) +- + s:close() + ctx:term() ++ +diff --git a/perf/remote_thr_push_pull.lua b/perf/remote_thr_push_pull.lua +new file mode 100644 +index 0000000..3604d6e +--- /dev/null ++++ b/perf/remote_thr_push_pull.lua +@@ -0,0 +1,49 @@ ++-- Copyright (c) 2010 Aleksey Yeschenko ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++if not arg[3] then ++ print("usage: lua remote_thr.lua ") ++ os.exit() ++end ++ ++local connect_to = arg[1] ++local message_size = tonumber(arg[2]) ++local message_count = tonumber(arg[3]) ++ ++local zmq = require"zmq" ++ ++local ctx = zmq.init(1) ++local s = assert(ctx:socket(zmq.PUSH)) ++assert(s:connect(connect_to)) ++ ++zmq.sleep(1) ++ ++local data = ("0"):rep(message_size) ++local msg_data = zmq.zmq_msg_t.init_data(data) ++local msg = zmq.zmq_msg_t.init() ++ ++for i = 1, message_count do ++ msg:copy(msg_data) ++ assert(s:send_msg(msg)) ++end ++ ++s:close() ++ctx:term() ++ +diff --git a/perf/thread_lat.lua b/perf/thread_lat.lua +index 93ed691..3f04689 100644 +--- a/perf/thread_lat.lua ++++ b/perf/thread_lat.lua +@@ -52,8 +52,8 @@ local child_code = [[ + ]] + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.REQ) +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.REQ)) ++assert(s:bind(bind_to)) + + local child_thread = zthreads.runstring(ctx, child_code, connect_to, message_size, roundtrip_count) + child_thread:start() +@@ -64,6 +64,8 @@ local msg = zmq.zmq_msg_t.init_size(message_size) + print(string.format("message size: %i [B]", message_size)) + print(string.format("roundtrip count: %i", roundtrip_count)) + ++zmq.sleep(2) -- wait for child thread to connect. ++ + local timer = zmq.stopwatch_start() + + for i = 1, roundtrip_count do +@@ -81,4 +83,7 @@ ctx:term() + local latency = elapsed / roundtrip_count / 2 + + print(string.format("mean latency: %.3f [us]", latency)) ++local secs = elapsed / (1000 * 1000) ++print(string.format("elapsed = %f", secs)) ++print(string.format("msg/sec = %f", roundtrip_count / secs)) + +diff --git a/perf/thread_push_pull.lua b/perf/thread_push_pull.lua +index f69ff48..5030172 100644 +--- a/perf/thread_push_pull.lua ++++ b/perf/thread_push_pull.lua +@@ -37,17 +37,18 @@ local child_code = [[ + local zthreads = require"zmq.threads" + + local ctx = zthreads.get_parent_ctx() +- local s = ctx:socket(zmq.PUSH) +- s:setopt(zmq.HWM, message_count/4) +- s:connect(connect_to) ++ local s = assert(ctx:socket(zmq.PUSH)) ++ assert(s:setopt(zmq.HWM, message_count/4)) ++ assert(s:connect(connect_to)) + + local data = ("0"):rep(message_size) +- local msg = zmq.zmq_msg_t.init_size(message_size) ++ local msg_data = zmq.zmq_msg_t.init_data(data) ++ local msg = zmq.zmq_msg_t.init() + + local timer = zmq.stopwatch_start() + + for i = 1, message_count do +- msg:set_data(data) ++ msg:copy(msg_data) + assert(s:send_msg(msg)) + end + +@@ -67,8 +68,8 @@ local child_code = [[ + ]] + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.PULL) +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.PULL)) ++assert(s:bind(bind_to)) + + print(string.format("message size: %i [B]", message_size)) + print(string.format("message count: %i", message_count)) +diff --git a/perf/thread_thr.lua b/perf/thread_thr.lua +index 7b9183a..a7a5d11 100644 +--- a/perf/thread_thr.lua ++++ b/perf/thread_thr.lua +@@ -24,8 +24,8 @@ end + + local message_size = tonumber(arg[1] or 1) + local message_count = tonumber(arg[2] or 100000) +-local bind_to = arg[3] or 'inproc://thread_lat_test' +-local connect_to = arg[4] or 'inproc://thread_lat_test' ++local bind_to = arg[3] or 'inproc://thread_thr_test' ++local connect_to = arg[4] or 'inproc://thread_thr_test' + + local zmq = require"zmq" + local zthreads = require"zmq.threads" +@@ -37,8 +37,10 @@ local child_code = [[ + local zthreads = require"zmq.threads" + + local ctx = zthreads.get_parent_ctx() +- local s = ctx:socket(zmq.PUB) +- s:connect(connect_to) ++ local s = assert(ctx:socket(zmq.PUB)) ++ -- for ZeroMQ 3.x need to change HWM option. ++ assert(s:set_hwm(0)) ++ assert(s:connect(connect_to)) + + local data = ("0"):rep(message_size) + local msg_data = zmq.zmq_msg_t.init_data(data) +@@ -67,9 +69,9 @@ local child_code = [[ + ]] + + local ctx = zmq.init(1) +-local s = ctx:socket(zmq.SUB) +-s:setopt(zmq.SUBSCRIBE, ""); +-s:bind(bind_to) ++local s = assert(ctx:socket(zmq.SUB)) ++assert(s:setopt(zmq.SUBSCRIBE, "")) ++assert(s:bind(bind_to)) + + print(string.format("message size: %i [B]", message_size)) + print(string.format("message count: %i", message_count)) +diff --git a/rockspecs/lua-zmq-scm-1.rockspec b/rockspecs/lua-zmq-scm-1.rockspec +index 10737b7..b3cd3c6 100644 +--- a/rockspecs/lua-zmq-scm-1.rockspec ++++ b/rockspecs/lua-zmq-scm-1.rockspec +@@ -12,12 +12,28 @@ dependencies = { + "lua >= 5.1", + } + external_dependencies = { ++ platforms = { ++ windows = { ++ ZEROMQ = { ++ library = "libzmq", ++ } ++ }, ++ }, + ZEROMQ = { + header = "zmq.h", + library = "zmq", + } + } + build = { ++ platforms = { ++ windows = { ++ modules = { ++ zmq = { ++ libraries = {"libzmq"}, ++ } ++ } ++ }, ++ }, + type = "builtin", + modules = { + zmq = { +diff --git a/rockspecs/lua-zmq-wireshark-scm-0.rockspec b/rockspecs/lua-zmq-wireshark-scm-0.rockspec +new file mode 100644 +index 0000000..5e3e0e1 +--- /dev/null ++++ b/rockspecs/lua-zmq-wireshark-scm-0.rockspec +@@ -0,0 +1,22 @@ ++package = "lua-zmq-wireshark" ++version = "scm-0" ++source = { ++ url = "git://github.com/Neopallium/lua-zmq.git", ++} ++description = { ++ summary = "Lua Wireshark dissector for the ZeroMQ protocol.", ++ homepage = "http://github.com/Neopallium/lua-zmq", ++ -- Wireshark requires dissectors to be licensed under the GPL. ++ license = "GPL", ++} ++dependencies = {} ++build = { ++ type = "none", ++ install = { ++ lua = { ++ ['zmq.ws.dissector'] = "ws/dissector.lua", ++ ['zmq.ws.tap'] = "ws/tap.lua", ++ ['zmq.ws.stats_tap'] = "ws/stats_tap.lua", ++ }, ++ }, ++} +diff --git a/src/ctx.nobj.lua b/src/ctx.nobj.lua +index adc0c42..694520f 100644 +--- a/src/ctx.nobj.lua ++++ b/src/ctx.nobj.lua +@@ -19,6 +19,7 @@ + -- THE SOFTWARE. + + object "ZMQ_Ctx" { ++ sys_include"string.h", + error_on_null = "get_zmq_strerror()", + c_source [[ + typedef struct ZMQ_Ctx ZMQ_Ctx; +@@ -35,5 +36,13 @@ typedef struct ZMQ_Ctx ZMQ_Ctx; + method "socket" { + c_method_call "!ZMQ_Socket *" "zmq_socket" { "int", "type"} + }, ++ method "set" { ++ if_defs = { "VERSION_3_2" }, ++ c_method_call "int" "zmq_ctx_set" { "int", "flag", "int", "value" } ++ }, ++ method "get" { ++ if_defs = { "VERSION_3_2" }, ++ c_method_call "int" "zmq_ctx_get" { "int", "flag" } ++ }, + } + +diff --git a/src/error.nobj.lua b/src/error.nobj.lua +index 4e353f3..b5559c7 100644 +--- a/src/error.nobj.lua ++++ b/src/error.nobj.lua +@@ -18,26 +18,295 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + ++-- E* error values. ++meta_object "ZErrors" { ++ export_definitions { ++ -- Native 0MQ error codes. ++ "EFSM", ++ "ENOCOMPATPROTO", ++ "ETERM", ++ "EMTHREAD", ++ ++ "EPERM", -- Operation not permitted ++ "ENOENT", -- No such file or directory ++ "ESRCH", -- No such process ++ "EINTR", -- Interrupted system call ++ "EIO", -- I/O error ++ "ENXIO", -- No such device or address ++ "E2BIG", -- Argument list too long ++ "ENOEXEC", -- Exec format error ++ "EBADF", -- Bad file number ++ "ECHILD", -- No child processes ++ "EAGAIN", -- Try again ++ "ENOMEM", -- Out of memory ++ "EACCES", -- Permission denied ++ "EFAULT", -- Bad address ++ "ENOTBLK", -- Block device required ++ "EBUSY", -- Device or resource busy ++ "EEXIST", -- File exists ++ "EXDEV", -- Cross-device link ++ "ENODEV", -- No such device ++ "ENOTDIR", -- Not a directory ++ "EISDIR", -- Is a directory ++ "EINVAL", -- Invalid argument ++ "ENFILE", -- File table overflow ++ "EMFILE", -- Too many open files ++ "ENOTTY", -- Not a typewriter ++ "ETXTBSY", -- Text file busy ++ "EFBIG", -- File too large ++ "ENOSPC", -- No space left on device ++ "ESPIPE", -- Illegal seek ++ "EROFS", -- Read-only file system ++ "EMLINK", -- Too many links ++ "EPIPE", -- Broken pipe ++ "EDOM", -- Math argument out of domain of func ++ "ERANGE", -- Math result not representable ++ ++ "EDEADLK", -- Resource deadlock would occur ++ "EDEADLOCK", -- EDEADLK ++ "ENAMETOOLONG", -- File name too long ++ "ENOLCK", -- No record locks available ++ "ENOSYS", -- Function not implemented ++ "ENOTEMPTY", -- Directory not empty ++ "ELOOP", -- Too many symbolic links encountered ++ "EWOULDBLOCK", -- Operation would block ++ "ENOMSG", -- No message of desired type ++ "EIDRM", -- Identifier removed ++ "ECHRNG", -- Channel number out of range ++ "EL2NSYNC", -- Level 2 not synchronized ++ "EL3HLT", -- Level 3 halted ++ "EL3RST", -- Level 3 reset ++ "ELNRNG", -- Link number out of range ++ "EUNATCH", -- Protocol driver not attached ++ "ENOCSI", -- No CSI structure available ++ "EL2HLT", -- Level 2 halted ++ "EBADE", -- Invalid exchange ++ "EBADR", -- Invalid request descriptor ++ "EXFULL", -- Exchange full ++ "ENOANO", -- No anode ++ "EBADRQC", -- Invalid request code ++ "EBADSLT", -- Invalid slot ++ ++ "EBFONT", -- Bad font file format ++ "ENOSTR", -- Device not a stream ++ "ENODATA", -- No data available ++ "ETIME", -- Timer expired ++ "ENOSR", -- Out of streams resources ++ "ENONET", -- Machine is not on the network ++ "ENOPKG", -- Package not installed ++ "EREMOTE", -- Object is remote ++ "ENOLINK", -- Link has been severed ++ "EADV", -- Advertise error ++ "ESRMNT", -- Srmount error ++ "ECOMM", -- Communication error on send ++ "EPROTO", -- Protocol error ++ "EMULTIHOP", -- Multihop attempted ++ "EDOTDOT", -- RFS specific error ++ "EBADMSG", -- Not a data message ++ "EOVERFLOW", -- Value too large for defined data type ++ "ENOTUNIQ", -- Name not unique on network ++ "EBADFD", -- File descriptor in bad state ++ "EREMCHG", -- Remote address changed ++ "ELIBACC", -- Can not access a needed shared library ++ "ELIBBAD", -- Accessing a corrupted shared library ++ "ELIBSCN", -- .lib section in a.out corrupted ++ "ELIBMAX", -- Attempting to link in too many shared libraries ++ "ELIBEXEC", -- Cannot exec a shared library directly ++ "EILSEQ", -- Illegal byte sequence ++ "ERESTART", -- Interrupted system call should be restarted ++ "ESTRPIPE", -- Streams pipe error ++ "EUSERS", -- Too many users ++ "ENOTSOCK", -- Socket operation on non-socket ++ "EDESTADDRREQ", -- Destination address required ++ "EMSGSIZE", -- Message too long ++ "EPROTOTYPE", -- Protocol wrong type for socket ++ "ENOPROTOOPT", -- Protocol not available ++ "EPROTONOSUPPORT", -- Protocol not supported ++ "ESOCKTNOSUPPORT", -- Socket type not supported ++ "EOPNOTSUPP", -- Operation not supported on transport endpoint ++ "EPFNOSUPPORT", -- Protocol family not supported ++ "EAFNOSUPPORT", -- Address family not supported by protocol ++ "EADDRINUSE", -- Address already in use ++ "EADDRNOTAVAIL", -- Cannot assign requested address ++ "ENETDOWN", -- Network is down ++ "ENETUNREACH", -- Network is unreachable ++ "ENETRESET", -- Network dropped connection because of reset ++ "ECONNABORTED", -- Software caused connection abort ++ "ECONNRESET", -- Connection reset by peer ++ "ENOBUFS", -- No buffer space available ++ "EISCONN", -- Transport endpoint is already connected ++ "ENOTCONN", -- Transport endpoint is not connected ++ "ESHUTDOWN", -- Cannot send after transport endpoint shutdown ++ "ETOOMANYREFS", -- Too many references: cannot splice ++ "ETIMEDOUT", -- Connection timed out ++ "ECONNREFUSED", -- Connection refused ++ "EHOSTDOWN", -- Host is down ++ "EHOSTUNREACH", -- No route to host ++ "EALREADY", -- Operation already in progress ++ "EINPROGRESS", -- Operation now in progress ++ "ESTALE", -- Stale NFS file handle ++ "EUCLEAN", -- Structure needs cleaning ++ "ENOTNAM", -- Not a XENIX named type file ++ "ENAVAIL", -- No XENIX semaphores available ++ "EISNAM", -- Is a named type file ++ "EREMOTEIO", -- Remote I/O error ++ "EDQUOT", -- Quota exceeded ++ ++ "ENOMEDIUM", -- No medium found ++ "EMEDIUMTYPE", -- Wrong medium type ++ "ECANCELED", -- Operation Canceled ++ "ENOKEY", -- Required key not available ++ "EKEYEXPIRED", -- Key has expired ++ "EKEYREVOKED", -- Key has been revoked ++ "EKEYREJECTED", -- Key was rejected by service ++ ++ -- for robust mutexes ++ "EOWNERDEAD", -- Owner died ++ "ENOTRECOVERABLE", -- State not recoverable ++ ++ "ERFKILL", -- Operation not possible due to RF-kill ++ }, ++ ++ method "description" { ++ var_in{ "", "err" }, ++ var_out{ "const char *", "msg" }, ++ c_source "pre" [[ ++ int err_type; ++ int err_num = -1; ++]], ++ c_source[[ ++ err_type = lua_type(L, ${err::idx}); ++ if(err_type == LUA_TSTRING) { ++ lua_pushvalue(L, ${err::idx}); ++ lua_rawget(L, ${this::idx}); ++ if(lua_isnumber(L, -1)) { ++ err_num = lua_tointeger(L, -1); ++ } ++ lua_pop(L, 1); ++ } else if(err_type == LUA_TNUMBER) { ++ err_num = lua_tointeger(L, ${err::idx}); ++ } else { ++ return luaL_argerror(L, ${err::idx}, "expected string/number"); ++ } ++ if(err_num < 0) { ++ lua_pushnil(L); ++ lua_pushliteral(L, "UNKNOWN ERROR"); ++ return 2; ++ } ++ ${msg} = strerror(err_num); ++]], ++ }, ++ ++ method "__index" { ++ var_in{ "int", "err" }, ++ var_out{ "const char *", "msg" }, ++ c_source[[ ++ switch(${err}) { ++ case EAGAIN: ++ ${msg} = "timeout"; ++ break; ++ case EINTR: ++ ${msg} = "interrupted"; ++ break; ++#if defined(ETERM) ++ case ETERM: ++ ${msg} = "closed"; ++ break; ++#endif ++ default: ++ ${msg} = zmq_strerror(${err}); ++ break; ++ } ++ lua_pushvalue(L, ${err::idx}); ++ lua_pushstring(L, ${msg}); ++ lua_rawset(L, ${this::idx}); ++]], ++ }, ++} ++ ++ffi_cdef[[ ++int zmq_errno (void); ++]] ++ ++ffi_source "ffi_src" [[ ++-- get ZErrors table to map errno to error name. ++local ZError_names = _M.ZErrors ++ ++local function get_zmq_strerror() ++ return ZError_names[C.zmq_errno()] ++end ++]] ++ ++c_source "extra_code" [[ ++static char *zmq_ZErrors_key = "zmq_ZErrors_key"; ++/* ++ * This wrapper function is to make the EAGAIN/ETERM error messages more like ++ * what is returned by LuaSocket. ++ */ ++static const char *get_zmq_strerror() { ++ int err = zmq_errno(); ++ switch(err) { ++ case EAGAIN: ++ return "timeout"; ++ break; ++ case EINTR: ++ return "interrupted"; ++ break; ++#if defined(ETERM) ++ case ETERM: ++ return "closed"; ++ break; ++#endif ++ default: ++ break; ++ } ++ return zmq_strerror(err); ++} ++ ++]] ++ ++c_source "module_init_src" [[ ++ /* Cache reference to zmq.ZErrors table for errno->string convertion. */ ++ lua_pushlightuserdata(L, zmq_ZErrors_key); ++ lua_getfield(L, -2, "ZErrors"); ++ lua_rawset(L, LUA_REGISTRYINDEX); ++]] ++ + -- Convert ZMQ Error codes into strings. + -- + -- This is an error code wrapper object, it converts C-style 'int' return error code + -- into Lua-style 'nil, "Error message"' return values. + -- + error_code "ZMQ_Error" "int" { +- ffi_cdef[[ +-typedef int ZMQ_Error; +-]], ++ ffi_type = "int", + is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end, + ffi_is_error_check = function(rec) return "(-1 == ${" .. rec.name .. "})" end, + default = "0", + c_source [[ ++ int num; + if(-1 == err) { +- err_str = get_zmq_strerror(); ++ /* get ZErrors table. */ ++ lua_pushlightuserdata(L, zmq_ZErrors_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); ++ /* convert zmq_errno to string. */ ++ num = zmq_errno(); ++ lua_pushinteger(L, num); ++ lua_gettable(L, -2); ++ /* remove ZErrors table. */ ++ lua_remove(L, -2); ++ if(!lua_isnil(L, -1)) { ++ /* found error. */ ++ return; ++ } ++ /* Unknown error. */ ++ lua_pop(L, 1); ++ lua_pushfstring(L, "UNKNOWN ERROR(%d)", num); ++ return; + } + ]], + ffi_source [[ + if(-1 == err) then +- err_str = get_zmq_strerror(); ++ err_str = ZError_names[C.zmq_errno()] + end + ]], + } +diff --git a/src/msg.nobj.lua b/src/msg.nobj.lua +index 28e18ed..c46e189 100644 +--- a/src/msg.nobj.lua ++++ b/src/msg.nobj.lua +@@ -21,6 +21,22 @@ + object "zmq_msg_t" { + -- store the `zmq_msg_t` structure in Lua userdata object + userdata_type = "embed", ++ implements "Buffer" { ++ implement_method "const_data" { ++ c_function = "zmq_msg_data" ++ }, ++ implement_method "get_size" { ++ c_function = "zmq_msg_size" ++ }, ++ }, ++ implements "MutableBuffer" { ++ implement_method "data" { ++ c_function = "zmq_msg_data" ++ }, ++ implement_method "get_size" { ++ c_function = "zmq_msg_size" ++ }, ++ }, + -- + -- Define zmq_msq_t type & function API for FFI + -- +@@ -34,42 +50,31 @@ struct zmq_msg_t + unsigned char vsm_data [30]; /* that '30' is from 'MAX_VSM_SIZE' */ + }; + +-typedef void (zmq_free_fn) (void *data, void *hint); +- + int zmq_msg_init (zmq_msg_t *msg); + int zmq_msg_init_size (zmq_msg_t *msg, size_t size); +-int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint); + + ]], + constructor "init" { +- var_out{ "ZMQ_Error", "err" }, +- c_source[[ +- zmq_msg_t tmp; +- ${this} = &tmp; +- ${err} = zmq_msg_init(${this}); +-]], ++ c_method_call "ZMQ_Error" "zmq_msg_init" {}, + }, + constructor "init_size" { +- var_in{ "size_t", "size" }, +- var_out{ "ZMQ_Error", "err" }, +- c_source[[ +- zmq_msg_t tmp; +- ${this} = &tmp; +- ${err} = zmq_msg_init_size(${this}, ${size}); +-]], ++ c_method_call "ZMQ_Error" "zmq_msg_init_size" { "size_t", "size" }, + }, + constructor "init_data" { + var_in{ "const char *", "data" }, +- var_out{ "ZMQ_Error", "err" }, ++ c_method_call { "ZMQ_Error", "err" } "zmq_msg_init_size" { "size_t", "#data" }, + c_source[[ +- zmq_msg_t tmp; +- ${this} = &tmp; +- ${err} = zmq_msg_init_size(${this}, ${data_len}); + if(0 == ${err}) { + /* fill message */ + memcpy(zmq_msg_data(${this}), ${data}, ${data_len}); + } + ]], ++ ffi_source[[ ++ if(0 == ${err}) then ++ -- fill message ++ ffi.copy(C.zmq_msg_data(${this}), ${data}, ${data_len}) ++ end ++]], + }, + destructor { + c_method_call "ZMQ_Error" "zmq_msg_close" {} +@@ -143,7 +148,7 @@ int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn + ]], + }, + method "size" { +- c_method_call "size_t" "zmq_msg_size" {} ++ c_method_call { "size_t", "size", ffi_wrap = "tonumber"} "zmq_msg_size" {} + }, + method "__tostring" { + var_out{ "const char *", "data", has_length = true }, +diff --git a/src/poller.lua b/src/poller.lua +index 8c77337..2ca40ea 100644 +--- a/src/poller.lua ++++ b/src/poller.lua +@@ -34,43 +34,36 @@ local poller_mt = {} + poller_mt.__index = poller_mt + + function poller_mt:add(sock, events, cb) +- self.poller:add(sock, events) +- self.callbacks[sock] = cb ++ local id = self.poller:add(sock, events) ++ self.callbacks[id] = function(revents) return cb(sock, revents) end + end + + function poller_mt:modify(sock, events, cb) ++ local id + if events ~= 0 and cb then +- self.callbacks[sock] = cb +- self.poller:modify(sock, events) ++ id = self.poller:modify(sock, events) ++ self.callbacks[id] = function(revents) return cb(sock, revents) end + else +- self:remove(sock) ++ id = self:remove(sock) ++ self.callbacks[id] = nil + end + end + + function poller_mt:remove(sock) +- self.poller:remove(sock) +- self.callbacks[sock] = nil ++ local id = self.poller:remove(sock) ++ self.callbacks[id] = nil + end + + function poller_mt:poll(timeout) + local poller = self.poller +- local status, err = poller:poll(timeout) +- if not status then ++ local count, err = poller:poll(timeout) ++ if not count then + return nil, err + end + local callbacks = self.callbacks +- local count = 0 +- while true do +- local sock, revents = poller:next_revents() +- if not sock then +- break +- end +- local cb = callbacks[sock] +- if not cb then +- error("Missing callback for sock:" .. tostring(sock)) +- end +- cb(sock, revents) +- count = count + 1 ++ for i=1,count do ++ local id, revents = poller:next_revents_idx() ++ callbacks[id](revents) + end + return count + end +@@ -78,7 +71,7 @@ end + function poller_mt:start() + self.is_running = true + while self.is_running do +- local status, err = self:poll(-1) ++ status, err = self:poll(-1) + if not status then + return false, err + end +@@ -90,14 +83,15 @@ function poller_mt:stop() + self.is_running = false + end + +-module(...) ++local M = {} + +-function new(pre_alloc) ++function M.new(pre_alloc) + return setmetatable({ + poller = zmq.ZMQ_Poller(pre_alloc), +- callbacks = setmetatable({}, {__mode="k"}), ++ callbacks = {}, + }, poller_mt) + end + +-setmetatable(_M, {__call = function(tab, ...) return new(...) end}) ++zmq.poller = M ++return setmetatable(M, {__call = function(tab, ...) return M.new(...) end}) + +diff --git a/src/poller.nobj.lua b/src/poller.nobj.lua +index 66594d2..fc51ac9 100644 +--- a/src/poller.nobj.lua ++++ b/src/poller.nobj.lua +@@ -58,7 +58,24 @@ static int poller_resize_items(ZMQ_Poller *poller, int len) { + return len; + } + +-static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { ++void poller_init(ZMQ_Poller *poller, int length) { ++ poller->items = (zmq_pollitem_t *)calloc(length, sizeof(zmq_pollitem_t)); ++ poller->next = -1; ++ poller->count = 0; ++ poller->len = length; ++ poller->free_list = -1; ++} ++ ++void poller_cleanup(ZMQ_Poller *poller) { ++ free(poller->items); ++ poller->items = NULL; ++ poller->next = -1; ++ poller->count = 0; ++ poller->len = 0; ++ poller->free_list = -1; ++} ++ ++int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { + zmq_pollitem_t *items; + int count; + int n; +@@ -73,7 +90,7 @@ static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { + return -1; + } + +-static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { ++int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { + zmq_pollitem_t *items; + int count; + int n; +@@ -88,7 +105,7 @@ static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { + return -1; + } + +-static void poller_remove_item(ZMQ_Poller *poller, int idx) { ++void poller_remove_item(ZMQ_Poller *poller, int idx) { + zmq_pollitem_t *items; + int free_list; + int count; +@@ -115,7 +132,7 @@ static void poller_remove_item(ZMQ_Poller *poller, int idx) { + items[idx].revents = 0; + } + +-static int poller_get_free_item(ZMQ_Poller *poller) { ++int poller_get_free_item(ZMQ_Poller *poller) { + zmq_pollitem_t *curr; + zmq_pollitem_t *next; + int count; +@@ -191,14 +208,46 @@ static int poller_compact_items(ZMQ_Poller *poller) { + return count; + } + +-static int poller_poll(ZMQ_Poller *poller, long timeout) { ++int poller_poll(ZMQ_Poller *poller, long timeout) { + int count; + /* remove free slots from items list. */ +- count = poller_compact_items(poller); ++ if(poller->free_list >= 0) { ++ count = poller_compact_items(poller); ++ } else { ++ count = poller->count; ++ } + /* poll for events. */ + return zmq_poll(poller->items, count, timeout); + } + ++int poller_next_revents(ZMQ_Poller *poller, int *revents) { ++ zmq_pollitem_t *items; ++ int count; ++ int idx; ++ int next; ++ ++ idx = poller->next; ++ /* do we need to poll for more events? */ ++ if(idx < 0) { ++ return idx; ++ } ++ items = poller->items; ++ count = poller->count; ++ /* find next item with pending events. */ ++ for(;idx < count; ++idx) { ++ /* did we find a pending event? */ ++ if(items[idx].revents != 0) { ++ *revents = items[idx].revents; ++ poller->next = idx+1; ++ return idx; ++ } ++ } ++ /* processed all pending events. */ ++ poller->next = -1; ++ *revents = 0; ++ return -1; ++} ++ + ]], + -- + -- Define ZMQ_Poller type & function API for FFI +@@ -212,36 +261,21 @@ typedef struct zmq_pollitem_t { + short revents; + } zmq_pollitem_t; + +-int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); ++int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock); ++int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd); ++int poller_get_free_item(ZMQ_Poller *poller); ++int poller_poll(ZMQ_Poller *poller, long timeout); ++void poller_remove_item(ZMQ_Poller *poller, int idx); ++ + ]], + ffi_cdef(ZMQ_Poller_type), +- ffi_export_function "int" "poller_find_sock_item" "(ZMQ_Poller *poller, ZMQ_Socket *sock)", +- ffi_export_function "int" "poller_find_fd_item" "(ZMQ_Poller *poller, socket_t fd)", +- ffi_export_function "int" "poller_get_free_item" "(ZMQ_Poller *poller)", +- ffi_export_function "int" "poller_poll" "(ZMQ_Poller *poller, long timeout)", +- ffi_export_function "void" "poller_remove_item" "(ZMQ_Poller *poller, int idx)", + + constructor "new" { + var_in{ "unsigned int", "length", is_optional = true, default = 10 }, +- c_source[[ +- ZMQ_Poller poller; +- ${this} = &poller; +- ${this}->items = (zmq_pollitem_t *)calloc(${length}, sizeof(zmq_pollitem_t)); +- ${this}->next = -1; +- ${this}->count = 0; +- ${this}->len = ${length}; +- ${this}->free_list = -1; +-]], ++ c_export_method_call "void" "poller_init" { "unsigned int", "length" }, + }, + destructor "close" { +- c_source[[ +- free(${this}->items); +- ${this}->items = NULL; +- ${this}->next = -1; +- ${this}->count = 0; +- ${this}->len = 0; +- ${this}->free_list = -1; +-]], ++ c_export_method_call "void" "poller_cleanup" {}, + }, + method "add" { + var_in{ "", "sock" }, +@@ -266,6 +300,23 @@ int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); + item->fd = fd; + item->events = ${events}; + ]], ++ ffi_source[[ ++ local fd = 0 ++ local sock_type = type(${sock}) ++ local sock ++ if sock_type == 'cdata' then ++ sock = obj_type_ZMQ_Socket_check(${sock}) ++ elseif sock_type == 'number' then ++ fd = ${sock} ++ else ++ error("expected number or ZMQ_Socket") ++ end ++ ${idx} = Cmod.poller_get_free_item(${this}) ++ local item = ${this}.items[${idx}] ++ item.socket = sock ++ item.fd = fd ++ item.events = ${events} ++]], + }, + method "modify" { + var_in{ "", "sock" }, +@@ -302,123 +353,101 @@ int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout); + poller_remove_item(${this}, ${idx}); + } + ]], ++ ffi_source[[ ++ local fd = 0 ++ local sock_type = type(${sock}) ++ local sock ++ if sock_type == 'cdata' then ++ sock = obj_type_ZMQ_Socket_check(${sock}) ++ -- find sock in items list. ++ ${idx} = Cmod.poller_find_sock_item(${this}, sock) ++ elseif sock_type == 'number' then ++ fd = ${sock} ++ -- find fd in items list. ++ ${idx} = Cmod.poller_find_fd_item(${this}, fd); ++ else ++ error("expected number or ZMQ_Socket") ++ end ++ if ${events} ~= 0 then ++ local item = ${this}.items[${idx}] ++ item.socket = sock ++ item.fd = fd ++ item.events = ${events} ++ else ++ Cmod.poller_remove_item(${this}, ${idx}) ++ end ++]], + }, + method "remove" { + var_in{ "", "sock" }, ++ var_out{ "int", "idx" }, + c_source "pre" [[ + ZMQ_Socket *sock; + socket_t fd; +- int idx; + ]], + c_source[[ + /* ZMQ_Socket or fd */ + if(lua_isuserdata(L, ${sock::idx})) { + sock = obj_type_ZMQ_Socket_check(L, ${sock::idx}); + /* find sock in items list. */ +- idx = poller_find_sock_item(${this}, sock); ++ ${idx} = poller_find_sock_item(${this}, sock); + } else if(lua_isnumber(L, ${sock::idx})) { + fd = lua_tonumber(L, ${sock::idx}); + /* find fd in items list. */ +- idx = poller_find_fd_item(${this}, fd); ++ ${idx} = poller_find_fd_item(${this}, fd); + } else { + return luaL_typerror(L, ${sock::idx}, "number or ZMQ_Socket"); + } + /* if sock/fd was found. */ +- if(idx >= 0) { +- poller_remove_item(${this}, idx); ++ if(${idx} >= 0) { ++ poller_remove_item(${this}, ${idx}); + } + ]], ++ ffi_source[[ ++ local fd = 0 ++ local sock_type = type(${sock}) ++ local sock ++ if sock_type == 'cdata' then ++ sock = obj_type_ZMQ_Socket_check(${sock}) ++ -- find sock in items list. ++ ${idx} = Cmod.poller_find_sock_item(${this}, sock) ++ elseif sock_type == 'number' then ++ fd = ${sock} ++ -- find fd in items list. ++ ${idx} = Cmod.poller_find_fd_item(${this}, fd); ++ else ++ error("expected number or ZMQ_Socket") ++ end ++ if ${idx} >= 0 then ++ Cmod.poller_remove_item(${this}, ${idx}) ++ end ++]], + }, + method "poll" { +- var_in{ "long", "timeout" }, +- var_out{ "ZMQ_Error", "err" }, ++ var_out{ "int", "count" }, ++ -- poll for events ++ c_export_method_call { "ZMQ_Error", "err>2" } "poller_poll" { "long", "timeout" }, + c_source[[ +- /* poll for events */ +- ${err} = poller_poll(${this}, ${timeout}); + if(${err} > 0) { + ${this}->next = 0; ++ ${count} = ${err}; + } else { + ${this}->next = -1; ++ ${count} = 0; + } + ]], + ffi_source[[ +- -- poll for events +- ${err} = poller_poll(${this}, ${timeout}) + if(${err} > 0) then + ${this}.next = 0 ++ ${count} = ${err} + else + ${this}.next = -1 ++ ${count} = 0 + end + ]], + }, +- method "next_revents" { +- var_out{ "", "sock" }, +- var_out{ "short", "revents" }, +- c_source "pre" [[ +- zmq_pollitem_t *items; +- int count; +- int idx; +-]], +- c_source[[ +- ${revents} = -1; +- idx = ${this}->next; +- if(idx >= 0) { +- count = ${this}->count; +- items = ${this}->items; +- /* find next item with pending events. */ +- while(idx < count && items[idx].revents == 0) ++idx; +- /* did we find a pending event? */ +- if(idx < count) { +- /* push the event's sock/fd. */ +- if(items[idx].socket != NULL) { +- obj_type_ZMQ_Socket_push(L, items[idx].socket, 0); +- } else { +- lua_pushnumber(L, items[idx].fd); +- } +- ${revents} = items[idx].revents; +- /* is this the last event. */ +- ++idx; +- ${this}->next = (idx < count) ? idx : -1; +- } +- } +- if(${revents} < 0) { +- /* no more pending events. */ +- lua_pushnil(L); +- ${this}->next = -1; +- } +-]], +- ffi_source[[ +- local sock +- local idx = ${this}.next +- if (idx < 0) then return nil, -1 end +- local count = ${this}.count +- -- find next item with pending events. +- while (idx < count and ${this}.items[idx].revents == 0) do +- idx = idx + 1 +- if (idx >= count) then +- idx = -1 +- break +- end +- end +- -- did we find a pending event? +- if(idx >= 0) then +- -- push the event's sock/fd. +- if(${this}.items[idx].socket ~= nil) then +- sock = obj_type_ZMQ_Socket_push(${this}.items[idx].socket, 0) +- else +- sock = tonumber(${this}.items[idx].fd) +- end +- ${revents} = ${this}.items[idx].revents +- -- is this the last event. +- idx = idx + 1 +- if (idx >= count) then +- idx = -1 +- end +- ${this}.next = idx +- return sock, ${revents} +- end +- ${this}.next = idx +-]], ++ method "next_revents_idx" { ++ c_export_method_call { "int", "idx>1" } "poller_next_revents" { "int", "&revents>2" }, + }, + method "count" { + var_out{ "int", "count" }, +diff --git a/src/pre_generated-zmq.nobj.c b/src/pre_generated-zmq.nobj.c +index a6d739d..081807f 100644 +--- a/src/pre_generated-zmq.nobj.c ++++ b/src/pre_generated-zmq.nobj.c +@@ -10,16 +10,65 @@ + #include "lauxlib.h" + #include "lualib.h" + +-#include +-#include "zmq.h" +-#include "zmq_utils.h" ++/* some Lua 5.0 compatibility support. */ ++#if !defined(lua_pushliteral) ++#define lua_pushliteral(L, s) lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1) ++#endif ++ ++#if !defined(LUA_VERSION_NUM) ++#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)n) ++#define luaL_Reg luaL_reg ++#endif ++ ++/* some Lua 5.1 compatibility support. */ ++#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) ++/* ++** Adapted from Lua 5.2.0 ++*/ ++static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { ++ luaL_checkstack(L, nup, "too many upvalues"); ++ for (; l->name != NULL; l++) { /* fill the table with given functions */ ++ int i; ++ for (i = 0; i < nup; i++) /* copy upvalues to the top */ ++ lua_pushvalue(L, -nup); ++ lua_pushstring(L, l->name); ++ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ ++ lua_settable(L, -(nup + 3)); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++ ++#define lua_load_no_mode(L, reader, data, source) \ ++ lua_load(L, reader, data, source) ++ ++#define lua_rawlen(L, idx) lua_objlen(L, idx) ++ ++#endif ++ ++#if LUA_VERSION_NUM == 502 ++ ++#define lua_load_no_mode(L, reader, data, source) \ ++ lua_load(L, reader, data, source, NULL) + ++static int luaL_typerror (lua_State *L, int narg, const char *tname) { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++} ++ ++#endif + + #define REG_PACKAGE_IS_CONSTRUCTOR 0 ++#define REG_MODULES_AS_GLOBALS 1 + #define REG_OBJECTS_AS_GLOBALS 0 + #define OBJ_DATA_HIDDEN_METATABLE 1 +-#define LUAJIT_FFI 1 + #define USE_FIELD_GET_SET_METHODS 0 ++#define LUAJIT_FFI 1 ++ ++ ++#include ++#include "zmq.h" ++#include "zmq_utils.h" + + + +@@ -41,6 +90,7 @@ + /* for MinGW32 compiler need to include */ + #ifdef __GNUC__ + #include ++#include + #else + + /* define some standard types missing on Windows. */ +@@ -57,7 +107,7 @@ typedef int bool; + #define true 1 + #endif + #ifndef false +-#define false 1 ++#define false 0 + #endif + + #endif +@@ -98,19 +148,26 @@ typedef int bool; + #define assert_obj_type(type, obj) + #endif + +-#ifndef obj_type_free ++void *nobj_realloc(void *ptr, size_t osize, size_t nsize); ++ ++void *nobj_realloc(void *ptr, size_t osize, size_t nsize) { ++ (void)osize; ++ if(0 == nsize) { ++ free(ptr); ++ return NULL; ++ } ++ return realloc(ptr, nsize); ++} ++ + #define obj_type_free(type, obj) do { \ + assert_obj_type(type, obj); \ +- free((obj)); \ ++ nobj_realloc((obj), sizeof(type), 0); \ + } while(0) +-#endif + +-#ifndef obj_type_new + #define obj_type_new(type, obj) do { \ + assert_obj_type(type, obj); \ +- (obj) = malloc(sizeof(type)); \ ++ (obj) = nobj_realloc(NULL, 0, sizeof(type)); \ + } while(0) +-#endif + + typedef struct obj_type obj_type; + +@@ -120,6 +177,7 @@ typedef void (*dyn_caster_t)(void **obj, obj_type **type); + + #define OBJ_TYPE_FLAG_WEAK_REF (1<<0) + #define OBJ_TYPE_SIMPLE (1<<1) ++#define OBJ_TYPE_IMPORT (1<<2) + struct obj_type { + dyn_caster_t dcaster; /**< caster to support casting to sub-objects. */ + int32_t id; /**< type's id. */ +@@ -168,15 +226,28 @@ typedef struct obj_field { + uint32_t flags; /**< is_writable:1bit */ + } obj_field; + ++typedef enum { ++ REG_OBJECT, ++ REG_PACKAGE, ++ REG_META, ++} module_reg_type; ++ ++typedef struct reg_impl { ++ const char *if_name; ++ const void *impl; ++} reg_impl; ++ + typedef struct reg_sub_module { + obj_type *type; +- int is_package; +- const luaL_reg *pub_funcs; +- const luaL_reg *methods; +- const luaL_reg *metas; ++ module_reg_type req_type; ++ const luaL_Reg *pub_funcs; ++ const luaL_Reg *methods; ++ const luaL_Reg *metas; + const obj_base *bases; + const obj_field *fields; + const obj_const *constants; ++ const reg_impl *implements; ++ int bidirectional_consts; + } reg_sub_module; + + #define OBJ_UDATA_FLAG_OWN (1<<0) +@@ -188,15 +259,95 @@ typedef struct obj_udata { + } obj_udata; + + /* use static pointer as key to weak userdata table. */ +-static char *obj_udata_weak_ref_key = "obj_udata_weak_ref_key"; ++static char obj_udata_weak_ref_key[] = "obj_udata_weak_ref_key"; ++ ++/* use static pointer as key to module's private table. */ ++static char obj_udata_private_key[] = "obj_udata_private_key"; + + #if LUAJIT_FFI ++typedef int (*ffi_export_func_t)(void); + typedef struct ffi_export_symbol { + const char *name; +- void *sym; ++ union { ++ void *data; ++ ffi_export_func_t func; ++ } sym; + } ffi_export_symbol; + #endif + ++/* detect zmq version */ ++#define VERSION_2_0 1 ++#define VERSION_2_1 0 ++#define VERSION_2_2 0 ++#define VERSION_3_0 0 ++#define VERSION_3_2 0 ++#if defined(ZMQ_VERSION_MAJOR) ++# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 2) ++# undef VERSION_2_2 ++# define VERSION_2_2 1 ++# undef VERSION_2_1 ++# define VERSION_2_1 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 1) ++# undef VERSION_2_1 ++# define VERSION_2_1 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 3) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_2 ++# define VERSION_3_2 1 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 2) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_2 ++# define VERSION_3_2 1 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif ++#endif ++ ++/* make sure ZMQ_DONTWAIT & ZMQ_NOBLOCK are both defined. */ ++#ifndef ZMQ_DONTWAIT ++# define ZMQ_DONTWAIT ZMQ_NOBLOCK ++#endif ++#ifndef ZMQ_NOBLOCK ++# define ZMQ_NOBLOCK ZMQ_DONTWAIT ++#endif ++ ++/* make sure DEALER/ROUTER & XREQ/XREP are all defined. */ ++#ifndef ZMQ_DEALER ++# define ZMQ_DEALER ZMQ_XREQ ++#endif ++#ifndef ZMQ_ROUTER ++# define ZMQ_ROUTER ZMQ_XREP ++#endif ++#ifndef ZMQ_XREQ ++# define ZMQ_XREQ ZMQ_DEALER ++#endif ++#ifndef ZMQ_XREP ++# define ZMQ_XREP ZMQ_ROUTER ++#endif ++ ++#if VERSION_2_0 ++# define ZMQ_POLL_MSEC 1000 // zmq_poll is usec ++#elif VERSION_3_0 ++# define ZMQ_POLL_MSEC 1 // zmq_poll is msec ++# ifndef ZMQ_HWM ++# define ZMQ_HWM 1 // backwards compatibility ++# endif ++#endif ++ ++ + + typedef int ZMQ_Error; + +@@ -204,29 +355,329 @@ static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err); + + + static obj_type obj_types[] = { +-#define obj_type_id_zmq_msg_t 0 ++#define obj_type_id_ZErrors 0 ++#define obj_type_ZErrors (obj_types[obj_type_id_ZErrors]) ++ { NULL, 0, OBJ_TYPE_FLAG_WEAK_REF, "ZErrors" }, ++#define obj_type_id_zmq_msg_t 1 + #define obj_type_zmq_msg_t (obj_types[obj_type_id_zmq_msg_t]) +- { NULL, 0, OBJ_TYPE_SIMPLE, "zmq_msg_t" }, +-#define obj_type_id_ZMQ_Socket 1 ++ { NULL, 1, OBJ_TYPE_SIMPLE, "zmq_msg_t" }, ++#define obj_type_id_ZMQ_Socket 2 + #define obj_type_ZMQ_Socket (obj_types[obj_type_id_ZMQ_Socket]) +- { NULL, 1, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Socket" }, +-#define obj_type_id_ZMQ_Poller 2 ++ { NULL, 2, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Socket" }, ++#define obj_type_id_ZMQ_Poller 3 + #define obj_type_ZMQ_Poller (obj_types[obj_type_id_ZMQ_Poller]) +- { NULL, 2, OBJ_TYPE_SIMPLE, "ZMQ_Poller" }, +-#define obj_type_id_ZMQ_Ctx 3 ++ { NULL, 3, OBJ_TYPE_SIMPLE, "ZMQ_Poller" }, ++#define obj_type_id_ZMQ_Ctx 4 + #define obj_type_ZMQ_Ctx (obj_types[obj_type_id_ZMQ_Ctx]) +- { NULL, 3, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Ctx" }, +-#define obj_type_id_ZMQ_StopWatch 4 ++ { NULL, 4, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_Ctx" }, ++#define obj_type_id_ZMQ_StopWatch 5 + #define obj_type_ZMQ_StopWatch (obj_types[obj_type_id_ZMQ_StopWatch]) +- { NULL, 4, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_StopWatch" }, ++ { NULL, 5, OBJ_TYPE_FLAG_WEAK_REF, "ZMQ_StopWatch" }, + {NULL, -1, 0, NULL}, + }; + + ++#if LUAJIT_FFI ++ ++/* nobj_ffi_support_enabled_hint should be set to 1 when FFI support is enabled in at-least one ++ * instance of a LuaJIT state. It should never be set back to 0. */ ++static int nobj_ffi_support_enabled_hint = 0; ++static const char nobj_ffi_support_key[] = "LuaNativeObject_FFI_SUPPORT"; ++static const char nobj_check_ffi_support_code[] = ++"local stat, ffi=pcall(require,\"ffi\")\n" /* try loading LuaJIT`s FFI module. */ ++"if not stat then return false end\n" ++"return true\n"; ++ ++static int nobj_check_ffi_support(lua_State *L) { ++ int rc; ++ int err; ++ ++ /* check if ffi test has already been done. */ ++ lua_pushstring(L, nobj_ffi_support_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); ++ if(!lua_isnil(L, -1)) { ++ rc = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ /* use results of previous check. */ ++ goto finished; ++ } ++ lua_pop(L, 1); /* pop nil. */ ++ ++ err = luaL_loadbuffer(L, nobj_check_ffi_support_code, ++ sizeof(nobj_check_ffi_support_code) - 1, nobj_ffi_support_key); ++ if(0 == err) { ++ err = lua_pcall(L, 0, 1, 0); ++ } ++ if(err) { ++ const char *msg = ""; ++ if(lua_isstring(L, -1)) { ++ msg = lua_tostring(L, -1); ++ } ++ printf("Error when checking for FFI-support: %s\n", msg); ++ lua_pop(L, 1); /* pop error message. */ ++ return 0; ++ } ++ /* check results of test. */ ++ rc = lua_toboolean(L, -1); ++ lua_pop(L, 1); /* pop results. */ ++ /* cache results. */ ++ lua_pushstring(L, nobj_ffi_support_key); ++ lua_pushboolean(L, rc); ++ lua_rawset(L, LUA_REGISTRYINDEX); ++ ++finished: ++ /* turn-on hint that there is FFI code enabled. */ ++ if(rc) { ++ nobj_ffi_support_enabled_hint = 1; ++ } ++ ++ return rc; ++} ++ ++typedef struct { ++ const char **ffi_init_code; ++ int offset; ++} nobj_reader_state; ++ ++static const char *nobj_lua_Reader(lua_State *L, void *data, size_t *size) { ++ nobj_reader_state *state = (nobj_reader_state *)data; ++ const char *ptr; ++ ++ (void)L; ++ ptr = state->ffi_init_code[state->offset]; ++ if(ptr != NULL) { ++ *size = strlen(ptr); ++ state->offset++; ++ } else { ++ *size = 0; ++ } ++ return ptr; ++} ++ ++static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, ++ const char *ffi_init_code[], const ffi_export_symbol *ffi_exports, int priv_table) ++{ ++ nobj_reader_state state = { ffi_init_code, 0 }; ++ int err; ++ ++ /* export symbols to priv_table. */ ++ while(ffi_exports->name != NULL) { ++ lua_pushstring(L, ffi_exports->name); ++ lua_pushlightuserdata(L, ffi_exports->sym.data); ++ lua_settable(L, priv_table); ++ ffi_exports++; ++ } ++ err = lua_load_no_mode(L, nobj_lua_Reader, &state, ffi_mod_name); ++ if(0 == err) { ++ lua_pushvalue(L, -2); /* dup C module's table. */ ++ lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ ++ lua_remove(L, priv_table); ++ lua_pushvalue(L, LUA_REGISTRYINDEX); ++ err = lua_pcall(L, 3, 0, 0); ++ } ++ if(err) { ++ const char *msg = ""; ++ if(lua_isstring(L, -1)) { ++ msg = lua_tostring(L, -1); ++ } ++ printf("Failed to install FFI-based bindings: %s\n", msg); ++ lua_pop(L, 1); /* pop error message. */ ++ } ++ return err; ++} ++#endif ++ ++ ++typedef struct { ++ void *impl; ++ void *obj; ++} obj_implement; ++ ++static FUNC_UNUSED void *obj_implement_luaoptional(lua_State *L, int _index, void **impl, char *if_name) { ++ void *ud; ++ if(lua_isnoneornil(L, _index)) { ++ return NULL; ++ } ++ /* get the implements table for this interface. */ ++ lua_pushlightuserdata(L, if_name); ++ lua_rawget(L, LUA_REGISTRYINDEX); ++ ++ /* get pointer to userdata value & check if it is a userdata value. */ ++ ud = (obj_implement *)lua_touserdata(L, _index); ++ if(ud != NULL) { ++ /* get the userdata's metatable */ ++ if(lua_getmetatable(L, _index)) { ++ /* lookup metatable in interface table for this object's implementation of the interface. */ ++ lua_gettable(L, -2); ++ } else { ++ /* no metatable. */ ++ goto no_interface; ++ } ++#if LUAJIT_FFI ++ } else if(nobj_ffi_support_enabled_hint) { /* handle cdata. */ ++ /* get cdata interface check function from interface table. */ ++ lua_getfield(L, -1, "cdata"); ++ if(lua_isfunction(L, -1)) { ++ /* pass cdata to function, return value should be an implmentation. */ ++ lua_pushvalue(L, _index); ++ lua_call(L, 1, 1); ++ /* get pointer to cdata. */ ++ ud = (void *)lua_topointer(L, _index); ++ } else { ++ lua_pop(L, 1); /* pop non-function. */ ++ goto no_interface; ++ } ++#endif ++ } else { ++ goto no_interface; ++ } ++ ++ if(!lua_isnil(L, -1)) { ++ *impl = lua_touserdata(L, -1); ++ lua_pop(L, 2); /* pop interface table & implementation. */ ++ /* object implements interface. */ ++ return ud; ++ } else { ++ lua_pop(L, 1); /* pop nil. */ ++ } ++no_interface: ++ lua_pop(L, 1); /* pop interface table. */ ++ return NULL; ++} ++ ++static FUNC_UNUSED void *obj_implement_luacheck(lua_State *L, int _index, void **impl, char *type) { ++ void *ud = obj_implement_luaoptional(L, _index, impl, type); ++ if(ud == NULL) { ++#define ERROR_BUFFER_SIZE 256 ++ char buf[ERROR_BUFFER_SIZE]; ++ snprintf(buf, ERROR_BUFFER_SIZE-1,"Expected object with %s interface", type); ++ /* value doesn't implement this interface. */ ++ luaL_argerror(L, _index, buf); ++ } ++ return ud; ++} ++ ++/* use static pointer as key to interfaces table. (version 1.0) */ ++static char obj_interfaces_table_key[] = "obj_interfaces<1.0>_table_key"; ++ ++static void obj_get_global_interfaces_table(lua_State *L) { ++ /* get global interfaces table. */ ++ lua_getfield(L, LUA_REGISTRYINDEX, obj_interfaces_table_key); ++ if(lua_isnil(L, -1)) { ++ /* Need to create global interfaces table. */ ++ lua_pop(L, 1); /* pop nil */ ++ lua_createtable(L, 0, 4); /* 0 size array part, small hash part. */ ++ lua_pushvalue(L, -1); /* dup table. */ ++ /* store interfaces table in Lua registery. */ ++ lua_setfield(L, LUA_REGISTRYINDEX, obj_interfaces_table_key); ++ } ++} ++ ++static void obj_get_interface(lua_State *L, const char *name, int global_if_tab) { ++ /* get a interface's implementation table */ ++ lua_getfield(L, global_if_tab, name); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil */ ++ /* new interface. (i.e. no object implement it yet.) ++ * ++ * create an empty table for this interface that will be used when an ++ * implementation is registered for this interface. ++ */ ++ lua_createtable(L, 0, 2); /* 0 size array part, small hash part. */ ++ lua_pushvalue(L, -1); /* dup table. */ ++ lua_setfield(L, global_if_tab, name); /* store interface in global interfaces table. */ ++ } ++} ++ ++static int obj_get_userdata_interface(lua_State *L) { ++ /* get the userdata's metatable */ ++ if(lua_getmetatable(L, 2)) { ++ /* lookup metatable in interface table for the userdata's implementation of the interface. */ ++ lua_gettable(L, 1); ++ if(!lua_isnil(L, -1)) { ++ /* return the implementation. */ ++ return 1; ++ } ++ } ++ /* no metatable or no implementation. */ ++ return 0; ++} ++ ++static void obj_interface_register(lua_State *L, char *name, int global_if_tab) { ++ /* get the table of implementations for this interface. */ ++ obj_get_interface(L, name, global_if_tab); ++ ++ /* check for 'userdata' function. */ ++ lua_getfield(L, -1, "userdata"); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. */ ++ /* add C function for getting a userdata's implementation. */ ++ lua_pushcfunction(L, obj_get_userdata_interface); ++ lua_setfield(L, -2, "userdata"); ++ } else { ++ /* already have function. */ ++ lua_pop(L, 1); /* pop C function. */ ++ } ++ /* we are going to use a lightuserdata pointer for fast lookup of the interface's impl. table. */ ++ lua_pushlightuserdata(L, name); ++ lua_insert(L, -2); ++ lua_settable(L, LUA_REGISTRYINDEX); ++} ++ ++static void obj_register_interfaces(lua_State *L, char *interfaces[]) { ++ int i; ++ int if_tab; ++ /* get global interfaces table. */ ++ obj_get_global_interfaces_table(L); ++ if_tab = lua_gettop(L); ++ ++ for(i = 0; interfaces[i] != NULL ; i++) { ++ obj_interface_register(L, interfaces[i], if_tab); ++ } ++ lua_pop(L, 1); /* pop global interfaces table. */ ++} ++ ++static void obj_type_register_implement(lua_State *L, const reg_impl *impl, int global_if_tab, int mt_tab) { ++ /* get the table of implementations for this interface. */ ++ obj_get_interface(L, impl->if_name, global_if_tab); ++ ++ /* register object's implement in the interface table. */ ++ lua_pushvalue(L, mt_tab); ++ lua_pushlightuserdata(L, (void *)impl->impl); ++ lua_settable(L, -3); ++ ++ lua_pop(L, 1); /* pop inteface table. */ ++} ++ ++static void obj_type_register_implements(lua_State *L, const reg_impl *impls) { ++ int if_tab; ++ int mt_tab; ++ /* get absolute position of object's metatable. */ ++ mt_tab = lua_gettop(L); ++ /* get global interfaces table. */ ++ obj_get_global_interfaces_table(L); ++ if_tab = lua_gettop(L); ++ ++ for(; impls->if_name != NULL ; impls++) { ++ obj_type_register_implement(L, impls, if_tab, mt_tab); ++ } ++ lua_pop(L, 1); /* pop global interfaces table. */ ++} ++ + #ifndef REG_PACKAGE_IS_CONSTRUCTOR + #define REG_PACKAGE_IS_CONSTRUCTOR 1 + #endif + ++#ifndef REG_MODULES_AS_GLOBALS ++#define REG_MODULES_AS_GLOBALS 0 ++#endif ++ ++/* For Lua 5.2 don't register modules as globals. */ ++#if LUA_VERSION_NUM == 502 ++#undef REG_MODULES_AS_GLOBALS ++#define REG_MODULES_AS_GLOBALS 0 ++#endif ++ + #ifndef REG_OBJECTS_AS_GLOBALS + #define REG_OBJECTS_AS_GLOBALS 0 + #endif +@@ -235,6 +686,48 @@ static obj_type obj_types[] = { + #define OBJ_DATA_HIDDEN_METATABLE 1 + #endif + ++static FUNC_UNUSED int obj_import_external_type(lua_State *L, obj_type *type) { ++ /* find the external type's metatable using it's name. */ ++ lua_pushstring(L, type->name); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* external type's metatable. */ ++ if(!lua_isnil(L, -1)) { ++ /* found it. Now we will map our 'type' pointer to the metatable. */ ++ /* REGISTERY[lightuserdata] = REGISTERY[type->name] */ ++ lua_pushlightuserdata(L, type); /* use our 'type' pointer as lookup key. */ ++ lua_pushvalue(L, -2); /* dup. type's metatable. */ ++ lua_rawset(L, LUA_REGISTRYINDEX); /* save external type's metatable. */ ++ /* NOTE: top of Lua stack still has the type's metatable. */ ++ return 1; ++ } else { ++ lua_pop(L, 1); /* pop nil. */ ++ } ++ return 0; ++} ++ ++static FUNC_UNUSED int obj_import_external_ffi_type(lua_State *L, obj_type *type) { ++ /* find the external type's metatable using it's name. */ ++ lua_pushstring(L, type->name); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* external type's metatable. */ ++ if(!lua_isnil(L, -1)) { ++ /* found it. Now we will map our 'type' pointer to the C check function. */ ++ /* _priv_table[lightuserdata] = REGISTERY[type->name].c_check */ ++ lua_getfield(L, -1, "c_check"); ++ lua_remove(L, -2); /* remove metatable. */ ++ if(lua_isfunction(L, -1)) { ++ lua_pushlightuserdata(L, type); /* use our 'type' pointer as lookup key. */ ++ lua_pushvalue(L, -2); /* dup. check function */ ++ lua_rawset(L, -4); /* save check function to module's private table. */ ++ /* NOTE: top of Lua stack still has the type's C check function. */ ++ return 1; ++ } else { ++ lua_pop(L, 1); /* pop non function value. */ ++ } ++ } else { ++ lua_pop(L, 1); /* pop nil. */ ++ } ++ return 0; ++} ++ + static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) { + obj_udata *ud; + size_t len; +@@ -245,7 +738,7 @@ static FUNC_UNUSED obj_udata *obj_udata_toobj(lua_State *L, int _index) { + luaL_typerror(L, _index, "userdata"); /* is not a userdata value. */ + } + /* verify userdata size. */ +- len = lua_objlen(L, _index); ++ len = lua_rawlen(L, _index); + if(len != sizeof(obj_udata)) { + /* This shouldn't be possible */ + luaL_error(L, "invalid userdata size: size=%d, expected=%d", len, sizeof(obj_udata)); +@@ -258,10 +751,23 @@ static FUNC_UNUSED int obj_udata_is_compatible(lua_State *L, obj_udata *ud, void + obj_type *ud_type; + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++recheck_metatable: + if(lua_rawequal(L, -1, -2)) { + *obj = ud->obj; + /* same type no casting needed. */ + return 1; ++ } else if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. */ ++ if((type->flags & OBJ_TYPE_IMPORT) == 0) { ++ /* can't resolve internal type. */ ++ luaL_error(L, "Unknown object type(id=%d, name=%s)", type->id, type->name); ++ } ++ /* try to import external type. */ ++ if(obj_import_external_type(L, type)) { ++ /* imported type, re-try metatable check. */ ++ goto recheck_metatable; ++ } ++ /* External type not yet available, so the object can't be compatible. */ + } else { + /* Different types see if we can cast to the required type. */ + lua_rawgeti(L, -2, type->id); +@@ -314,6 +820,39 @@ static FUNC_UNUSED obj_udata *obj_udata_luacheck_internal(lua_State *L, int _ind + return ud; + } + } ++ } else if(!lua_isnoneornil(L, _index)) { ++ /* handle cdata. */ ++ /* get private table. */ ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ ++ /* get cdata type check function from private table. */ ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, -2); ++ ++ /* check for function. */ ++ if(!lua_isnil(L, -1)) { ++got_check_func: ++ /* pass cdata value to type checking function. */ ++ lua_pushvalue(L, _index); ++ lua_call(L, 1, 1); ++ if(!lua_isnil(L, -1)) { ++ /* valid type get pointer from cdata. */ ++ lua_pop(L, 2); ++ *obj = *(void **)lua_topointer(L, _index); ++ return ud; ++ } ++ lua_pop(L, 2); ++ } else { ++ lua_pop(L, 1); /* pop nil. */ ++ if(type->flags & OBJ_TYPE_IMPORT) { ++ /* try to import external ffi type. */ ++ if(obj_import_external_ffi_type(L, type)) { ++ /* imported type. */ ++ goto got_check_func; ++ } ++ /* External type not yet available, so the object can't be compatible. */ ++ } ++ } + } + if(not_delete) { + luaL_typerror(L, _index, type->name); /* is not a userdata value. */ +@@ -327,6 +866,15 @@ static FUNC_UNUSED void *obj_udata_luacheck(lua_State *L, int _index, obj_type * + return obj; + } + ++static FUNC_UNUSED void *obj_udata_luaoptional(lua_State *L, int _index, obj_type *type) { ++ void *obj = NULL; ++ if(lua_isnoneornil(L, _index)) { ++ return obj; ++ } ++ obj_udata_luacheck_internal(L, _index, &(obj), type, 1); ++ return obj; ++} ++ + static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { + void *obj; + obj_udata *ud = obj_udata_luacheck_internal(L, _index, &(obj), type, 0); +@@ -335,6 +883,9 @@ static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type + /* null userdata. */ + ud->obj = NULL; + ud->flags = 0; ++ /* clear the metatable in invalidate userdata. */ ++ lua_pushnil(L); ++ lua_setmetatable(L, _index); + return obj; + } + +@@ -345,6 +896,17 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ + lua_pushnil(L); + return; + } ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_pushinteger(L, flags); ++ lua_call(L, 2, 1); ++ return; ++ } ++#endif + /* check for type caster. */ + if(type->dcaster) { + (type->dcaster)(&obj, &type); +@@ -354,8 +916,12 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ + ud->obj = obj; + ud->flags = flags; + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + } + +@@ -367,6 +933,9 @@ static FUNC_UNUSED void *obj_udata_luadelete_weak(lua_State *L, int _index, obj_ + /* null userdata. */ + ud->obj = NULL; + ud->flags = 0; ++ /* clear the metatable in invalidate userdata. */ ++ lua_pushnil(L); ++ lua_setmetatable(L, _index); + /* get objects weak table. */ + lua_pushlightuserdata(L, obj_udata_weak_ref_key); + lua_rawget(L, LUA_REGISTRYINDEX); /* weak ref table. */ +@@ -401,6 +970,18 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type + } + lua_pop(L, 1); /* pop nil. */ + ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ lua_remove(L, -2); ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_pushinteger(L, flags); ++ lua_call(L, 2, 1); ++ return; ++ } ++#endif + /* create new userdata. */ + ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata)); + +@@ -408,8 +989,12 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type + ud->obj = obj; + ud->flags = flags; + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + + /* add weak reference to object. */ +@@ -468,9 +1053,53 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob + if(lua_getmetatable(L, _index)) { + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++recheck_metatable: + if(lua_rawequal(L, -1, -2)) { + lua_pop(L, 2); /* pop both metatables. */ + return ud; ++ } else if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. */ ++ if((type->flags & OBJ_TYPE_IMPORT) == 0) { ++ /* can't resolve internal type. */ ++ luaL_error(L, "Unknown object type(id=%d, name=%s)", type->id, type->name); ++ } ++ /* try to import external type. */ ++ if(obj_import_external_type(L, type)) { ++ /* imported type, re-try metatable check. */ ++ goto recheck_metatable; ++ } ++ /* External type not yet available, so the object can't be compatible. */ ++ return 0; ++ } ++ } ++ } else if(!lua_isnoneornil(L, _index)) { ++ /* handle cdata. */ ++ /* get private table. */ ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */ ++ /* get cdata type check function from private table. */ ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, -2); ++ ++ /* check for function. */ ++ if(!lua_isnil(L, -1)) { ++got_check_func: ++ /* pass cdata value to type checking function. */ ++ lua_pushvalue(L, _index); ++ lua_call(L, 1, 1); ++ if(!lua_isnil(L, -1)) { ++ /* valid type get pointer from cdata. */ ++ lua_pop(L, 2); ++ return (void *)lua_topointer(L, _index); ++ } ++ } else { ++ if(type->flags & OBJ_TYPE_IMPORT) { ++ /* try to import external ffi type. */ ++ if(obj_import_external_ffi_type(L, type)) { ++ /* imported type. */ ++ goto got_check_func; ++ } ++ /* External type not yet available, so the object can't be compatible. */ + } + } + } +@@ -478,10 +1107,16 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob + return NULL; + } + +-static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) { ++static FUNC_UNUSED void * obj_simple_udata_luaoptional(lua_State *L, int _index, obj_type *type) { ++ if(lua_isnoneornil(L, _index)) { ++ return NULL; ++ } ++ return obj_simple_udata_luacheck(L, _index, type); ++} ++ ++static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type) { + void *obj; + obj = obj_simple_udata_luacheck(L, _index, type); +- *flags = OBJ_UDATA_FLAG_OWN; + /* clear the metatable to invalidate userdata. */ + lua_pushnil(L); + lua_setmetatable(L, _index); +@@ -490,12 +1125,27 @@ static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, o + + static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type) + { ++ void *ud; ++#if LUAJIT_FFI ++ lua_pushlightuserdata(L, type); ++ lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++ if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) { ++ /* call special FFI "void *" to FFI object convertion function. */ ++ lua_pushlightuserdata(L, obj); ++ lua_call(L, 1, 1); ++ return obj; ++ } ++#endif + /* create new userdata. */ +- void *ud = lua_newuserdata(L, size); ++ ud = lua_newuserdata(L, size); + memcpy(ud, obj, size); + /* get obj_type metatable. */ ++#if LUAJIT_FFI ++ lua_insert(L, -2); /* move userdata below metatable. */ ++#else + lua_pushlightuserdata(L, type); + lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */ ++#endif + lua_setmetatable(L, -2); + + return ud; +@@ -504,9 +1154,9 @@ static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int s + /* default simple object equal method. */ + static FUNC_UNUSED int obj_simple_udata_default_equal(lua_State *L) { + void *ud1 = obj_simple_udata_toobj(L, 1); +- size_t len1 = lua_objlen(L, 1); ++ size_t len1 = lua_rawlen(L, 1); + void *ud2 = obj_simple_udata_toobj(L, 2); +- size_t len2 = lua_objlen(L, 2); ++ size_t len2 = lua_rawlen(L, 2); + + if(len1 == len2) { + lua_pushboolean(L, (memcmp(ud1, ud2, len1) == 0)); +@@ -544,7 +1194,8 @@ static int obj_constructor_call_wrapper(lua_State *L) { + return lua_gettop(L); + } + +-static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx) { ++static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx, ++ int bidirectional) { + /* register constants. */ + while(constants->name != NULL) { + lua_pushstring(L, constants->name); +@@ -562,40 +1213,84 @@ static void obj_type_register_constants(lua_State *L, const obj_const *constants + lua_pushnil(L); + break; + } ++ /* map values back to keys. */ ++ if(bidirectional) { ++ /* check if value already exists. */ ++ lua_pushvalue(L, -1); ++ lua_rawget(L, tab_idx - 3); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); ++ /* add value->key mapping. */ ++ lua_pushvalue(L, -1); ++ lua_pushvalue(L, -3); ++ lua_rawset(L, tab_idx - 4); ++ } else { ++ /* value already exists. */ ++ lua_pop(L, 1); ++ } ++ } + lua_rawset(L, tab_idx - 2); + constants++; + } + } + + static void obj_type_register_package(lua_State *L, const reg_sub_module *type_reg) { +- const luaL_reg *reg_list = type_reg->pub_funcs; ++ const luaL_Reg *reg_list = type_reg->pub_funcs; + + /* create public functions table. */ + if(reg_list != NULL && reg_list[0].name != NULL) { + /* register functions */ +- luaL_register(L, NULL, reg_list); ++ luaL_setfuncs(L, reg_list, 0); + } + +- obj_type_register_constants(L, type_reg->constants, -1); ++ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); + + lua_pop(L, 1); /* drop package table */ + } + ++static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) { ++ const luaL_Reg *reg_list; ++ ++ /* create public functions table. */ ++ reg_list = type_reg->pub_funcs; ++ if(reg_list != NULL && reg_list[0].name != NULL) { ++ /* register functions */ ++ luaL_setfuncs(L, reg_list, 0); ++ } ++ ++ obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts); ++ ++ /* register methods. */ ++ luaL_setfuncs(L, type_reg->methods, 0); ++ ++ /* create metatable table. */ ++ lua_newtable(L); ++ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ ++ /* setmetatable on meta-object. */ ++ lua_setmetatable(L, -2); ++ ++ lua_pop(L, 1); /* drop meta-object */ ++} ++ + static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) { +- const luaL_reg *reg_list; ++ const luaL_Reg *reg_list; + obj_type *type = type_reg->type; + const obj_base *base = type_reg->bases; + +- if(type_reg->is_package == 1) { ++ if(type_reg->req_type == REG_PACKAGE) { + obj_type_register_package(L, type_reg); + return; + } ++ if(type_reg->req_type == REG_META) { ++ obj_type_register_meta(L, type_reg); ++ return; ++ } + + /* create public functions table. */ + reg_list = type_reg->pub_funcs; + if(reg_list != NULL && reg_list[0].name != NULL) { + /* register "constructors" as to object's public API */ +- luaL_register(L, NULL, reg_list); /* fill public API table. */ ++ luaL_setfuncs(L, reg_list, 0); /* fill public API table. */ + + /* make public API table callable as the default constructor. */ + lua_newtable(L); /* create metatable */ +@@ -625,7 +1320,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + #endif + } + +- luaL_register(L, NULL, type_reg->methods); /* fill methods table. */ ++ luaL_setfuncs(L, type_reg->methods, 0); /* fill methods table. */ + + luaL_newmetatable(L, type->name); /* create metatable */ + lua_pushliteral(L, ".name"); +@@ -638,16 +1333,12 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + lua_pushvalue(L, -2); /* dup metatable. */ + lua_rawset(L, LUA_REGISTRYINDEX); /* REGISTRY[type] = metatable */ + +-#if LUAJIT_FFI + /* add metatable to 'priv_table' */ + lua_pushstring(L, type->name); + lua_pushvalue(L, -2); /* dup metatable. */ + lua_rawset(L, priv_table); /* priv_table[""] = metatable */ +-#else +- (void)priv_table; +-#endif + +- luaL_register(L, NULL, type_reg->metas); /* fill metatable */ ++ luaL_setfuncs(L, type_reg->metas, 0); /* fill metatable */ + + /* add obj_bases to metatable. */ + while(base->id >= 0) { +@@ -656,7 +1347,9 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int + base++; + } + +- obj_type_register_constants(L, type_reg->constants, -2); ++ obj_type_register_constants(L, type_reg->constants, -2, type_reg->bidirectional_consts); ++ ++ obj_type_register_implements(L, type_reg->implements); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -3); /* dup methods table */ +@@ -676,62 +1369,193 @@ static FUNC_UNUSED int lua_checktype_ref(lua_State *L, int _index, int _type) { + return luaL_ref(L, LUA_REGISTRYINDEX); + } + +-#if LUAJIT_FFI +-static int nobj_udata_new_ffi(lua_State *L) { +- size_t size = luaL_checkinteger(L, 1); +- void *ud; +- luaL_checktype(L, 2, LUA_TTABLE); +- lua_settop(L, 2); +- /* create userdata. */ +- ud = lua_newuserdata(L, size); +- lua_replace(L, 1); +- /* set userdata's metatable. */ +- lua_setmetatable(L, 1); +- return 1; +-} ++/* use static pointer as key to weak callback_state table. */ ++static char obj_callback_state_weak_ref_key[] = "obj_callback_state_weak_ref_key"; + +-static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, +- const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table) +-{ +- int err; ++static FUNC_UNUSED void *nobj_get_callback_state(lua_State *L, int owner_idx, int size) { ++ void *cb_state; + +- /* export symbols to priv_table. */ +- while(ffi_exports->name != NULL) { +- lua_pushstring(L, ffi_exports->name); +- lua_pushlightuserdata(L, ffi_exports->sym); +- lua_settable(L, priv_table); +- ffi_exports++; ++ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ ++ lua_rawget(L, LUA_REGISTRYINDEX); /* check if weak table exists already. */ ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. */ ++ /* create weak table for callback_state */ ++ lua_newtable(L); /* weak table. */ ++ lua_newtable(L); /* metatable for weak table. */ ++ lua_pushliteral(L, "__mode"); ++ lua_pushliteral(L, "k"); ++ lua_rawset(L, -3); /* metatable.__mode = 'k' weak keys. */ ++ lua_setmetatable(L, -2); /* add metatable to weak table. */ ++ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ ++ lua_pushvalue(L, -2); /* dup weak table. */ ++ lua_rawset(L, LUA_REGISTRYINDEX); /* add weak table to registry. */ + } +- err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name); +- if(0 == err) { +- lua_pushvalue(L, -2); /* dup C module's table. */ +- lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */ +- lua_remove(L, priv_table); +- lua_pushcfunction(L, nobj_udata_new_ffi); +- err = lua_pcall(L, 3, 0, 0); ++ ++ /* check weak table for callback_state. */ ++ lua_pushvalue(L, owner_idx); /* dup. owner as lookup key. */ ++ lua_rawget(L, -2); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. */ ++ lua_pushvalue(L, owner_idx); /* dup. owner as lookup key. */ ++ /* create new callback state. */ ++ cb_state = lua_newuserdata(L, size); ++ lua_rawset(L, -3); ++ lua_pop(L, 1); /* pop */ ++ } else { ++ /* got existing callback state. */ ++ cb_state = lua_touserdata(L, -1); ++ lua_pop(L, 2); /* pop , */ + } +- if(err) { +- const char *msg = ""; +- if(lua_isstring(L, -1)) { +- msg = lua_tostring(L, -1); +- } +- printf("Failed to install FFI-based bindings: %s\n", msg); +- lua_pop(L, 1); /* pop error message. */ ++ ++ return cb_state; ++} ++ ++static FUNC_UNUSED void *nobj_delete_callback_state(lua_State *L, int owner_idx) { ++ void *cb_state = NULL; ++ ++ lua_pushlightuserdata(L, obj_callback_state_weak_ref_key); /* key for weak table. */ ++ lua_rawget(L, LUA_REGISTRYINDEX); /* check if weak table exists already. */ ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop nil. no weak table, so there is no callback state. */ ++ return NULL; + } +- return err; ++ /* get callback state. */ ++ lua_pushvalue(L, owner_idx); /* dup. owner */ ++ lua_rawget(L, -2); ++ if(lua_isnil(L, -1)) { ++ lua_pop(L, 2); /* pop , nil. No callback state for the owner. */ ++ } else { ++ cb_state = lua_touserdata(L, -1); ++ lua_pop(L, 1); /* pop */ ++ /* remove callback state. */ ++ lua_pushvalue(L, owner_idx); /* dup. owner */ ++ lua_pushnil(L); ++ lua_rawset(L, -3); ++ lua_pop(L, 1); /* pop */ ++ } ++ ++ return cb_state; + } +-#endif ++ ++ ++ ++ ++ ++typedef struct Buffer_if { ++ const uint8_t * (* const const_data)(void *this_v); ++ size_t (* const get_size)(void *this_v); ++} BufferIF; ++ ++/* a per-module unique pointer for fast lookup of an interface's implementation table. */ ++static char obj_interface_BufferIF[] = "BufferIF"; ++ ++#define BufferIF_VAR(var_name) \ ++ BufferIF *var_name ## _if; \ ++ void *var_name; ++ ++#define BufferIF_LUA_OPTIONAL(L, _index, var_name) \ ++ var_name = obj_implement_luaoptional(L, _index, (void **)&(var_name ## _if), \ ++ obj_interface_BufferIF) ++ ++#define BufferIF_LUA_CHECK(L, _index, var_name) \ ++ var_name = obj_implement_luacheck(L, _index, (void **)&(var_name ## _if), \ ++ obj_interface_BufferIF) ++ ++ ++ ++ ++ ++ ++typedef struct MutableBuffer_if { ++ uint8_t * (* const data)(void *this_v); ++ size_t (* const get_size)(void *this_v); ++} MutableBufferIF; ++ ++/* a per-module unique pointer for fast lookup of an interface's implementation table. */ ++static char obj_interface_MutableBufferIF[] = "MutableBufferIF"; ++ ++#define MutableBufferIF_VAR(var_name) \ ++ MutableBufferIF *var_name ## _if; \ ++ void *var_name; ++ ++#define MutableBufferIF_LUA_OPTIONAL(L, _index, var_name) \ ++ var_name = obj_implement_luaoptional(L, _index, (void **)&(var_name ## _if), \ ++ obj_interface_MutableBufferIF) ++ ++#define MutableBufferIF_LUA_CHECK(L, _index, var_name) \ ++ var_name = obj_implement_luacheck(L, _index, (void **)&(var_name ## _if), \ ++ obj_interface_MutableBufferIF) ++ ++ ++ ++ ++static char *obj_interfaces[] = { ++ obj_interface_BufferIF, ++ obj_interface_MutableBufferIF, ++ NULL, ++}; ++ ++/** ++ * zmq_msg_t implements Buffer interface ++ */ ++/** ++ * Buffer interface method const_data ++ */ ++static const uint8_t * zmq_msg_t_Buffer_const_data(void *this_v) { ++ zmq_msg_t * this_p = this_v; ++ return zmq_msg_data(this_p); ++} ++/** ++ * Buffer interface method get_size ++ */ ++static size_t zmq_msg_t_Buffer_get_size(void *this_v) { ++ zmq_msg_t * this_p = this_v; ++ return zmq_msg_size(this_p); ++} ++ ++static const BufferIF zmq_msg_t_Buffer = { ++ zmq_msg_t_Buffer_const_data, ++ zmq_msg_t_Buffer_get_size ++}; ++ ++/** ++ * zmq_msg_t implements MutableBuffer interface ++ */ ++/** ++ * MutableBuffer interface method data ++ */ ++static uint8_t * zmq_msg_t_MutableBuffer_data(void *this_v) { ++ zmq_msg_t * this_p = this_v; ++ return zmq_msg_data(this_p); ++} ++/** ++ * MutableBuffer interface method get_size ++ */ ++static size_t zmq_msg_t_MutableBuffer_get_size(void *this_v) { ++ zmq_msg_t * this_p = this_v; ++ return zmq_msg_size(this_p); ++} ++ ++static const MutableBufferIF zmq_msg_t_MutableBuffer = { ++ zmq_msg_t_MutableBuffer_data, ++ zmq_msg_t_MutableBuffer_get_size ++}; ++ + + + #define obj_type_zmq_msg_t_check(L, _index) \ + (zmq_msg_t *)obj_simple_udata_luacheck(L, _index, &(obj_type_zmq_msg_t)) +-#define obj_type_zmq_msg_t_delete(L, _index, flags) \ +- (zmq_msg_t *)obj_simple_udata_luadelete(L, _index, &(obj_type_zmq_msg_t), flags) +-#define obj_type_zmq_msg_t_push(L, obj, flags) \ ++#define obj_type_zmq_msg_t_optional(L, _index) \ ++ (zmq_msg_t *)obj_simple_udata_luaoptional(L, _index, &(obj_type_zmq_msg_t)) ++#define obj_type_zmq_msg_t_delete(L, _index) \ ++ (zmq_msg_t *)obj_simple_udata_luadelete(L, _index, &(obj_type_zmq_msg_t)) ++#define obj_type_zmq_msg_t_push(L, obj) \ + obj_simple_udata_luapush(L, obj, sizeof(zmq_msg_t), &(obj_type_zmq_msg_t)) + + #define obj_type_ZMQ_Socket_check(L, _index) \ + obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Socket)) ++#define obj_type_ZMQ_Socket_optional(L, _index) \ ++ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_Socket)) + #define obj_type_ZMQ_Socket_delete(L, _index, flags) \ + obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_Socket), flags) + #define obj_type_ZMQ_Socket_push(L, obj, flags) \ +@@ -739,13 +1563,17 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + + #define obj_type_ZMQ_Poller_check(L, _index) \ + (ZMQ_Poller *)obj_simple_udata_luacheck(L, _index, &(obj_type_ZMQ_Poller)) +-#define obj_type_ZMQ_Poller_delete(L, _index, flags) \ +- (ZMQ_Poller *)obj_simple_udata_luadelete(L, _index, &(obj_type_ZMQ_Poller), flags) +-#define obj_type_ZMQ_Poller_push(L, obj, flags) \ ++#define obj_type_ZMQ_Poller_optional(L, _index) \ ++ (ZMQ_Poller *)obj_simple_udata_luaoptional(L, _index, &(obj_type_ZMQ_Poller)) ++#define obj_type_ZMQ_Poller_delete(L, _index) \ ++ (ZMQ_Poller *)obj_simple_udata_luadelete(L, _index, &(obj_type_ZMQ_Poller)) ++#define obj_type_ZMQ_Poller_push(L, obj) \ + obj_simple_udata_luapush(L, obj, sizeof(ZMQ_Poller), &(obj_type_ZMQ_Poller)) + + #define obj_type_ZMQ_Ctx_check(L, _index) \ + obj_udata_luacheck(L, _index, &(obj_type_ZMQ_Ctx)) ++#define obj_type_ZMQ_Ctx_optional(L, _index) \ ++ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_Ctx)) + #define obj_type_ZMQ_Ctx_delete(L, _index, flags) \ + obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_Ctx), flags) + #define obj_type_ZMQ_Ctx_push(L, obj, flags) \ +@@ -753,6 +1581,8 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + + #define obj_type_ZMQ_StopWatch_check(L, _index) \ + obj_udata_luacheck(L, _index, &(obj_type_ZMQ_StopWatch)) ++#define obj_type_ZMQ_StopWatch_optional(L, _index) \ ++ obj_udata_luaoptional(L, _index, &(obj_type_ZMQ_StopWatch)) + #define obj_type_ZMQ_StopWatch_delete(L, _index, flags) \ + obj_udata_luadelete_weak(L, _index, &(obj_type_ZMQ_StopWatch), flags) + #define obj_type_ZMQ_StopWatch_push(L, obj, flags) \ +@@ -761,30 +1591,71 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name, + + + +-static const char zmq_ffi_lua_code[] = "local error = error\n" ++static const char *zmq_ffi_lua_code[] = { "local ffi=require\"ffi\"\n" ++"local function ffi_safe_load(name, global)\n" ++" local stat, C = pcall(ffi.load, name, global)\n" ++" if not stat then return nil, C end\n" ++" if global then return ffi.C end\n" ++" return C\n" ++"end\n" ++"local function ffi_load(name, global)\n" ++" return assert(ffi_safe_load(name, global))\n" ++"end\n" ++"\n" ++"local ffi_string = ffi.string\n" ++"\n" ++"local f_cast = ffi.cast\n" ++"local pcall = pcall\n" ++"local error = error\n" + "local type = type\n" + "local tonumber = tonumber\n" + "local tostring = tostring\n" ++"local sformat = require\"string\".format\n" + "local rawset = rawset\n" +-"\n" +-"-- try loading luajit's ffi\n" +-"local stat, ffi=pcall(require,\"ffi\")\n" +-"if not stat then\n" +-" return\n" ++"local setmetatable = setmetatable\n" ++"local package = (require\"package\") or {}\n" ++"local p_config = package.config\n" ++"local p_cpath = package.cpath\n" ++"\n" ++"\n" ++"local ffi_load_cmodule\n" ++"\n" ++"-- try to detect luvit.\n" ++"if p_config == nil and p_cpath == nil then\n" ++" ffi_load_cmodule = function(name, global)\n" ++" for path,module in pairs(package.loaded) do\n" ++" if module == name then\n" ++" local C, err = ffi_safe_load(path, global)\n" ++" -- return opened library\n" ++" if C then return C end\n" ++" end\n" ++" end\n" ++" error(\"Failed to find: \" .. name)\n" ++" end\n" ++"else\n" ++" ffi_load_cmodule = function(name, global)\n" ++" local dir_sep = p_config:sub(1,1)\n" ++" local path_sep = p_config:sub(3,3)\n" ++" local path_mark = p_config:sub(5,5)\n" ++" local path_match = \"([^\" .. path_sep .. \"]*)\" .. path_sep\n" ++" -- convert dotted name to directory path.\n" ++" name = name:gsub('%.', dir_sep)\n" ++" -- try each path in search path.\n" ++" for path in p_cpath:gmatch(path_match) do\n" ++" local fname = path:gsub(path_mark, name)\n" ++" local C, err = ffi_safe_load(fname, global)\n" ++" -- return opened library\n" ++" if C then return C end\n" ++" end\n" ++" error(\"Failed to find: \" .. name)\n" ++" end\n" + "end\n" + "\n" +-"local _M, _priv, udata_new = ...\n" +-"\n" +-"local band = bit.band\n" +-"local d_getmetatable = debug.getmetatable\n" +-"local d_setmetatable = debug.setmetatable\n" ++"local _M, _priv, reg_table = ...\n" ++"local REG_OBJECTS_AS_GLOBALS = false\n" ++"local C = ffi.C\n" + "\n" + "local OBJ_UDATA_FLAG_OWN = 1\n" +-"local OBJ_UDATA_FLAG_LOOKUP = 2\n" +-"local OBJ_UDATA_LAST_FLAG = OBJ_UDATA_FLAG_LOOKUP\n" +-"\n" +-"local OBJ_TYPE_FLAG_WEAK_REF = 1\n" +-"local OBJ_TYPE_SIMPLE = 2\n" + "\n" + "local function ffi_safe_cdef(block_name, cdefs)\n" + " local fake_type = \"struct sentinel_\" .. block_name .. \"_ty\"\n" +@@ -822,151 +1693,101 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + " uint32_t flags; /**< lua_own:1bit */\n" + "} obj_udata;\n" + "\n" +-"]])\n" +-"\n" +-"-- cache mapping of cdata to userdata\n" +-"local weak_objects = setmetatable({}, { __mode = \"v\" })\n" ++"int memcmp(const void *s1, const void *s2, size_t n);\n" + "\n" +-"local function obj_udata_luacheck_internal(obj, type_mt, not_delete)\n" +-" local obj_mt = d_getmetatable(obj)\n" +-" if obj_mt == type_mt then\n" +-" -- convert userdata to cdata.\n" +-" return ffi.cast(\"obj_udata *\", obj)\n" +-" end\n" +-" if not_delete then\n" +-" error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(obj) .. \")\", 3)\n" +-" end\n" +-"end\n" ++"]])\n" + "\n" +-"local function obj_udata_luacheck(obj, type_mt)\n" +-" local ud = obj_udata_luacheck_internal(obj, type_mt, true)\n" +-" return ud.obj\n" +-"end\n" ++"local nobj_callback_states = {}\n" ++"local nobj_weak_objects = setmetatable({}, {__mode = \"v\"})\n" ++"local nobj_obj_flags = {}\n" + "\n" +-"local function obj_udata_to_cdata(objects, ud_obj, c_type, ud_mt)\n" +-" -- convert userdata to cdata.\n" +-" local c_obj = ffi.cast(c_type, obj_udata_luacheck(ud_obj, ud_mt))\n" +-" -- cache converted cdata\n" +-" rawset(objects, ud_obj, c_obj)\n" +-" return c_obj\n" ++"local function obj_ptr_to_id(ptr)\n" ++" return tonumber(f_cast('uintptr_t', ptr))\n" + "end\n" + "\n" +-"local function obj_udata_luadelete(ud_obj, type_mt)\n" +-" local ud = obj_udata_luacheck_internal(ud_obj, type_mt, false)\n" +-" if not ud then return nil, 0 end\n" +-" local obj, flags = ud.obj, ud.flags\n" +-" -- null userdata.\n" +-" ud.obj = nil\n" +-" ud.flags = 0\n" +-" -- invalid userdata, by setting the metatable to nil.\n" +-" d_setmetatable(ud_obj, nil)\n" +-" return obj, flags\n" ++"local function obj_to_id(ptr)\n" ++" return tonumber(f_cast('uintptr_t', f_cast('void *', ptr)))\n" + "end\n" + "\n" +-"local function obj_udata_luapush(obj, type_mt, obj_type, flags)\n" +-" if obj == nil then return end\n" +-"\n" +-" -- apply type's dynamic caster.\n" +-" if obj_type.dcaster ~= nil then\n" +-" local obj_ptr = ffi.new(\"void *[1]\", obj)\n" +-" local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n" +-" obj_type.dcaster(obj_ptr, type_ptr)\n" +-" obj = obj_ptr[1]\n" +-" type = type_ptr[1]\n" ++"local function register_default_constructor(_pub, obj_name, constructor)\n" ++" local obj_pub = _pub[obj_name]\n" ++" if type(obj_pub) == 'table' then\n" ++" -- copy table since it might have a locked metatable\n" ++" local new_pub = {}\n" ++" for k,v in pairs(obj_pub) do\n" ++" new_pub[k] = v\n" ++" end\n" ++" setmetatable(new_pub, { __call = function(t,...)\n" ++" return constructor(...)\n" ++" end,\n" ++" __metatable = false,\n" ++" })\n" ++" obj_pub = new_pub\n" ++" else\n" ++" obj_pub = constructor\n" + " end\n" +-"\n" +-" -- create new userdata\n" +-" local ud_obj = udata_new(ffi.sizeof\"obj_udata\", type_mt)\n" +-" local ud = ffi.cast(\"obj_udata *\", ud_obj)\n" +-" -- init. object\n" +-" ud.obj = obj\n" +-" ud.flags = flags\n" +-"\n" +-" return ud_obj\n" +-"end\n" +-"\n" +-"local function obj_udata_luadelete_weak(ud_obj, type_mt)\n" +-" local ud = obj_udata_luacheck_internal(ud_obj, type_mt, false)\n" +-" if not ud then return nil, 0 end\n" +-" local obj, flags = ud.obj, ud.flags\n" +-" -- null userdata.\n" +-" ud.obj = nil\n" +-" ud.flags = 0\n" +-" -- invalid userdata, by setting the metatable to nil.\n" +-" d_setmetatable(ud_obj, nil)\n" +-" -- remove object from weak ref. table.\n" +-" local obj_key = tonumber(ffi.cast('uintptr_t', obj))\n" +-" weak_objects[obj_key] = nil\n" +-" return obj, flags\n" +-"end\n" +-"\n" +-"local function obj_udata_luapush_weak(obj, type_mt, obj_type, flags)\n" +-" if obj == nil then return end\n" +-"\n" +-" -- apply type's dynamic caster.\n" +-" if obj_type.dcaster ~= nil then\n" +-" local obj_ptr = ffi.new(\"void *[1]\", obj)\n" +-" local type_ptr = ffi.new(\"obj_type *[1]\", obj_type)\n" +-" obj_type.dcaster(obj_ptr, type_ptr)\n" +-" obj = obj_ptr[1]\n" +-" type = type_ptr[1]\n" ++" _pub[obj_name] = obj_pub\n" ++" _M[obj_name] = obj_pub\n" ++" if REG_OBJECTS_AS_GLOBALS then\n" ++" _G[obj_name] = obj_pub\n" + " end\n" ++"end\n" + "\n" +-" -- lookup object in weak ref. table.\n" +-" local obj_key = tonumber(ffi.cast('uintptr_t', obj))\n" +-" local ud_obj = weak_objects[obj_key]\n" +-" if ud_obj ~= nil then return ud_obj end\n" +-"\n" +-" -- create new userdata\n" +-" ud_obj = udata_new(ffi.sizeof\"obj_udata\", type_mt)\n" +-" local ud = ffi.cast(\"obj_udata *\", ud_obj)\n" +-" -- init. object\n" +-" ud.obj = obj\n" +-" ud.flags = flags\n" +-"\n" +-" -- cache weak reference to object.\n" +-" weak_objects[obj_key] = ud_obj\n" + "\n" +-" return ud_obj\n" ++"-- detect zmq version\n" ++"local VERSION_2_0 = true\n" ++"local VERSION_2_1 = false\n" ++"local VERSION_2_2 = false\n" ++"local VERSION_3_0 = false\n" ++"local zver = _M.version()\n" ++"if zver[1] == 3 then\n" ++" VERSION_2_0 = false\n" ++" VERSION_3_0 = true\n" ++"elseif zver[1] == 2 and zver[2] == 2 then\n" ++" VERSION_2_2 = true\n" ++" VERSION_2_1 = true\n" ++"elseif zver[1] == 2 and zver[2] == 1 then\n" ++" VERSION_2_1 = true\n" + "end\n" + "\n" +-"local function obj_simple_udata_luacheck(ud_obj, type_mt)\n" +-" local obj_mt = d_getmetatable(ud_obj)\n" +-" if obj_mt == type_mt then\n" +-" -- convert userdata to cdata.\n" +-" return ffi.cast(\"void *\", ud_obj)\n" +-" end\n" +-" error(\"(expected `\" .. type_mt['.name'] .. \"`, got \" .. type(ud_obj) .. \")\", 3)\n" +-"end\n" ++"if VERSION_2_0 then\n" ++" ffi.cdef[==[\n" ++"typedef int ZMQ_Error;\n" ++"typedef struct ZMQ_Socket ZMQ_Socket;\n" ++"typedef struct zmq_msg_t zmq_msg_t;\n" + "\n" +-"local function obj_simple_udata_to_cdata(objects, ud_obj, c_type, ud_mt)\n" +-" -- convert userdata to cdata.\n" +-" local c_obj = ffi.cast(c_type, obj_simple_udata_luacheck(ud_obj, ud_mt))\n" +-" -- cache converted cdata\n" +-" rawset(objects, ud_obj, c_obj)\n" +-" return c_obj\n" ++"ZMQ_Error zmq_sendmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__(\"zmq_send\");\n" ++"ZMQ_Error zmq_recvmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__(\"zmq_recv\");\n" ++"]==]\n" + "end\n" + "\n" +-"local function obj_simple_udata_luadelete(ud_obj, type_mt)\n" +-" local c_obj = obj_simple_udata_luacheck(ud_obj, type_mt)\n" +-" -- invalid userdata, by setting the metatable to nil.\n" +-" d_setmetatable(ud_obj, nil)\n" +-" return c_obj, OBJ_UDATA_FLAG_OWN\n" +-"end\n" ++"ffi_safe_cdef(\"BufferIF\", [[\n" ++"typedef struct Buffer_if {\n" ++" const uint8_t * (* const const_data)(void *this_v);\n" ++" size_t (* const get_size)(void *this_v);\n" ++"} BufferIF;\n" ++"]])\n" + "\n" +-"local function obj_simple_udata_luapush(c_obj, size, type_mt)\n" +-" if c_obj == nil then return end\n" ++"ffi_safe_cdef(\"FDIF\", [[\n" ++"typedef struct FD_if {\n" ++" int (* const get_fd)(void *this_v);\n" ++" int (* const get_type)(void *this_v);\n" ++"} FDIF;\n" ++"]])\n" + "\n" +-" -- create new userdata\n" +-" local ud_obj = udata_new(size, type_mt)\n" +-" local cdata = ffi.cast(\"void *\", ud_obj)\n" +-" -- init. object\n" +-" ffi.copy(cdata, c_obj, size)\n" ++"ffi_safe_cdef(\"MutableBufferIF\", [[\n" ++"typedef struct MutableBuffer_if {\n" ++" uint8_t * (* const data)(void *this_v);\n" ++" size_t (* const get_size)(void *this_v);\n" ++"} MutableBufferIF;\n" ++"]])\n" + "\n" +-" return ud_obj, cdata\n" +-"end\n" ++"local Cmod = ffi_load_cmodule(\"zmq\", false)\n" ++"local C = Cmod\n" + "\n" + "ffi.cdef[[\n" ++"typedef int ZMQ_Error;\n" ++"\n" + "typedef struct zmq_msg_t zmq_msg_t;\n" + "typedef struct ZMQ_Socket ZMQ_Socket;\n" + "typedef struct ZMQ_Poller ZMQ_Poller;\n" +@@ -976,9 +1797,7 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + "]]\n" + "\n" + "ffi.cdef[[\n" +-"typedef const char * (*get_zmq_strerror_func)();\n" +-"\n" +-"typedef int ZMQ_Error;\n" ++"int zmq_errno (void);\n" + "\n" + "\n" + "struct zmq_msg_t\n" +@@ -989,39 +1808,138 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + " unsigned char vsm_data [30]; /* that '30' is from 'MAX_VSM_SIZE' */\n" + "};\n" + "\n" +-"typedef void (zmq_free_fn) (void *data, void *hint);\n" +-"\n" + "int zmq_msg_init (zmq_msg_t *msg);\n" + "int zmq_msg_init_size (zmq_msg_t *msg, size_t size);\n" +-"int zmq_msg_init_data (zmq_msg_t *msg, void *data, size_t size, zmq_free_fn *ffn, void *hint);\n" + "\n" + "\n" +-"ZMQ_Error zmq_msg_close(zmq_msg_t * this1);\n" ++"ZMQ_Error zmq_msg_init(zmq_msg_t *);\n" ++"\n" ++"ZMQ_Error zmq_msg_init_size(zmq_msg_t *, size_t);\n" ++"\n" ++"ZMQ_Error zmq_msg_close(zmq_msg_t *);\n" ++"\n" ++"ZMQ_Error zmq_msg_move(zmq_msg_t *, zmq_msg_t *);\n" + "\n" +-"ZMQ_Error zmq_msg_close(zmq_msg_t * this1);\n" ++"ZMQ_Error zmq_msg_copy(zmq_msg_t *, zmq_msg_t *);\n" + "\n" +-"ZMQ_Error zmq_msg_move(zmq_msg_t * this1, zmq_msg_t * src2);\n" ++"void * zmq_msg_data(zmq_msg_t *);\n" + "\n" +-"ZMQ_Error zmq_msg_copy(zmq_msg_t * this1, zmq_msg_t * src2);\n" ++"size_t zmq_msg_size(zmq_msg_t *);\n" + "\n" +-"void * zmq_msg_data(zmq_msg_t * this1);\n" ++"ZMQ_Error zmq_close(ZMQ_Socket *);\n" + "\n" +-"size_t zmq_msg_size(zmq_msg_t * this1);\n" ++"ZMQ_Error zmq_bind(ZMQ_Socket *, const char *);\n" + "\n" +-"ZMQ_Error zmq_close(ZMQ_Socket * this1);\n" ++"ZMQ_Error zmq_unbind(ZMQ_Socket *, const char *);\n" + "\n" +-"ZMQ_Error zmq_bind(ZMQ_Socket * this1, const char * addr2);\n" ++"ZMQ_Error zmq_connect(ZMQ_Socket *, const char *);\n" + "\n" +-"ZMQ_Error zmq_connect(ZMQ_Socket * this1, const char * addr2);\n" ++"ZMQ_Error zmq_disconnect(ZMQ_Socket *, const char *);\n" + "\n" + "int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen);\n" + "int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen);\n" + "\n" +-"ZMQ_Error zmq_send(ZMQ_Socket * this1, zmq_msg_t * msg2, int flags3);\n" ++"ZMQ_Error zmq_sendmsg(ZMQ_Socket *, zmq_msg_t *, int);\n" ++"\n" ++"ZMQ_Error simple_zmq_send(ZMQ_Socket *, const char *, size_t, int);\n" ++"\n" ++"ZMQ_Error zmq_recvmsg(ZMQ_Socket *, zmq_msg_t *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_swap(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_swap(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *, uint64_t*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *, uint64_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_identity(ZMQ_Socket *, char *, size_t*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *, const char *, size_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *, const char *, size_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *, const char *, size_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_rate(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_mcast_loop(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_mcast_loop(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_fd(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_events(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_type(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_linger(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *, int);\n" + "\n" +-"typedef ZMQ_Error (*simple_zmq_send_func)(ZMQ_Socket *sock, const char *data, size_t data_len, int flags);\n" ++"ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *, int*);\n" + "\n" +-"ZMQ_Error zmq_recv(ZMQ_Socket * this1, zmq_msg_t * msg2, int flags3);\n" ++"ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_recovery_ivl_msec(ZMQ_Socket *, int64_t*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_recovery_ivl_msec(ZMQ_Socket *, int64_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_maxmsgsize(ZMQ_Socket *, int64_t*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_maxmsgsize(ZMQ_Socket *, int64_t);\n" ++"\n" ++"ZMQ_Error lzmq_socket_sndhwm(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_sndhwm(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_rcvhwm(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_rcvhwm(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_multicast_hops(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_multicast_hops(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *, int);\n" ++"\n" ++"ZMQ_Error lzmq_socket_ipv4only(ZMQ_Socket *, int*);\n" ++"\n" ++"ZMQ_Error lzmq_socket_set_ipv4only(ZMQ_Socket *, int);\n" + "\n" + "typedef int socket_t;\n" + "typedef struct zmq_pollitem_t {\n" +@@ -1031,7 +1949,12 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + " short revents;\n" + "} zmq_pollitem_t;\n" + "\n" +-"int zmq_poll(zmq_pollitem_t *items, int nitems, long timeout);\n" ++"int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock);\n" ++"int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd);\n" ++"int poller_get_free_item(ZMQ_Poller *poller);\n" ++"int poller_poll(ZMQ_Poller *poller, long timeout);\n" ++"void poller_remove_item(ZMQ_Poller *poller, int idx);\n" ++"\n" + "\n" + "struct ZMQ_Poller {\n" + " zmq_pollitem_t *items;\n" +@@ -1041,616 +1964,862 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + " int len;\n" + "};\n" + "\n" +-"typedef int (*poller_find_sock_item_func)(ZMQ_Poller *poller, ZMQ_Socket *sock);\n" ++"void poller_init(ZMQ_Poller *, unsigned int);\n" ++"\n" ++"void poller_cleanup(ZMQ_Poller *);\n" + "\n" +-"typedef int (*poller_find_fd_item_func)(ZMQ_Poller *poller, socket_t fd);\n" ++"ZMQ_Error poller_poll(ZMQ_Poller *, long);\n" + "\n" +-"typedef int (*poller_get_free_item_func)(ZMQ_Poller *poller);\n" ++"int poller_next_revents(ZMQ_Poller *, int*);\n" + "\n" +-"typedef int (*poller_poll_func)(ZMQ_Poller *poller, long timeout);\n" ++"ZMQ_Error zmq_term(ZMQ_Ctx *);\n" + "\n" +-"typedef void (*poller_remove_item_func)(ZMQ_Poller *poller, int idx);\n" ++"ZMQ_Socket * zmq_socket(ZMQ_Ctx *, int);\n" + "\n" +-"ZMQ_Error zmq_term(ZMQ_Ctx * this1);\n" ++"int zmq_ctx_set(ZMQ_Ctx *, int, int);\n" + "\n" +-"ZMQ_Socket * zmq_socket(ZMQ_Ctx * this1, int type2);\n" ++"int zmq_ctx_get(ZMQ_Ctx *, int);\n" + "\n" + "ZMQ_StopWatch * zmq_stopwatch_start();\n" + "\n" +-"unsigned long zmq_stopwatch_stop(ZMQ_StopWatch * this1);\n" ++"unsigned long zmq_stopwatch_stop(ZMQ_StopWatch *);\n" + "\n" +-"ZMQ_Ctx * zmq_init(int io_threads1);\n" ++"ZMQ_Ctx * zmq_init(int);\n" + "\n" +-"ZMQ_Error zmq_device(int device1, ZMQ_Socket * insock2, ZMQ_Socket * outsock3);\n" ++"ZMQ_Error zmq_device(int, ZMQ_Socket *, ZMQ_Socket *);\n" + "\n" +-"ZMQ_StopWatch * zmq_stopwatch_start();\n" ++"ZMQ_Error zmq_proxy(ZMQ_Socket *, ZMQ_Socket *, ZMQ_Socket *);\n" + "\n" +-"void zmq_sleep(int seconds_1);\n" ++"void zmq_sleep(int);\n" + "\n" + "\n" + "]]\n" + "\n" ++"REG_OBJECTS_AS_GLOBALS = false\n" ++"local _obj_interfaces_ffi = {}\n" + "local _pub = {}\n" + "local _meth = {}\n" ++"local _push = {}\n" ++"local _obj_subs = {}\n" + "for obj_name,mt in pairs(_priv) do\n" +-" if type(mt) == 'table' and mt.__index then\n" +-" _meth[obj_name] = mt.__index\n" ++" if type(mt) == 'table' then\n" ++" _obj_subs[obj_name] = {}\n" ++" if mt.__index then\n" ++" _meth[obj_name] = mt.__index\n" ++" end\n" + " end\n" + "end\n" +-"_pub.zmq = _M\n" + "for obj_name,pub in pairs(_M) do\n" + " _pub[obj_name] = pub\n" + "end\n" + "\n" +-"\n" +-"local obj_type_zmq_msg_t_check\n" +-"local obj_type_zmq_msg_t_delete\n" +-"local obj_type_zmq_msg_t_push\n" +-"\n" +-"(function()\n" +-"local zmq_msg_t_mt = _priv.zmq_msg_t\n" +-"local zmq_msg_t_objects = setmetatable({}, { __mode = \"k\",\n" +-"__index = function(objects, ud_obj)\n" +-" return obj_simple_udata_to_cdata(objects, ud_obj, \"zmq_msg_t *\", zmq_msg_t_mt)\n" +-"end,\n" +-"})\n" +-"function obj_type_zmq_msg_t_check(ud_obj)\n" +-" return zmq_msg_t_objects[ud_obj]\n" ++"--\n" ++"-- CData Metatable access\n" ++"--\n" ++"local _ctypes = {}\n" ++"local _type_names = {}\n" ++"local _get_mt_key = {}\n" ++"local _ctype_meta_map = {}\n" ++"\n" ++"local f_typeof = ffi.typeof\n" ++"local function get_cdata_type_id(cdata)\n" ++" return tonumber(f_typeof(cdata))\n" + "end\n" +-"\n" +-"function obj_type_zmq_msg_t_delete(ud_obj)\n" +-" zmq_msg_t_objects[ud_obj] = nil\n" +-" return obj_simple_udata_luadelete(ud_obj, zmq_msg_t_mt)\n" ++"local function get_cdata_mt(cdata)\n" ++" return _ctype_meta_map[tonumber(f_typeof(cdata))]\n" + "end\n" + "\n" +-"local zmq_msg_t_sizeof = ffi.sizeof\"zmq_msg_t\"\n" +-"function obj_type_zmq_msg_t_push(c_obj)\n" +-" local ud_obj, cdata = obj_simple_udata_luapush(c_obj, zmq_msg_t_sizeof, zmq_msg_t_mt)\n" +-" zmq_msg_t_objects[ud_obj] = cdata\n" +-" return ud_obj\n" ++"local function obj_register_ctype(name, ctype)\n" ++" local obj_mt = _priv[name]\n" ++" local obj_type = obj_mt['.type']\n" ++" local obj_ctype = ffi.typeof(ctype)\n" ++" local obj_type_id = tonumber(obj_ctype)\n" ++" _ctypes[name] = obj_ctype\n" ++" _type_names[name] = tostring(obj_ctype)\n" ++" _ctype_meta_map[obj_type_id] = obj_mt\n" ++" _ctype_meta_map[obj_mt] = obj_type_id\n" ++" return obj_mt, obj_type, obj_ctype\n" + "end\n" +-"end)()\n" + "\n" ++"--\n" ++"-- Interfaces helper code.\n" ++"--\n" ++"local _obj_interfaces_key = \"obj_interfaces<1.0>_table_key\"\n" ++"local _obj_interfaces_ud = reg_table[_obj_interfaces_key]\n" ++"local _obj_interfaces_key_ffi = _obj_interfaces_key .. \"_LJ2_FFI\"\n" ++"_obj_interfaces_ffi = reg_table[_obj_interfaces_key_ffi]\n" ++"if not _obj_interfaces_ffi then\n" ++" -- create missing interfaces table for FFI bindings.\n" ++" _obj_interfaces_ffi = {}\n" ++" reg_table[_obj_interfaces_key_ffi] = _obj_interfaces_ffi\n" ++"end\n" + "\n" +-"local obj_type_ZMQ_Socket_check\n" +-"local obj_type_ZMQ_Socket_delete\n" +-"local obj_type_ZMQ_Socket_push\n" +-"\n" +-"(function()\n" +-"local ZMQ_Socket_mt = _priv.ZMQ_Socket\n" +-"local ZMQ_Socket_objects = setmetatable({}, { __mode = \"k\",\n" +-"__index = function(objects, ud_obj)\n" +-" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_Socket *\", ZMQ_Socket_mt)\n" +-"end,\n" +-"})\n" +-"function obj_type_ZMQ_Socket_check(ud_obj)\n" +-" return ZMQ_Socket_objects[ud_obj]\n" ++"local function obj_get_userdata_interface(if_name, expected_err)\n" ++" local impls_ud = _obj_interfaces_ud[if_name]\n" ++" if not impls_ud then\n" ++" impls_ud = {}\n" ++" _obj_interfaces_ud[if_name] = impls_ud\n" ++" end\n" ++" -- create cdata check function to be used by non-ffi bindings.\n" ++" if not impls_ud.cdata then\n" ++" function impls_ud.cdata(obj)\n" ++" return assert(impls_ud[get_cdata_mt(obj)], expected_err)\n" ++" end\n" ++" end\n" ++" return impls_ud\n" + "end\n" + "\n" +-"function obj_type_ZMQ_Socket_delete(ud_obj)\n" +-" ZMQ_Socket_objects[ud_obj] = nil\n" +-" return obj_udata_luadelete_weak(ud_obj, ZMQ_Socket_mt)\n" ++"local function obj_get_interface_check(if_name, expected_err)\n" ++" local impls_ffi = _obj_interfaces_ffi[if_name]\n" ++" if not impls_ffi then\n" ++" local if_type = ffi.typeof(if_name .. \" *\")\n" ++" local impls_ud = obj_get_userdata_interface(if_name, expected_err)\n" ++" -- create table for FFI-based interface implementations.\n" ++" impls_ffi = setmetatable({}, {\n" ++" __index = function(impls_ffi, mt)\n" ++" local impl = impls_ud[mt]\n" ++" if impl then\n" ++" -- cast to cdata\n" ++" impl = if_type(impl)\n" ++" rawset(impls_ffi, mt, impl)\n" ++" end\n" ++" return impl\n" ++" end})\n" ++" _obj_interfaces_ffi[if_name] = impls_ffi\n" ++"\n" ++" -- create check function for this interface.\n" ++" function impls_ffi.check(obj)\n" ++" local impl\n" ++" if type(obj) == 'cdata' then\n" ++" impl = impls_ffi[get_cdata_type_id(obj)]\n" ++" else\n" ++" impl = impls_ud.userdata(impls_ffi, obj)\n" ++" end\n" ++" return assert(impl, expected_err)\n" ++" end\n" ++" end\n" ++" return impls_ffi.check\n" + "end\n" + "\n" +-"local ZMQ_Socket_type = ffi.cast(\"obj_type *\", ZMQ_Socket_mt[\".type\"])\n" +-"function obj_type_ZMQ_Socket_push(c_obj, flags)\n" +-" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Socket_mt, ZMQ_Socket_type, flags)\n" +-" ZMQ_Socket_objects[ud_obj] = c_obj\n" +-" return ud_obj\n" ++"local function obj_register_interface(if_name, obj_name)\n" ++" -- loopkup cdata id\n" ++" local obj_mt = _priv[obj_name]\n" ++" local obj_type_id = _ctype_meta_map[obj_mt]\n" ++" local impl_meths = {}\n" ++" local ffi_impls = _obj_interfaces_ffi[if_name]\n" ++" ffi_impls[obj_type_id] = impl_meths\n" ++" _meth[obj_name]['NOBJ_get_' .. if_name] = impl_meths\n" ++" return impl_meths\n" + "end\n" +-"end)()\n" + "\n" + "\n" +-"local obj_type_ZMQ_Poller_check\n" +-"local obj_type_ZMQ_Poller_delete\n" +-"local obj_type_ZMQ_Poller_push\n" ++"local obj_type_zmq_msg_t_check\n" ++"local obj_type_zmq_msg_t_delete\n" ++"local obj_type_zmq_msg_t_push\n" + "\n" +-"(function()\n" +-"local ZMQ_Poller_mt = _priv.ZMQ_Poller\n" +-"local ZMQ_Poller_objects = setmetatable({}, { __mode = \"k\",\n" +-"__index = function(objects, ud_obj)\n" +-" return obj_simple_udata_to_cdata(objects, ud_obj, \"ZMQ_Poller *\", ZMQ_Poller_mt)\n" +-"end,\n" +-"})\n" +-"function obj_type_ZMQ_Poller_check(ud_obj)\n" +-" return ZMQ_Poller_objects[ud_obj]\n" +-"end\n" ++"do\n" ++" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"zmq_msg_t\", \"zmq_msg_t\")\n" ++" local zmq_msg_t_sizeof = ffi.sizeof\"zmq_msg_t\"\n" + "\n" +-"function obj_type_ZMQ_Poller_delete(ud_obj)\n" +-" ZMQ_Poller_objects[ud_obj] = nil\n" +-" return obj_simple_udata_luadelete(ud_obj, ZMQ_Poller_mt)\n" +-"end\n" ++" function obj_type_zmq_msg_t_check(obj)\n" ++" return obj\n" ++" end\n" + "\n" +-"local ZMQ_Poller_sizeof = ffi.sizeof\"ZMQ_Poller\"\n" +-"function obj_type_ZMQ_Poller_push(c_obj)\n" +-" local ud_obj, cdata = obj_simple_udata_luapush(c_obj, ZMQ_Poller_sizeof, ZMQ_Poller_mt)\n" +-" ZMQ_Poller_objects[ud_obj] = cdata\n" +-" return ud_obj\n" +-"end\n" +-"end)()\n" ++" function obj_type_zmq_msg_t_delete(obj)\n" ++" return obj\n" ++" end\n" + "\n" ++" function obj_type_zmq_msg_t_push(obj)\n" ++" return obj\n" ++" end\n" + "\n" +-"local obj_type_ZMQ_Ctx_check\n" +-"local obj_type_ZMQ_Ctx_delete\n" +-"local obj_type_ZMQ_Ctx_push\n" ++" function obj_mt:__tostring()\n" ++" return sformat(\"zmq_msg_t: %p\", self)\n" ++" end\n" + "\n" +-"(function()\n" +-"local ZMQ_Ctx_mt = _priv.ZMQ_Ctx\n" +-"local ZMQ_Ctx_objects = setmetatable({}, { __mode = \"k\",\n" +-"__index = function(objects, ud_obj)\n" +-" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_Ctx *\", ZMQ_Ctx_mt)\n" +-"end,\n" +-"})\n" +-"function obj_type_ZMQ_Ctx_check(ud_obj)\n" +-" return ZMQ_Ctx_objects[ud_obj]\n" +-"end\n" ++" function obj_mt.__eq(val1, val2)\n" ++" if not ffi.istype(obj_ctype, val2) then return false end\n" ++" assert(ffi.istype(obj_ctype, val1), \"expected zmq_msg_t\")\n" ++" return (C.memcmp(val1, val2, zmq_msg_t_sizeof) == 0)\n" ++" end\n" + "\n" +-"function obj_type_ZMQ_Ctx_delete(ud_obj)\n" +-" ZMQ_Ctx_objects[ud_obj] = nil\n" +-" return obj_udata_luadelete_weak(ud_obj, ZMQ_Ctx_mt)\n" +-"end\n" ++" -- type checking function for C API.\n" ++" local function c_check(obj)\n" ++" if ffi.istype(obj_ctype, obj) then return obj end\n" ++" return nil\n" ++" end\n" ++" _priv[obj_type] = c_check\n" ++" -- push function for C API.\n" ++" reg_table[obj_type] = function(ptr)\n" ++" local obj = obj_ctype()\n", /* ----- CUT ----- */ ++" ffi.copy(obj, ptr, zmq_msg_t_sizeof);\n" ++" return obj\n" ++" end\n" + "\n" +-"local ZMQ_Ctx_type = ffi.cast(\"obj_type *\", ZMQ_Ctx_mt[\".type\"])\n" +-"function obj_type_ZMQ_Ctx_push(c_obj, flags)\n" +-" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_Ctx_mt, ZMQ_Ctx_type, flags)\n" +-" ZMQ_Ctx_objects[ud_obj] = c_obj\n" +-" return ud_obj\n" ++" -- export check functions for use in other modules.\n" ++" obj_mt.c_check = c_check\n" ++" obj_mt.ffi_check = obj_type_zmq_msg_t_check\n" + "end\n" +-"end)()\n" +-"\n" + "\n" +-"local obj_type_ZMQ_StopWatch_check\n" +-"local obj_type_ZMQ_StopWatch_delete\n" +-"local obj_type_ZMQ_StopWatch_push\n" + "\n" +-"(function()\n" +-"local ZMQ_StopWatch_mt = _priv.ZMQ_StopWatch\n" +-"local ZMQ_StopWatch_objects = setmetatable({}, { __mode = \"k\",\n" +-"__index = function(objects, ud_obj)\n" +-" return obj_udata_to_cdata(objects, ud_obj, \"ZMQ_StopWatch *\", ZMQ_StopWatch_mt)\n" +-"end,\n" +-"})\n" +-"function obj_type_ZMQ_StopWatch_check(ud_obj)\n" +-" return ZMQ_StopWatch_objects[ud_obj]\n" +-"end\n" ++"local obj_type_ZMQ_Socket_check\n" ++"local obj_type_ZMQ_Socket_delete\n" ++"local obj_type_ZMQ_Socket_push\n" + "\n" +-"function obj_type_ZMQ_StopWatch_delete(ud_obj)\n" +-" ZMQ_StopWatch_objects[ud_obj] = nil\n" +-" return obj_udata_luadelete_weak(ud_obj, ZMQ_StopWatch_mt)\n" +-"end\n" ++"do\n" ++" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Socket\", \"ZMQ_Socket *\")\n" ++"\n" ++" function obj_type_ZMQ_Socket_check(ptr)\n" ++" -- if ptr is nil or is the correct type, then just return it.\n" ++" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" ++" -- check if it is a compatible type.\n" ++" local ctype = tostring(ffi.typeof(ptr))\n" ++" local bcaster = _obj_subs.ZMQ_Socket[ctype]\n" ++" if bcaster then\n" ++" return bcaster(ptr)\n" ++" end\n" ++" return error(\"Expected 'ZMQ_Socket *'\", 2)\n" ++" end\n" + "\n" +-"local ZMQ_StopWatch_type = ffi.cast(\"obj_type *\", ZMQ_StopWatch_mt[\".type\"])\n" +-"function obj_type_ZMQ_StopWatch_push(c_obj, flags)\n" +-" local ud_obj = obj_udata_luapush_weak(c_obj, ZMQ_StopWatch_mt, ZMQ_StopWatch_type, flags)\n" +-" ZMQ_StopWatch_objects[ud_obj] = c_obj\n" +-" return ud_obj\n" +-"end\n" +-"end)()\n" ++" function obj_type_ZMQ_Socket_delete(ptr)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" local flags = nobj_obj_flags[id]\n" ++" if not flags then return nil, 0 end\n" ++" ffi.gc(ptr, nil)\n" ++" nobj_obj_flags[id] = nil\n" ++" return ptr, flags\n" ++" end\n" + "\n" ++" function obj_type_ZMQ_Socket_push(ptr, flags)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" -- check weak refs\n" ++" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" + "\n" +-"local get_zmq_strerror = ffi.new(\"get_zmq_strerror_func\", _priv[\"get_zmq_strerror\"])\n" ++" if flags ~= 0 then\n" ++" nobj_obj_flags[id] = flags\n" ++" ffi.gc(ptr, obj_mt.__gc)\n" ++" end\n" ++" nobj_weak_objects[id] = ptr\n" ++" return ptr\n" ++" end\n" + "\n" +-"local simple_zmq_send = ffi.new(\"simple_zmq_send_func\", _priv[\"simple_zmq_send\"])\n" ++" function obj_mt:__tostring()\n" ++" return sformat(\"ZMQ_Socket: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" ++" end\n" + "\n" +-"local poller_find_sock_item = ffi.new(\"poller_find_sock_item_func\", _priv[\"poller_find_sock_item\"])\n" ++" -- type checking function for C API.\n" ++" _priv[obj_type] = obj_type_ZMQ_Socket_check\n" ++" -- push function for C API.\n" ++" reg_table[obj_type] = function(ptr, flags)\n" ++" return obj_type_ZMQ_Socket_push(ffi.cast(obj_ctype,ptr), flags)\n" ++" end\n" + "\n" +-"local poller_find_fd_item = ffi.new(\"poller_find_fd_item_func\", _priv[\"poller_find_fd_item\"])\n" ++" -- export check functions for use in other modules.\n" ++" obj_mt.c_check = obj_type_ZMQ_Socket_check\n" ++" obj_mt.ffi_check = obj_type_ZMQ_Socket_check\n" ++"end\n" + "\n" +-"local poller_get_free_item = ffi.new(\"poller_get_free_item_func\", _priv[\"poller_get_free_item\"])\n" + "\n" +-"local poller_poll = ffi.new(\"poller_poll_func\", _priv[\"poller_poll\"])\n" ++"local obj_type_ZMQ_Poller_check\n" ++"local obj_type_ZMQ_Poller_delete\n" ++"local obj_type_ZMQ_Poller_push\n" + "\n" +-"local poller_remove_item = ffi.new(\"poller_remove_item_func\", _priv[\"poller_remove_item\"])\n" ++"do\n" ++" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Poller\", \"ZMQ_Poller\")\n" ++" local ZMQ_Poller_sizeof = ffi.sizeof\"ZMQ_Poller\"\n" + "\n" +-"local os_lib_table = {\n" +-" [\"Windows\"] = \"libzmq\",\n" +-"}\n" +-"local C = ffi.load(os_lib_table[ffi.os] or \"zmq\")\n" ++" function obj_type_ZMQ_Poller_check(obj)\n" ++" return obj\n" ++" end\n" + "\n" +-"local C_get_zmq_strerror = get_zmq_strerror\n" +-"-- make nicer wrapper for exported error function.\n" +-"local function get_zmq_strerror()\n" +-" return ffi.string(C_get_zmq_strerror())\n" +-"end\n" ++" function obj_type_ZMQ_Poller_delete(obj)\n" ++" return obj\n" ++" end\n" + "\n" +-"local function error_code__ZMQ_Error__push(err)\n" +-" local err_str\n" +-" if(-1 == err) then\n" +-" err_str = get_zmq_strerror();\n" ++" function obj_type_ZMQ_Poller_push(obj)\n" ++" return obj\n" + " end\n" + "\n" +-" return err_str\n" +-"end\n" ++" function obj_mt:__tostring()\n" ++" return sformat(\"ZMQ_Poller: %p\", self)\n" ++" end\n" ++"\n" ++" function obj_mt.__eq(val1, val2)\n" ++" if not ffi.istype(obj_ctype, val2) then return false end\n" ++" assert(ffi.istype(obj_ctype, val1), \"expected ZMQ_Poller\")\n" ++" return (C.memcmp(val1, val2, ZMQ_Poller_sizeof) == 0)\n" ++" end\n" ++"\n" ++" -- type checking function for C API.\n" ++" local function c_check(obj)\n" ++" if ffi.istype(obj_ctype, obj) then return obj end\n" ++" return nil\n" ++" end\n" ++" _priv[obj_type] = c_check\n" ++" -- push function for C API.\n" ++" reg_table[obj_type] = function(ptr)\n" ++" local obj = obj_ctype()\n" ++" ffi.copy(obj, ptr, ZMQ_Poller_sizeof);\n" ++" return obj\n" ++" end\n" ++"\n" ++" -- export check functions for use in other modules.\n" ++" obj_mt.c_check = c_check\n" ++" obj_mt.ffi_check = obj_type_ZMQ_Poller_check\n" ++"end\n" ++"\n" ++"\n" ++"local obj_type_ZMQ_Ctx_check\n" ++"local obj_type_ZMQ_Ctx_delete\n" ++"local obj_type_ZMQ_Ctx_push\n" ++"\n" ++"do\n" ++" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_Ctx\", \"ZMQ_Ctx *\")\n" ++"\n" ++" function obj_type_ZMQ_Ctx_check(ptr)\n" ++" -- if ptr is nil or is the correct type, then just return it.\n" ++" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" ++" -- check if it is a compatible type.\n" ++" local ctype = tostring(ffi.typeof(ptr))\n" ++" local bcaster = _obj_subs.ZMQ_Ctx[ctype]\n" ++" if bcaster then\n" ++" return bcaster(ptr)\n" ++" end\n" ++" return error(\"Expected 'ZMQ_Ctx *'\", 2)\n" ++" end\n" ++"\n" ++" function obj_type_ZMQ_Ctx_delete(ptr)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" local flags = nobj_obj_flags[id]\n" ++" if not flags then return nil, 0 end\n" ++" ffi.gc(ptr, nil)\n" ++" nobj_obj_flags[id] = nil\n" ++" return ptr, flags\n" ++" end\n" ++"\n" ++" function obj_type_ZMQ_Ctx_push(ptr, flags)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" -- check weak refs\n" ++" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" ++"\n" ++" if flags ~= 0 then\n" ++" nobj_obj_flags[id] = flags\n" ++" ffi.gc(ptr, obj_mt.__gc)\n" ++" end\n" ++" nobj_weak_objects[id] = ptr\n" ++" return ptr\n" ++" end\n" ++"\n" ++" function obj_mt:__tostring()\n" ++" return sformat(\"ZMQ_Ctx: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" ++" end\n" ++"\n" ++" -- type checking function for C API.\n" ++" _priv[obj_type] = obj_type_ZMQ_Ctx_check\n" ++" -- push function for C API.\n" ++" reg_table[obj_type] = function(ptr, flags)\n" ++" return obj_type_ZMQ_Ctx_push(ffi.cast(obj_ctype,ptr), flags)\n" ++" end\n" ++"\n" ++" -- export check functions for use in other modules.\n" ++" obj_mt.c_check = obj_type_ZMQ_Ctx_check\n" ++" obj_mt.ffi_check = obj_type_ZMQ_Ctx_check\n" ++"end\n" ++"\n" ++"\n" ++"local obj_type_ZMQ_StopWatch_check\n" ++"local obj_type_ZMQ_StopWatch_delete\n" ++"local obj_type_ZMQ_StopWatch_push\n" ++"\n" ++"do\n" ++" local obj_mt, obj_type, obj_ctype = obj_register_ctype(\"ZMQ_StopWatch\", \"ZMQ_StopWatch *\")\n" ++"\n" ++" function obj_type_ZMQ_StopWatch_check(ptr)\n" ++" -- if ptr is nil or is the correct type, then just return it.\n" ++" if not ptr or ffi.istype(obj_ctype, ptr) then return ptr end\n" ++" -- check if it is a compatible type.\n" ++" local ctype = tostring(ffi.typeof(ptr))\n" ++" local bcaster = _obj_subs.ZMQ_StopWatch[ctype]\n" ++" if bcaster then\n" ++" return bcaster(ptr)\n" ++" end\n" ++" return error(\"Expected 'ZMQ_StopWatch *'\", 2)\n" ++" end\n" ++"\n" ++" function obj_type_ZMQ_StopWatch_delete(ptr)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" local flags = nobj_obj_flags[id]\n" ++" if not flags then return nil, 0 end\n" ++" ffi.gc(ptr, nil)\n" ++" nobj_obj_flags[id] = nil\n" ++" return ptr, flags\n" ++" end\n" ++"\n" ++" function obj_type_ZMQ_StopWatch_push(ptr, flags)\n" ++" local id = obj_ptr_to_id(ptr)\n" ++" -- check weak refs\n" ++" if nobj_obj_flags[id] then return nobj_weak_objects[id] end\n" ++"\n" ++" if flags ~= 0 then\n" ++" nobj_obj_flags[id] = flags\n" ++" ffi.gc(ptr, obj_mt.__gc)\n" ++" end\n" ++" nobj_weak_objects[id] = ptr\n" ++" return ptr\n" ++" end\n" ++"\n" ++" function obj_mt:__tostring()\n" ++" return sformat(\"ZMQ_StopWatch: %p, flags=%d\", self, nobj_obj_flags[obj_ptr_to_id(self)] or 0)\n" ++" end\n" ++"\n" ++" -- type checking function for C API.\n" ++" _priv[obj_type] = obj_type_ZMQ_StopWatch_check\n" ++" -- push function for C API.\n" ++" reg_table[obj_type] = function(ptr, flags)\n" ++" return obj_type_ZMQ_StopWatch_push(ffi.cast(obj_ctype,ptr), flags)\n" ++" end\n" ++"\n" ++" -- export check functions for use in other modules.\n" ++" obj_mt.c_check = obj_type_ZMQ_StopWatch_check\n" ++" obj_mt.ffi_check = obj_type_ZMQ_StopWatch_check\n" ++"end\n" ++"\n" ++"\n" ++"local obj_type_Buffer_check =\n" ++" obj_get_interface_check(\"BufferIF\", \"Expected object with Buffer interface\")\n" ++"\n" ++"local obj_type_FD_check =\n" ++" obj_get_interface_check(\"FDIF\", \"Expected object with FD interface\")\n" ++"\n" ++"local obj_type_MutableBuffer_check =\n" ++" obj_get_interface_check(\"MutableBufferIF\", \"Expected object with MutableBuffer interface\")\n" ++"\n" ++"local os_lib_table = {\n" ++" [\"Windows\"] = \"libzmq\",\n" ++"}\n" ++"C = ffi_load(os_lib_table[ffi.os] or \"zmq\")\n" ++"\n" ++"\n" ++"-- Start \"ZErrors\" FFI interface\n" ++"-- End \"ZErrors\" FFI interface\n" ++"\n" ++"-- get ZErrors table to map errno to error name.\n" ++"local ZError_names = _M.ZErrors\n" ++"\n" ++"local function get_zmq_strerror()\n" ++" return ZError_names[C.zmq_errno()]\n" ++"end\n" ++"\n" ++"local function error_code__ZMQ_Error__push(err)\n" ++" local err_str\n" ++" if(-1 == err) then\n" ++" err_str = ZError_names[C.zmq_errno()]\n" ++" end\n" ++"\n" ++" return err_str\n" ++"end\n" + "\n" + "\n" + "-- Start \"zmq_msg_t\" FFI interface\n" ++"-- method: init\n" ++"function _pub.zmq_msg_t.init()\n" ++" local self = ffi.new(\"zmq_msg_t\")\n" ++" local rc_zmq_msg_init2 = 0\n" ++" rc_zmq_msg_init2 = C.zmq_msg_init(self)\n" ++" if (-1 == rc_zmq_msg_init2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_zmq_msg_init2)\n" ++" end\n" ++" return obj_type_zmq_msg_t_push(self)\n" ++"end\n" ++"register_default_constructor(_pub,\"zmq_msg_t\",_pub.zmq_msg_t.init)\n" ++"\n" ++"-- method: init_size\n" ++"function _pub.zmq_msg_t.init_size(size1)\n" ++" \n" ++" local self = ffi.new(\"zmq_msg_t\")\n" ++" local rc_zmq_msg_init_size2 = 0\n" ++" rc_zmq_msg_init_size2 = C.zmq_msg_init_size(self, size1)\n" ++" if (-1 == rc_zmq_msg_init_size2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_zmq_msg_init_size2)\n" ++" end\n" ++" return obj_type_zmq_msg_t_push(self)\n" ++"end\n" ++"\n" ++"-- method: init_data\n" ++"function _pub.zmq_msg_t.init_data(data1)\n" ++" local data_len1 = #data1\n" ++" local self = ffi.new(\"zmq_msg_t\")\n" ++" local err2 = 0\n" ++" err2 = C.zmq_msg_init_size(self, data_len1)\n" ++" if(0 == err2) then\n" ++" -- fill message\n" ++" ffi.copy(C.zmq_msg_data(self), data1, data_len1)\n" ++" end\n" ++"\n" ++" if (-1 == err2) then\n" ++" return nil,error_code__ZMQ_Error__push(err2)\n" ++" end\n" ++" return obj_type_zmq_msg_t_push(self)\n" ++"end\n" ++"\n" + "-- method: __gc\n" + "function _priv.zmq_msg_t.__gc(self)\n" +-" local this1,this_flags1 = obj_type_zmq_msg_t_delete(self)\n" +-" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" +-" local rc_zmq_msg_close1\n" +-" rc_zmq_msg_close1 = C.zmq_msg_close(this1)\n" ++" local self = obj_type_zmq_msg_t_delete(self)\n" ++" if not self then return end\n" ++" local rc_zmq_msg_close1 = 0\n" ++" rc_zmq_msg_close1 = C.zmq_msg_close(self)\n" + " -- check for error.\n" +-" local rc_zmq_msg_close1_err\n" + " if (-1 == rc_zmq_msg_close1) then\n" +-" rc_zmq_msg_close1_err = error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" +-" rc_zmq_msg_close1 = nil\n" +-" else\n" +-" rc_zmq_msg_close1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" + " end\n" +-" return rc_zmq_msg_close1, rc_zmq_msg_close1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: close\n" + "function _meth.zmq_msg_t.close(self)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" +-" local rc_zmq_msg_close1\n" +-" rc_zmq_msg_close1 = C.zmq_msg_close(this1)\n" ++" \n" ++" local rc_zmq_msg_close1 = 0\n" ++" rc_zmq_msg_close1 = C.zmq_msg_close(self)\n" + " -- check for error.\n" +-" local rc_zmq_msg_close1_err\n" + " if (-1 == rc_zmq_msg_close1) then\n" +-" rc_zmq_msg_close1_err = error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" +-" rc_zmq_msg_close1 = nil\n" +-" else\n" +-" rc_zmq_msg_close1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_close1)\n" + " end\n" +-" return rc_zmq_msg_close1, rc_zmq_msg_close1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: move\n" + "function _meth.zmq_msg_t.move(self, src2)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" +-" src2 = obj_type_zmq_msg_t_check(src2)\n" +-" local rc_zmq_msg_move1\n" +-" rc_zmq_msg_move1 = C.zmq_msg_move(this1, src2)\n" ++" \n" ++" \n" ++" local rc_zmq_msg_move1 = 0\n" ++" rc_zmq_msg_move1 = C.zmq_msg_move(self, src2)\n" + " -- check for error.\n" +-" local rc_zmq_msg_move1_err\n" + " if (-1 == rc_zmq_msg_move1) then\n" +-" rc_zmq_msg_move1_err = error_code__ZMQ_Error__push(rc_zmq_msg_move1)\n" +-" rc_zmq_msg_move1 = nil\n" +-" else\n" +-" rc_zmq_msg_move1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_move1)\n" + " end\n" +-" return rc_zmq_msg_move1, rc_zmq_msg_move1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: copy\n" + "function _meth.zmq_msg_t.copy(self, src2)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" +-" src2 = obj_type_zmq_msg_t_check(src2)\n" +-" local rc_zmq_msg_copy1\n" +-" rc_zmq_msg_copy1 = C.zmq_msg_copy(this1, src2)\n" ++" \n" ++" \n" ++" local rc_zmq_msg_copy1 = 0\n" ++" rc_zmq_msg_copy1 = C.zmq_msg_copy(self, src2)\n" + " -- check for error.\n" +-" local rc_zmq_msg_copy1_err\n" + " if (-1 == rc_zmq_msg_copy1) then\n" +-" rc_zmq_msg_copy1_err = error_code__ZMQ_Error__push(rc_zmq_msg_copy1)\n" +-" rc_zmq_msg_copy1 = nil\n" +-" else\n" +-" rc_zmq_msg_copy1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_msg_copy1)\n" + " end\n" +-" return rc_zmq_msg_copy1, rc_zmq_msg_copy1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: set_data\n" + "function _meth.zmq_msg_t.set_data(self, data2)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" ++" \n" + " local data_len2 = #data2\n" +-" local err1\n" ++" local err1 = 0\n" + " -- check message data size.\n" +-" if (C.zmq_msg_size(this1) ~= data_len2) then\n" ++" if (C.zmq_msg_size(self) ~= data_len2) then\n" + " -- need to resize message.\n" +-" C.zmq_msg_close(this1); -- close old message, to free old data.\n" +-" err1 = C.zmq_msg_init_size(this1, data_len2); -- re-initialize message.\n" ++" C.zmq_msg_close(self); -- close old message, to free old data.\n" ++" err1 = C.zmq_msg_init_size(self, data_len2); -- re-initialize message.\n" + " if (0 ~= err1) then\n" + " error(\"set_data() failed: \" .. get_zmq_strerror());\n" + " end\n" + " end\n" + " -- copy data into message\n" +-" ffi.copy(C.zmq_msg_data(this1), data2, data_len2);\n" ++" ffi.copy(C.zmq_msg_data(self), data2, data_len2);\n" + "\n" + " -- check for error.\n" +-" local err1_err\n" + " if (-1 == err1) then\n" +-" err1_err = error_code__ZMQ_Error__push(err1)\n" +-" err1 = nil\n" +-" else\n" +-" err1 = true\n" ++" return nil, error_code__ZMQ_Error__push(err1)\n" + " end\n" +-" return err1, err1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: data\n" + "function _meth.zmq_msg_t.data(self)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" ++" \n" + " local rc_zmq_msg_data1\n" +-" rc_zmq_msg_data1 = C.zmq_msg_data(this1)\n" +-" rc_zmq_msg_data1 = rc_zmq_msg_data1\n" ++" rc_zmq_msg_data1 = C.zmq_msg_data(self)\n" + " return rc_zmq_msg_data1\n" + "end\n" + "\n" + "-- method: set_size\n" + "function _meth.zmq_msg_t.set_size(self, size2)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" + " \n" +-" local err1\n" ++" \n" ++" local err1 = 0\n" + " -- check message data size.\n" +-" if (C.zmq_msg_size(this1) ~= size2) then\n" ++" if (C.zmq_msg_size(self) ~= size2) then\n" + " -- need to resize message.\n" +-" C.zmq_msg_close(this1); -- close old message, to free old data.\n" +-" err1 = C.zmq_msg_init_size(this1, size2); -- re-initialize message.\n" ++" C.zmq_msg_close(self); -- close old message, to free old data.\n" ++" err1 = C.zmq_msg_init_size(self, size2); -- re-initialize message.\n" + " if (0 ~= err1) then\n" + " error(\"set_size() failed: \" .. get_zmq_strerror());\n" + " end\n" + " end\n" + "\n" + " -- check for error.\n" +-" local err1_err\n" + " if (-1 == err1) then\n" +-" err1_err = error_code__ZMQ_Error__push(err1)\n" +-" err1 = nil\n" +-" else\n" +-" err1 = true\n" ++" return nil, error_code__ZMQ_Error__push(err1)\n" + " end\n" +-" return err1, err1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: size\n" + "function _meth.zmq_msg_t.size(self)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" +-" local rc_zmq_msg_size1\n" +-" rc_zmq_msg_size1 = C.zmq_msg_size(this1)\n" +-" rc_zmq_msg_size1 = rc_zmq_msg_size1\n" +-" return rc_zmq_msg_size1\n" ++" \n" ++" local size1 = 0\n" ++" size1 = C.zmq_msg_size(self)\n" ++" return tonumber(size1)\n" + "end\n" + "\n" + "-- method: __tostring\n" + "function _priv.zmq_msg_t.__tostring(self)\n" +-" local this1 = obj_type_zmq_msg_t_check(self)\n" ++" \n" + " local data_len1 = 0\n" + " local data1\n" +-" data1 = C.zmq_msg_data(this1);\n" +-" data_len1 = C.zmq_msg_size(this1);\n" ++" data1 = C.zmq_msg_data(self);\n" ++" data_len1 = C.zmq_msg_size(self);\n" ++"\n" ++" return data1 ~= nil and ffi_string(data1,data_len1) or nil\n" ++"end\n" ++"\n" ++"-- zmq_msg_t implements Buffer interface\n" ++"do\n" ++" local impl_meths = obj_register_interface(\"BufferIF\", \"zmq_msg_t\")\n" ++"-- Buffer interface method const_data\n" ++"impl_meths.const_data = C.zmq_msg_data\n" ++"-- Buffer interface method get_size\n" ++"impl_meths.get_size = C.zmq_msg_size\n" ++"end\n" + "\n" +-" data1 = ((nil ~= data1) and ffi.string(data1,data_len1))\n" +-" return data1\n" ++"-- zmq_msg_t implements MutableBuffer interface\n" ++"do\n" ++" local impl_meths = obj_register_interface(\"MutableBufferIF\", \"zmq_msg_t\")\n" ++"-- MutableBuffer interface method data\n" ++"impl_meths.data = C.zmq_msg_data\n" ++"-- MutableBuffer interface method get_size\n" ++"impl_meths.get_size = C.zmq_msg_size\n" + "end\n" + "\n" ++"_push.zmq_msg_t = obj_type_zmq_msg_t_push\n" ++"ffi.metatype(\"zmq_msg_t\", _priv.zmq_msg_t)\n" + "-- End \"zmq_msg_t\" FFI interface\n" + "\n" + "\n" + "-- Start \"ZMQ_Socket\" FFI interface\n" + "-- method: close\n" + "function _meth.ZMQ_Socket.close(self)\n" +-" local this1,this_flags1 = obj_type_ZMQ_Socket_delete(self)\n" +-" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" +-" local rc_zmq_close1\n" +-" rc_zmq_close1 = C.zmq_close(this1)\n" ++" local self,this_flags1 = obj_type_ZMQ_Socket_delete(self)\n" ++" if not self then return end\n" ++" local rc_zmq_close1 = 0\n" ++" rc_zmq_close1 = C.zmq_close(self)\n" + " -- check for error.\n" +-" local rc_zmq_close1_err\n" + " if (-1 == rc_zmq_close1) then\n" +-" rc_zmq_close1_err = error_code__ZMQ_Error__push(rc_zmq_close1)\n" +-" rc_zmq_close1 = nil\n" +-" else\n" +-" rc_zmq_close1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_close1)\n" + " end\n" +-" return rc_zmq_close1, rc_zmq_close1_err\n" ++" return true\n" + "end\n" ++"_priv.ZMQ_Socket.__gc = _meth.ZMQ_Socket.close\n" + "\n" + "-- method: bind\n" + "function _meth.ZMQ_Socket.bind(self, addr2)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" ++" \n" + " local addr_len2 = #addr2\n" +-" local rc_zmq_bind1\n" +-" rc_zmq_bind1 = C.zmq_bind(this1, addr2)\n" ++" local rc_zmq_bind1 = 0\n" ++" rc_zmq_bind1 = C.zmq_bind(self, addr2)\n" + " -- check for error.\n" +-" local rc_zmq_bind1_err\n" + " if (-1 == rc_zmq_bind1) then\n" +-" rc_zmq_bind1_err = error_code__ZMQ_Error__push(rc_zmq_bind1)\n" +-" rc_zmq_bind1 = nil\n" +-" else\n" +-" rc_zmq_bind1 = true\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_bind1)\n" + " end\n" +-" return rc_zmq_bind1, rc_zmq_bind1_err\n" ++" return true\n" ++"end\n" ++"\n" ++"-- method: unbind\n" ++"if (_meth.ZMQ_Socket.unbind) then\n" ++"function _meth.ZMQ_Socket.unbind(self, addr2)\n" ++" \n" ++" local addr_len2 = #addr2\n" ++" local rc_zmq_unbind1 = 0\n" ++" rc_zmq_unbind1 = C.zmq_unbind(self, addr2)\n" ++" -- check for error.\n" ++" if (-1 == rc_zmq_unbind1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_unbind1)\n" ++" end\n" ++" return true\n" ++"end\n" + "end\n" + "\n" + "-- method: connect\n" + "function _meth.ZMQ_Socket.connect(self, addr2)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" ++" \n" + " local addr_len2 = #addr2\n" +-" local rc_zmq_connect1\n" +-" rc_zmq_connect1 = C.zmq_connect(this1, addr2)\n" ++" local rc_zmq_connect1 = 0\n" ++" rc_zmq_connect1 = C.zmq_connect(self, addr2)\n" + " -- check for error.\n" +-" local rc_zmq_connect1_err\n" + " if (-1 == rc_zmq_connect1) then\n" +-" rc_zmq_connect1_err = error_code__ZMQ_Error__push(rc_zmq_connect1)\n" +-" rc_zmq_connect1 = nil\n" +-" else\n" +-" rc_zmq_connect1 = true\n" +-" end\n" +-" return rc_zmq_connect1, rc_zmq_connect1_err\n" +-"end\n" +-"\n" +-"local option_types = {\n" +-"[zmq.HWM] = 'uint64_t[1]',\n" +-"[zmq.SWAP] = 'int64_t[1]',\n" +-"[zmq.AFFINITY] = 'uint64_t[1]',\n" +-"[zmq.IDENTITY] = 'string',\n" +-"[zmq.SUBSCRIBE] = 'string',\n" +-"[zmq.UNSUBSCRIBE] = 'string',\n" +-"[zmq.RATE] = 'int64_t[1]',\n" +-"[zmq.RECOVERY_IVL] = 'int64_t[1]',\n" +-"[zmq.MCAST_LOOP] = 'int64_t[1]',\n" +-"[zmq.SNDBUF] = 'uint64_t[1]',\n" +-"[zmq.RCVBUF] = 'uint64_t[1]',\n" +-"[zmq.RCVMORE] = 'int64_t[1]',\n" +-"[zmq.FD] = 'int[1]',\n" +-"[zmq.EVENTS] = 'uint32_t[1]',\n" +-"[zmq.TYPE] = 'int[1]',\n" +-"[zmq.LINGER] = 'int[1]',\n" +-"[zmq.RECONNECT_IVL] = 'int[1]',\n" +-"[zmq.BACKLOG] = 'int[1]',\n" +-"}\n" +-"local option_len = {}\n" +-"local option_tmps = {}\n" +-"for k,v in pairs(option_types) do\n" +-" if v ~= 'string' then\n" +-" option_len[k] = ffi.sizeof(v)\n" +-" option_tmps[k] = ffi.new(v, 0)\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_connect1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"\n" ++"-- method: disconnect\n" ++"if (_meth.ZMQ_Socket.disconnect) then\n" ++"function _meth.ZMQ_Socket.disconnect(self, addr2)\n" ++" \n" ++" local addr_len2 = #addr2\n" ++" local rc_zmq_disconnect1 = 0\n" ++" rc_zmq_disconnect1 = C.zmq_disconnect(self, addr2)\n" ++" -- check for error.\n" ++" if (-1 == rc_zmq_disconnect1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_disconnect1)\n" + " end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"local option_gets = {}\n" ++"local option_sets = {}\n" ++"\n" ++"do\n" ++" local opt_name\n" ++" local methods = _meth.ZMQ_Socket\n" ++" setmetatable(option_gets,{__index = function(tab,opt)\n" ++" local opt_name = opt_name[opt]\n" ++" if not opt_name then return nil end\n" ++" local method = methods[opt_name]\n" ++" rawset(tab, opt, method)\n" ++" return method\n" ++" end})\n" ++" setmetatable(option_sets,{__index = function(tab,opt)\n" ++" local opt_name = opt_name[opt]\n" ++" if not opt_name then return nil end\n" ++" local method = methods['set_' .. opt_name] or methods[opt_name]\n" ++" rawset(tab, opt, method)\n" ++" return method\n" ++" end})\n" ++" opt_name = {\n" ++" [1] = 'hwm',\n" ++" [3] = 'swap',\n" ++" [4] = 'affinity',\n" ++" [5] = 'identity',\n" ++" [6] = 'subscribe',\n" ++" [7] = 'unsubscribe',\n", /* ----- CUT ----- */ ++" [8] = 'rate',\n" ++" [9] = 'recovery_ivl',\n" ++" [10] = 'mcast_loop',\n" ++" [11] = 'sndbuf',\n" ++" [12] = 'rcvbuf',\n" ++" [13] = 'rcvmore',\n" ++" [14] = 'fd',\n" ++" [15] = 'events',\n" ++" [16] = 'type',\n" ++" [17] = 'linger',\n" ++" [18] = 'reconnect_ivl',\n" ++" [19] = 'backlog',\n" ++" [20] = 'recovery_ivl_msec',\n" ++" [21] = 'reconnect_ivl_max',\n" ++" [27] = 'rcvtimeo',\n" ++" [28] = 'sndtimeo',\n" ++" [22] = 'maxmsgsize',\n" ++" [23] = 'sndhwm',\n" ++" [24] = 'rcvhwm',\n" ++" [25] = 'multicast_hops',\n" ++" [31] = 'ipv4only',\n" ++"}\n" + "end\n" + "\n" + "\n" + "-- method: setopt\n" + "function _meth.ZMQ_Socket.setopt(self, opt2, val3)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" +-" \n" +-" local err1\n" +-" local ctype = option_types[opt2]\n" +-" local tval\n" +-" local tval_len = 0\n" +-" if ctype == 'string' then\n" +-" tval = tostring(val3)\n" +-" tval_len = #val3\n" ++" \n" ++" \n" ++" local err1 = 0\n" ++" local set = option_sets[opt2]\n" ++" if set then\n" ++" return set(self,val3)\n" + " else\n" +-" tval = option_tmps[opt2]\n" +-" tval[0] = val3\n" +-" tval_len = option_len[opt2]\n" ++" error(\"Invalid socket option.\")\n" + " end\n" +-" err1 = C.zmq_setsockopt(this1, opt2, tval, tval_len)\n" + "\n" + " -- check for error.\n" +-" local err1_err\n" + " if (-1 == err1) then\n" +-" err1_err = error_code__ZMQ_Error__push(err1)\n" +-" err1 = nil\n" +-" else\n" +-" err1 = true\n" ++" return nil, error_code__ZMQ_Error__push(err1)\n" + " end\n" +-" return err1, err1_err\n" ++" return true\n" + "end\n" + "\n" + "local tmp_val_len = ffi.new('size_t[1]', 4)\n" + "\n" + "-- method: getopt\n" + "function _meth.ZMQ_Socket.getopt(self, opt2)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" ++" \n" + " \n" + " local val1\n" +-" local err2\n" +-" local ctype = option_types[opt2]\n" +-" local val\n" +-" local val_len = tmp_val_len\n" +-" if ctype == 'string' then\n" +-" val_len[0] = 255\n" +-" val = ffi.new('uint8_t[?]', val_len[0])\n" +-" ffi.fill(val, val_len[0])\n" ++" local err2 = 0\n" ++" local get = option_gets[opt2]\n" ++" if get then\n" ++" return get(self)\n" + " else\n" +-" val = option_tmps[opt2]\n" +-" val[0] = 0\n" +-" val_len[0] = option_len[opt2]\n" +-" end\n" +-" err2 = C.zmq_getsockopt(this1, opt2, val, val_len)\n" +-" if err2 == 0 then\n" +-" if ctype == 'string' then\n" +-" val_len = val_len[0]\n" +-" return ffi.string(val, val_len)\n" +-" else\n" +-" return tonumber(val[0])\n" +-" end\n" ++" error(\"Invalid socket option.\")\n" + " end\n" + "\n" +-" err2 = error_code__ZMQ_Error__push(err2)\n" +-" return val1, err2\n" +-"end\n" +-"\n" +-"-- temp. values for 'events' function.\n" +-"local events_tmp = ffi.new('uint32_t[1]', 0)\n" +-"local events_tmp_size = ffi.sizeof('uint32_t')\n" +-"local events_tmp_len = ffi.new('size_t[1]', events_tmp_size)\n" +-"local ZMQ_EVENTS = _M.EVENTS\n" +-"\n" +-"-- method: events\n" +-"function _meth.ZMQ_Socket.events(self)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" +-" local events1\n" +-" local err2\n" +-" events_tmp_len[0] = events_tmp_size\n" +-" err2 = C.zmq_getsockopt(this1, ZMQ_EVENTS, events_tmp, events_tmp_len);\n" +-" events1 = events_tmp[0]\n" +-"\n" +-" if not (-1 == err2) then\n" +-" events1 = events1\n" +-" else\n" +-" events1 = nil\n" +-" end\n" +-" err2 = error_code__ZMQ_Error__push(err2)\n" +-" return events1, err2\n" ++" return val1\n" + "end\n" + "\n" + "-- method: send_msg\n" + "function _meth.ZMQ_Socket.send_msg(self, msg2, flags3)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" +-" msg2 = obj_type_zmq_msg_t_check(msg2)\n" +-" flags3 = flags3 or 0\n" +-" local rc_zmq_send1\n" +-" rc_zmq_send1 = C.zmq_send(this1, msg2, flags3)\n" ++" \n" ++" \n" ++" flags3 = flags3 or 0\n" ++" local rc_zmq_sendmsg1 = 0\n" ++" rc_zmq_sendmsg1 = C.zmq_sendmsg(self, msg2, flags3)\n" + " -- check for error.\n" +-" local rc_zmq_send1_err\n" +-" if (-1 == rc_zmq_send1) then\n" +-" rc_zmq_send1_err = error_code__ZMQ_Error__push(rc_zmq_send1)\n" +-" rc_zmq_send1 = nil\n" +-" else\n" +-" rc_zmq_send1 = true\n" ++" if (-1 == rc_zmq_sendmsg1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_sendmsg1)\n" + " end\n" +-" return rc_zmq_send1, rc_zmq_send1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: send\n" + "function _meth.ZMQ_Socket.send(self, data2, flags3)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" ++" \n" + " local data_len2 = #data2\n" +-" flags3 = flags3 or 0\n" +-" local err1\n" +-" err1 = simple_zmq_send(this1, data2, data_len2, flags3);\n" +-"\n" ++" flags3 = flags3 or 0\n" ++" local rc_simple_zmq_send1 = 0\n" ++" rc_simple_zmq_send1 = Cmod.simple_zmq_send(self, data2, data_len2, flags3)\n" + " -- check for error.\n" +-" local err1_err\n" +-" if (-1 == err1) then\n" +-" err1_err = error_code__ZMQ_Error__push(err1)\n" +-" err1 = nil\n" +-" else\n" +-" err1 = true\n" ++" if (-1 == rc_simple_zmq_send1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_simple_zmq_send1)\n" + " end\n" +-" return err1, err1_err\n" ++" return true\n" + "end\n" + "\n" + "-- method: recv_msg\n" + "function _meth.ZMQ_Socket.recv_msg(self, msg2, flags3)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" +-" msg2 = obj_type_zmq_msg_t_check(msg2)\n" +-" flags3 = flags3 or 0\n" +-" local rc_zmq_recv1\n" +-" rc_zmq_recv1 = C.zmq_recv(this1, msg2, flags3)\n" ++" \n" ++" \n" ++" flags3 = flags3 or 0\n" ++" local rc_zmq_recvmsg1 = 0\n" ++" rc_zmq_recvmsg1 = C.zmq_recvmsg(self, msg2, flags3)\n" + " -- check for error.\n" +-" local rc_zmq_recv1_err\n" +-" if (-1 == rc_zmq_recv1) then\n" +-" rc_zmq_recv1_err = error_code__ZMQ_Error__push(rc_zmq_recv1)\n" +-" rc_zmq_recv1 = nil\n" +-" else\n" +-" rc_zmq_recv1 = true\n" ++" if (-1 == rc_zmq_recvmsg1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_recvmsg1)\n" + " end\n" +-" return rc_zmq_recv1, rc_zmq_recv1_err\n" ++" return true\n" + "end\n" + "\n" + "local tmp_msg = ffi.new('zmq_msg_t')\n" + "\n" + "-- method: recv\n" + "function _meth.ZMQ_Socket.recv(self, flags2)\n" +-" local this1 = obj_type_ZMQ_Socket_check(self)\n" +-" flags2 = flags2 or 0\n" ++" \n" ++" flags2 = flags2 or 0\n" + " local data_len1 = 0\n" + " local data1\n" +-" local err2\n" ++" local err2 = 0\n" + " local msg = tmp_msg\n" + " -- initialize blank message.\n" + " if C.zmq_msg_init(msg) < 0 then\n" +@@ -1658,1106 +2827,3603 @@ static const char zmq_ffi_lua_code[] = "local error = error\n" + " end\n" + "\n" + " -- receive message\n" +-" err2 = C.zmq_recv(this1, msg, flags2)\n" +-" if 0 == err2 then\n" ++" err2 = C.zmq_recvmsg(self, msg, flags2)\n" ++" if err2 >= 0 then\n" + " local data = ffi.string(C.zmq_msg_data(msg), C.zmq_msg_size(msg))\n" + " -- close message\n" + " C.zmq_msg_close(msg)\n" + " return data\n" + " end\n" + "\n" +-" if not (-1 == err2) then\n" +-" data1 = ((nil ~= data1) and ffi.string(data1,data_len1))\n" +-" else\n" +-" data1 = nil\n" ++" if (-1 == err2) then\n" ++" return nil,error_code__ZMQ_Error__push(err2)\n" + " end\n" +-" err2 = error_code__ZMQ_Error__push(err2)\n" + " -- close message\n" + " C.zmq_msg_close(msg)\n" + "\n" +-" return data1, err2\n" ++" return data1 ~= nil and ffi_string(data1,data_len1) or nil\n" + "end\n" + "\n" +-"-- End \"ZMQ_Socket\" FFI interface\n" +-"\n" ++"do\n" ++" local hwm_value_tmp = ffi.new(\"int[1]\")\n" + "\n" +-"-- Start \"ZMQ_Poller\" FFI interface\n" +-"-- method: poll\n" +-"function _meth.ZMQ_Poller.poll(self, timeout2)\n" +-" local this1 = obj_type_ZMQ_Poller_check(self)\n" ++"-- method: hwm\n" ++"if (_meth.ZMQ_Socket.hwm) then\n" ++"function _meth.ZMQ_Socket.hwm(self)\n" + " \n" +-" local err1\n" +-" -- poll for events\n" +-" err1 = poller_poll(this1, timeout2)\n" +-" if(err1 > 0) then\n" +-" this1.next = 0\n" +-" else\n" +-" this1.next = -1\n" +-" end\n" ++" local value1\n" ++" local rc_lzmq_socket_hwm2 = 0\n" ++" rc_lzmq_socket_hwm2 = Cmod.lzmq_socket_hwm(self, hwm_value_tmp)\n" ++" value1 = hwm_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_hwm2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_hwm2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" + "\n" ++"-- method: set_hwm\n" ++"if (_meth.ZMQ_Socket.set_hwm) then\n" ++"function _meth.ZMQ_Socket.set_hwm(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_hwm1 = 0\n" ++" rc_lzmq_socket_set_hwm1 = Cmod.lzmq_socket_set_hwm(self, value2)\n" + " -- check for error.\n" +-" local err1_err\n" +-" if (-1 == err1) then\n" +-" err1_err = error_code__ZMQ_Error__push(err1)\n" +-" err1 = nil\n" +-" else\n" +-" err1 = true\n" ++" if (-1 == rc_lzmq_socket_set_hwm1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_hwm1)\n" + " end\n" +-" return err1, err1_err\n" ++" return true\n" ++"end\n" + "end\n" + "\n" +-"-- method: next_revents\n" +-"function _meth.ZMQ_Poller.next_revents(self)\n" +-" local this1 = obj_type_ZMQ_Poller_check(self)\n" +-" local sock1\n" +-" local revents2\n" +-" local sock\n" +-" local idx = this1.next\n" +-" if (idx < 0) then return nil, -1 end\n" +-" local count = this1.count\n" +-" -- find next item with pending events.\n" +-" while (idx < count and this1.items[idx].revents == 0) do\n" +-" idx = idx + 1\n" +-" if (idx >= count) then\n" +-" idx = -1\n" +-" break\n" +-" end\n" +-" end\n" +-" -- did we find a pending event?\n" +-" if(idx >= 0) then\n" +-" -- push the event's sock/fd.\n" +-" if(this1.items[idx].socket ~= nil) then\n" +-" sock = obj_type_ZMQ_Socket_push(this1.items[idx].socket, 0)\n" +-" else\n" +-" sock = tonumber(this1.items[idx].fd)\n" +-" end\n" +-" revents2 = this1.items[idx].revents\n" +-" -- is this the last event.\n" +-" idx = idx + 1\n" +-" if (idx >= count) then\n" +-" idx = -1\n" +-" end\n" +-" this1.next = idx\n" +-" return sock, revents2\n" +-" end\n" +-" this1.next = idx\n" ++"do\n" ++" local swap_value_tmp = ffi.new(\"int[1]\")\n" + "\n" +-" revents2 = revents2\n" +-" return sock1, revents2\n" ++"-- method: swap\n" ++"if (_meth.ZMQ_Socket.swap) then\n" ++"function _meth.ZMQ_Socket.swap(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_swap2 = 0\n" ++" rc_lzmq_socket_swap2 = Cmod.lzmq_socket_swap(self, swap_value_tmp)\n" ++" value1 = swap_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_swap2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_swap2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" + "end\n" + "\n" +-"-- method: count\n" +-"function _meth.ZMQ_Poller.count(self)\n" +-" local this1 = obj_type_ZMQ_Poller_check(self)\n" +-" local count1\n" +-" count1 = this1.count;\n" +-"\n" +-" count1 = count1\n" +-" return count1\n" ++"-- method: set_swap\n" ++"if (_meth.ZMQ_Socket.set_swap) then\n" ++"function _meth.ZMQ_Socket.set_swap(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_swap1 = 0\n" ++" rc_lzmq_socket_set_swap1 = Cmod.lzmq_socket_set_swap(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_swap1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_swap1)\n" ++" end\n" ++" return true\n" ++"end\n" + "end\n" + "\n" +-"-- End \"ZMQ_Poller\" FFI interface\n" ++"do\n" ++" local affinity_value_tmp = ffi.new(\"uint64_t[1]\")\n" + "\n" ++"-- method: affinity\n" ++"if (_meth.ZMQ_Socket.affinity) then\n" ++"function _meth.ZMQ_Socket.affinity(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_affinity2 = 0\n" ++" rc_lzmq_socket_affinity2 = Cmod.lzmq_socket_affinity(self, affinity_value_tmp)\n" ++" value1 = affinity_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_affinity2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_affinity2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" + "\n" +-"-- Start \"ZMQ_Ctx\" FFI interface\n" +-"-- method: term\n" +-"function _meth.ZMQ_Ctx.term(self)\n" +-" local this1,this_flags1 = obj_type_ZMQ_Ctx_delete(self)\n" +-" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" +-" local rc_zmq_term1\n" +-" rc_zmq_term1 = C.zmq_term(this1)\n" ++"-- method: set_affinity\n" ++"if (_meth.ZMQ_Socket.set_affinity) then\n" ++"function _meth.ZMQ_Socket.set_affinity(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_affinity1 = 0\n" ++" rc_lzmq_socket_set_affinity1 = Cmod.lzmq_socket_set_affinity(self, value2)\n" + " -- check for error.\n" +-" local rc_zmq_term1_err\n" +-" if (-1 == rc_zmq_term1) then\n" +-" rc_zmq_term1_err = error_code__ZMQ_Error__push(rc_zmq_term1)\n" +-" rc_zmq_term1 = nil\n" +-" else\n" +-" rc_zmq_term1 = true\n" ++" if (-1 == rc_lzmq_socket_set_affinity1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_affinity1)\n" + " end\n" +-" return rc_zmq_term1, rc_zmq_term1_err\n" ++" return true\n" ++"end\n" + "end\n" + "\n" +-"-- method: socket\n" +-"function _meth.ZMQ_Ctx.socket(self, type2)\n" +-" local this1 = obj_type_ZMQ_Ctx_check(self)\n" ++"do\n" ++" local identity_value_len_tmp = ffi.new(\"size_t[1]\")\n" ++"\n" ++"-- method: identity\n" ++"if (_meth.ZMQ_Socket.identity) then\n" ++"function _meth.ZMQ_Socket.identity(self)\n" + " \n" +-" local rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN\n" +-" local rc_zmq_socket1\n" +-" rc_zmq_socket1 = C.zmq_socket(this1, type2)\n" +-" local rc_zmq_socket1_err\n" +-" if (nil == rc_zmq_socket1) then\n" +-" rc_zmq_socket1_err = get_zmq_strerror()\n" +-" else\n" +-" rc_zmq_socket1 = obj_type_ZMQ_Socket_push(rc_zmq_socket1, rc_zmq_socket_flags1)\n" ++" local value_len1 = 0\n" ++" local value1\n" ++" local rc_lzmq_socket_identity2 = 0\n" ++" rc_lzmq_socket_identity2 = Cmod.lzmq_socket_identity(self, value1, identity_value_len_tmp)\n" ++" value_len1 = identity_value_len_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_identity2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_identity2)\n" + " end\n" +-" return rc_zmq_socket1, rc_zmq_socket1_err\n" ++" return value1 ~= nil and ffi_string(value1,value_len1) or nil\n" ++"end\n" ++"end\n" + "end\n" + "\n" +-"-- End \"ZMQ_Ctx\" FFI interface\n" +-"\n" ++"-- method: set_identity\n" ++"if (_meth.ZMQ_Socket.set_identity) then\n" ++"function _meth.ZMQ_Socket.set_identity(self, value2)\n" ++" \n" ++" local value_len2 = #value2\n" ++" local rc_lzmq_socket_set_identity1 = 0\n" ++" rc_lzmq_socket_set_identity1 = Cmod.lzmq_socket_set_identity(self, value2, value_len2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_identity1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_identity1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" + "\n" +-"-- Start \"ZMQ_StopWatch\" FFI interface\n" +-"-- method: start\n" +-"function _pub.ZMQ_StopWatch.start()\n" +-" local this_flags1 = OBJ_UDATA_FLAG_OWN\n" +-" local this1\n" +-" this1 = C.zmq_stopwatch_start()\n" +-" this1 = obj_type_ZMQ_StopWatch_push(this1, this_flags1)\n" +-" return this1\n" ++"-- method: subscribe\n" ++"if (_meth.ZMQ_Socket.subscribe) then\n" ++"function _meth.ZMQ_Socket.subscribe(self, value2)\n" ++" \n" ++" local value_len2 = #value2\n" ++" local rc_lzmq_socket_subscribe1 = 0\n" ++" rc_lzmq_socket_subscribe1 = Cmod.lzmq_socket_subscribe(self, value2, value_len2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_subscribe1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_subscribe1)\n" ++" end\n" ++" return true\n" ++"end\n" + "end\n" + "\n" +-"-- method: stop\n" +-"function _meth.ZMQ_StopWatch.stop(self)\n" +-" local this1,this_flags1 = obj_type_ZMQ_StopWatch_delete(self)\n" +-" if(band(this_flags1,OBJ_UDATA_FLAG_OWN) == 0) then return end\n" +-" local usecs1\n" +-" usecs1 = C.zmq_stopwatch_stop(this1)\n" +-" usecs1 = tonumber(usecs1)\n" +-" return usecs1\n" ++"-- method: unsubscribe\n" ++"if (_meth.ZMQ_Socket.unsubscribe) then\n" ++"function _meth.ZMQ_Socket.unsubscribe(self, value2)\n" ++" \n" ++" local value_len2 = #value2\n" ++" local rc_lzmq_socket_unsubscribe1 = 0\n" ++" rc_lzmq_socket_unsubscribe1 = Cmod.lzmq_socket_unsubscribe(self, value2, value_len2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_unsubscribe1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_unsubscribe1)\n" ++" end\n" ++" return true\n" ++"end\n" + "end\n" + "\n" +-"-- End \"ZMQ_StopWatch\" FFI interface\n" ++"do\n" ++" local rate_value_tmp = ffi.new(\"int[1]\")\n" + "\n" +-"-- method: init\n" +-"function _pub.zmq.init(io_threads1)\n" ++"-- method: rate\n" ++"if (_meth.ZMQ_Socket.rate) then\n" ++"function _meth.ZMQ_Socket.rate(self)\n" + " \n" +-" local rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN\n" +-" local rc_zmq_init1\n" +-" rc_zmq_init1 = C.zmq_init(io_threads1)\n" +-" local rc_zmq_init1_err\n" +-" if (nil == rc_zmq_init1) then\n" +-" rc_zmq_init1_err = get_zmq_strerror()\n" +-" else\n" +-" rc_zmq_init1 = obj_type_ZMQ_Ctx_push(rc_zmq_init1, rc_zmq_init_flags1)\n" ++" local value1\n" ++" local rc_lzmq_socket_rate2 = 0\n" ++" rc_lzmq_socket_rate2 = Cmod.lzmq_socket_rate(self, rate_value_tmp)\n" ++" value1 = rate_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_rate2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rate2)\n" + " end\n" +-" return rc_zmq_init1, rc_zmq_init1_err\n" ++" return value1\n" ++"end\n" ++"end\n" + "end\n" + "\n" +-"-- method: init_ctx\n" +-"function _pub.zmq.init_ctx(ptr1)\n" +-" local ctx1\n" +-" local p_type = type(ptr1)\n" +-" if p_type == 'userdata' then\n" +-" ctx1 = ffi.cast('void *', ptr1);\n" +-" elseif p_type == 'cdata' then\n" +-" ctx1 = ptr1;\n" +-" else\n" +-" return error(\"expected lightuserdata/cdata\");\n" +-" end\n" ++"-- method: set_rate\n" ++"if (_meth.ZMQ_Socket.set_rate) then\n" ++"function _meth.ZMQ_Socket.set_rate(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_rate1 = 0\n" ++" rc_lzmq_socket_set_rate1 = Cmod.lzmq_socket_set_rate(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_rate1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rate1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" + "\n" +-" local ctx1_err\n" +-" if (nil == ctx1) then\n" +-" ctx1_err = get_zmq_strerror()\n" +-" else\n" +-" ctx1 = obj_type_ZMQ_Ctx_push(ctx1, 0)\n" ++"do\n" ++" local recovery_ivl_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: recovery_ivl\n" ++"if (_meth.ZMQ_Socket.recovery_ivl) then\n" ++"function _meth.ZMQ_Socket.recovery_ivl(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_recovery_ivl2 = 0\n" ++" rc_lzmq_socket_recovery_ivl2 = Cmod.lzmq_socket_recovery_ivl(self, recovery_ivl_value_tmp)\n" ++" value1 = recovery_ivl_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_recovery_ivl2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_recovery_ivl2)\n" + " end\n" +-" return ctx1, ctx1_err\n" ++" return value1\n" ++"end\n" ++"end\n" + "end\n" + "\n" +-"-- method: device\n" +-"function _pub.zmq.device(device1, insock2, outsock3)\n" ++"-- method: set_recovery_ivl\n" ++"if (_meth.ZMQ_Socket.set_recovery_ivl) then\n" ++"function _meth.ZMQ_Socket.set_recovery_ivl(self, value2)\n" + " \n" +-" insock2 = obj_type_ZMQ_Socket_check(insock2)\n" +-" outsock3 = obj_type_ZMQ_Socket_check(outsock3)\n" +-" local rc_zmq_device1\n" +-" rc_zmq_device1 = C.zmq_device(device1, insock2, outsock3)\n" ++" \n" ++" local rc_lzmq_socket_set_recovery_ivl1 = 0\n" ++" rc_lzmq_socket_set_recovery_ivl1 = Cmod.lzmq_socket_set_recovery_ivl(self, value2)\n" + " -- check for error.\n" +-" local rc_zmq_device1_err\n" +-" if (-1 == rc_zmq_device1) then\n" +-" rc_zmq_device1_err = error_code__ZMQ_Error__push(rc_zmq_device1)\n" +-" rc_zmq_device1 = nil\n" +-" else\n" +-" rc_zmq_device1 = true\n" ++" if (-1 == rc_lzmq_socket_set_recovery_ivl1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_recovery_ivl1)\n" + " end\n" +-" return rc_zmq_device1, rc_zmq_device1_err\n" ++" return true\n" + "end\n" +-"\n" +-"-- method: stopwatch_start\n" +-"function _pub.zmq.stopwatch_start()\n" +-" local rc_zmq_stopwatch_start_flags1 = OBJ_UDATA_FLAG_OWN\n" +-" local rc_zmq_stopwatch_start1\n" +-" rc_zmq_stopwatch_start1 = C.zmq_stopwatch_start()\n" +-" rc_zmq_stopwatch_start1 = obj_type_ZMQ_StopWatch_push(rc_zmq_stopwatch_start1, rc_zmq_stopwatch_start_flags1)\n" +-" return rc_zmq_stopwatch_start1\n" + "end\n" + "\n" +-"-- method: sleep\n" +-"function _pub.zmq.sleep(seconds_1)\n" ++"do\n" ++" local mcast_loop_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: mcast_loop\n" ++"if (_meth.ZMQ_Socket.mcast_loop) then\n" ++"function _meth.ZMQ_Socket.mcast_loop(self)\n" + " \n" +-" C.zmq_sleep(seconds_1)\n" +-" return \n" ++" local value1\n" ++" local rc_lzmq_socket_mcast_loop2 = 0\n" ++" rc_lzmq_socket_mcast_loop2 = Cmod.lzmq_socket_mcast_loop(self, mcast_loop_value_tmp)\n" ++" value1 = mcast_loop_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_mcast_loop2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_mcast_loop2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" + "end\n" + "\n" +-""; +- +-/* detect zmq version >= 2.1.0 */ +-#define VERSION_2_1 0 +-#if defined(ZMQ_VERSION) +-#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0)) +-#undef VERSION_2_1 +-#define VERSION_2_1 1 ++"-- method: set_mcast_loop\n" ++"if (_meth.ZMQ_Socket.set_mcast_loop) then\n" ++"function _meth.ZMQ_Socket.set_mcast_loop(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_mcast_loop1 = 0\n" ++" rc_lzmq_socket_set_mcast_loop1 = Cmod.lzmq_socket_set_mcast_loop(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_mcast_loop1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_mcast_loop1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local sndbuf_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: sndbuf\n" ++"if (_meth.ZMQ_Socket.sndbuf) then\n" ++"function _meth.ZMQ_Socket.sndbuf(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_sndbuf2 = 0\n" ++" rc_lzmq_socket_sndbuf2 = Cmod.lzmq_socket_sndbuf(self, sndbuf_value_tmp)\n" ++" value1 = sndbuf_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_sndbuf2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndbuf2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_sndbuf\n" ++"if (_meth.ZMQ_Socket.set_sndbuf) then\n" ++"function _meth.ZMQ_Socket.set_sndbuf(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_sndbuf1 = 0\n" ++" rc_lzmq_socket_set_sndbuf1 = Cmod.lzmq_socket_set_sndbuf(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_sndbuf1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndbuf1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local rcvbuf_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: rcvbuf\n" ++"if (_meth.ZMQ_Socket.rcvbuf) then\n" ++"function _meth.ZMQ_Socket.rcvbuf(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_rcvbuf2 = 0\n" ++" rc_lzmq_socket_rcvbuf2 = Cmod.lzmq_socket_rcvbuf(self, rcvbuf_value_tmp)\n" ++" value1 = rcvbuf_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_rcvbuf2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvbuf2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_rcvbuf\n" ++"if (_meth.ZMQ_Socket.set_rcvbuf) then\n" ++"function _meth.ZMQ_Socket.set_rcvbuf(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_rcvbuf1 = 0\n" ++" rc_lzmq_socket_set_rcvbuf1 = Cmod.lzmq_socket_set_rcvbuf(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_rcvbuf1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvbuf1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local rcvmore_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: rcvmore\n" ++"if (_meth.ZMQ_Socket.rcvmore) then\n" ++"function _meth.ZMQ_Socket.rcvmore(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_rcvmore2 = 0\n" ++" rc_lzmq_socket_rcvmore2 = Cmod.lzmq_socket_rcvmore(self, rcvmore_value_tmp)\n" ++" value1 = rcvmore_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_rcvmore2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvmore2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local fd_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: fd\n" ++"if (_meth.ZMQ_Socket.fd) then\n" ++"function _meth.ZMQ_Socket.fd(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_fd2 = 0\n" ++" rc_lzmq_socket_fd2 = Cmod.lzmq_socket_fd(self, fd_value_tmp)\n" ++" value1 = fd_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_fd2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_fd2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local events_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: events\n" ++"if (_meth.ZMQ_Socket.events) then\n" ++"function _meth.ZMQ_Socket.events(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_events2 = 0\n" ++" rc_lzmq_socket_events2 = Cmod.lzmq_socket_events(self, events_value_tmp)\n" ++" value1 = events_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_events2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_events2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local type_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: type\n" ++"if (_meth.ZMQ_Socket.type) then\n" ++"function _meth.ZMQ_Socket.type(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_type2 = 0\n" ++" rc_lzmq_socket_type2 = Cmod.lzmq_socket_type(self, type_value_tmp)\n" ++" value1 = type_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_type2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_type2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local linger_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: linger\n" ++"if (_meth.ZMQ_Socket.linger) then\n" ++"function _meth.ZMQ_Socket.linger(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_linger2 = 0\n" ++" rc_lzmq_socket_linger2 = Cmod.lzmq_socket_linger(self, linger_value_tmp)\n" ++" value1 = linger_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_linger2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_linger2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_linger\n" ++"if (_meth.ZMQ_Socket.set_linger) then\n" ++"function _meth.ZMQ_Socket.set_linger(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_linger1 = 0\n" ++" rc_lzmq_socket_set_linger1 = Cmod.lzmq_socket_set_linger(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_linger1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_linger1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n", /* ----- CUT ----- */ ++"do\n" ++" local reconnect_ivl_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: reconnect_ivl\n" ++"if (_meth.ZMQ_Socket.reconnect_ivl) then\n" ++"function _meth.ZMQ_Socket.reconnect_ivl(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_reconnect_ivl2 = 0\n" ++" rc_lzmq_socket_reconnect_ivl2 = Cmod.lzmq_socket_reconnect_ivl(self, reconnect_ivl_value_tmp)\n" ++" value1 = reconnect_ivl_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_reconnect_ivl2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_reconnect_ivl2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_reconnect_ivl\n" ++"if (_meth.ZMQ_Socket.set_reconnect_ivl) then\n" ++"function _meth.ZMQ_Socket.set_reconnect_ivl(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_reconnect_ivl1 = 0\n" ++" rc_lzmq_socket_set_reconnect_ivl1 = Cmod.lzmq_socket_set_reconnect_ivl(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_reconnect_ivl1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_reconnect_ivl1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local backlog_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: backlog\n" ++"if (_meth.ZMQ_Socket.backlog) then\n" ++"function _meth.ZMQ_Socket.backlog(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_backlog2 = 0\n" ++" rc_lzmq_socket_backlog2 = Cmod.lzmq_socket_backlog(self, backlog_value_tmp)\n" ++" value1 = backlog_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_backlog2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_backlog2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_backlog\n" ++"if (_meth.ZMQ_Socket.set_backlog) then\n" ++"function _meth.ZMQ_Socket.set_backlog(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_backlog1 = 0\n" ++" rc_lzmq_socket_set_backlog1 = Cmod.lzmq_socket_set_backlog(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_backlog1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_backlog1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local recovery_ivl_msec_value_tmp = ffi.new(\"int64_t[1]\")\n" ++"\n" ++"-- method: recovery_ivl_msec\n" ++"if (_meth.ZMQ_Socket.recovery_ivl_msec) then\n" ++"function _meth.ZMQ_Socket.recovery_ivl_msec(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_recovery_ivl_msec2 = 0\n" ++" rc_lzmq_socket_recovery_ivl_msec2 = Cmod.lzmq_socket_recovery_ivl_msec(self, recovery_ivl_msec_value_tmp)\n" ++" value1 = recovery_ivl_msec_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_recovery_ivl_msec2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_recovery_ivl_msec2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_recovery_ivl_msec\n" ++"if (_meth.ZMQ_Socket.set_recovery_ivl_msec) then\n" ++"function _meth.ZMQ_Socket.set_recovery_ivl_msec(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_recovery_ivl_msec1 = 0\n" ++" rc_lzmq_socket_set_recovery_ivl_msec1 = Cmod.lzmq_socket_set_recovery_ivl_msec(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_recovery_ivl_msec1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_recovery_ivl_msec1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local reconnect_ivl_max_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: reconnect_ivl_max\n" ++"if (_meth.ZMQ_Socket.reconnect_ivl_max) then\n" ++"function _meth.ZMQ_Socket.reconnect_ivl_max(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_reconnect_ivl_max2 = 0\n" ++" rc_lzmq_socket_reconnect_ivl_max2 = Cmod.lzmq_socket_reconnect_ivl_max(self, reconnect_ivl_max_value_tmp)\n" ++" value1 = reconnect_ivl_max_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_reconnect_ivl_max2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_reconnect_ivl_max2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_reconnect_ivl_max\n" ++"if (_meth.ZMQ_Socket.set_reconnect_ivl_max) then\n" ++"function _meth.ZMQ_Socket.set_reconnect_ivl_max(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_reconnect_ivl_max1 = 0\n" ++" rc_lzmq_socket_set_reconnect_ivl_max1 = Cmod.lzmq_socket_set_reconnect_ivl_max(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_reconnect_ivl_max1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_reconnect_ivl_max1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local maxmsgsize_value_tmp = ffi.new(\"int64_t[1]\")\n" ++"\n" ++"-- method: maxmsgsize\n" ++"if (_meth.ZMQ_Socket.maxmsgsize) then\n" ++"function _meth.ZMQ_Socket.maxmsgsize(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_maxmsgsize2 = 0\n" ++" rc_lzmq_socket_maxmsgsize2 = Cmod.lzmq_socket_maxmsgsize(self, maxmsgsize_value_tmp)\n" ++" value1 = maxmsgsize_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_maxmsgsize2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_maxmsgsize2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_maxmsgsize\n" ++"if (_meth.ZMQ_Socket.set_maxmsgsize) then\n" ++"function _meth.ZMQ_Socket.set_maxmsgsize(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_maxmsgsize1 = 0\n" ++" rc_lzmq_socket_set_maxmsgsize1 = Cmod.lzmq_socket_set_maxmsgsize(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_maxmsgsize1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_maxmsgsize1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local sndhwm_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: sndhwm\n" ++"if (_meth.ZMQ_Socket.sndhwm) then\n" ++"function _meth.ZMQ_Socket.sndhwm(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_sndhwm2 = 0\n" ++" rc_lzmq_socket_sndhwm2 = Cmod.lzmq_socket_sndhwm(self, sndhwm_value_tmp)\n" ++" value1 = sndhwm_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_sndhwm2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndhwm2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_sndhwm\n" ++"if (_meth.ZMQ_Socket.set_sndhwm) then\n" ++"function _meth.ZMQ_Socket.set_sndhwm(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_sndhwm1 = 0\n" ++" rc_lzmq_socket_set_sndhwm1 = Cmod.lzmq_socket_set_sndhwm(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_sndhwm1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndhwm1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local rcvhwm_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: rcvhwm\n" ++"if (_meth.ZMQ_Socket.rcvhwm) then\n" ++"function _meth.ZMQ_Socket.rcvhwm(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_rcvhwm2 = 0\n" ++" rc_lzmq_socket_rcvhwm2 = Cmod.lzmq_socket_rcvhwm(self, rcvhwm_value_tmp)\n" ++" value1 = rcvhwm_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_rcvhwm2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvhwm2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_rcvhwm\n" ++"if (_meth.ZMQ_Socket.set_rcvhwm) then\n" ++"function _meth.ZMQ_Socket.set_rcvhwm(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_rcvhwm1 = 0\n" ++" rc_lzmq_socket_set_rcvhwm1 = Cmod.lzmq_socket_set_rcvhwm(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_rcvhwm1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvhwm1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local multicast_hops_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: multicast_hops\n" ++"if (_meth.ZMQ_Socket.multicast_hops) then\n" ++"function _meth.ZMQ_Socket.multicast_hops(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_multicast_hops2 = 0\n" ++" rc_lzmq_socket_multicast_hops2 = Cmod.lzmq_socket_multicast_hops(self, multicast_hops_value_tmp)\n" ++" value1 = multicast_hops_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_multicast_hops2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_multicast_hops2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_multicast_hops\n" ++"if (_meth.ZMQ_Socket.set_multicast_hops) then\n" ++"function _meth.ZMQ_Socket.set_multicast_hops(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_multicast_hops1 = 0\n" ++" rc_lzmq_socket_set_multicast_hops1 = Cmod.lzmq_socket_set_multicast_hops(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_multicast_hops1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_multicast_hops1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local rcvtimeo_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: rcvtimeo\n" ++"if (_meth.ZMQ_Socket.rcvtimeo) then\n" ++"function _meth.ZMQ_Socket.rcvtimeo(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_rcvtimeo2 = 0\n" ++" rc_lzmq_socket_rcvtimeo2 = Cmod.lzmq_socket_rcvtimeo(self, rcvtimeo_value_tmp)\n" ++" value1 = rcvtimeo_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_rcvtimeo2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_rcvtimeo2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_rcvtimeo\n" ++"if (_meth.ZMQ_Socket.set_rcvtimeo) then\n" ++"function _meth.ZMQ_Socket.set_rcvtimeo(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_rcvtimeo1 = 0\n" ++" rc_lzmq_socket_set_rcvtimeo1 = Cmod.lzmq_socket_set_rcvtimeo(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_rcvtimeo1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_rcvtimeo1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local sndtimeo_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: sndtimeo\n" ++"if (_meth.ZMQ_Socket.sndtimeo) then\n" ++"function _meth.ZMQ_Socket.sndtimeo(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_sndtimeo2 = 0\n" ++" rc_lzmq_socket_sndtimeo2 = Cmod.lzmq_socket_sndtimeo(self, sndtimeo_value_tmp)\n" ++" value1 = sndtimeo_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_sndtimeo2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_sndtimeo2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_sndtimeo\n" ++"if (_meth.ZMQ_Socket.set_sndtimeo) then\n" ++"function _meth.ZMQ_Socket.set_sndtimeo(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_sndtimeo1 = 0\n" ++" rc_lzmq_socket_set_sndtimeo1 = Cmod.lzmq_socket_set_sndtimeo(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_sndtimeo1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_sndtimeo1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"do\n" ++" local ipv4only_value_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: ipv4only\n" ++"if (_meth.ZMQ_Socket.ipv4only) then\n" ++"function _meth.ZMQ_Socket.ipv4only(self)\n" ++" \n" ++" local value1\n" ++" local rc_lzmq_socket_ipv4only2 = 0\n" ++" rc_lzmq_socket_ipv4only2 = Cmod.lzmq_socket_ipv4only(self, ipv4only_value_tmp)\n" ++" value1 = ipv4only_value_tmp[0]\n" ++" if (-1 == rc_lzmq_socket_ipv4only2) then\n" ++" return nil,error_code__ZMQ_Error__push(rc_lzmq_socket_ipv4only2)\n" ++" end\n" ++" return value1\n" ++"end\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: set_ipv4only\n" ++"if (_meth.ZMQ_Socket.set_ipv4only) then\n" ++"function _meth.ZMQ_Socket.set_ipv4only(self, value2)\n" ++" \n" ++" \n" ++" local rc_lzmq_socket_set_ipv4only1 = 0\n" ++" rc_lzmq_socket_set_ipv4only1 = Cmod.lzmq_socket_set_ipv4only(self, value2)\n" ++" -- check for error.\n" ++" if (-1 == rc_lzmq_socket_set_ipv4only1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_lzmq_socket_set_ipv4only1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"_push.ZMQ_Socket = obj_type_ZMQ_Socket_push\n" ++"ffi.metatype(\"ZMQ_Socket\", _priv.ZMQ_Socket)\n" ++"-- End \"ZMQ_Socket\" FFI interface\n" ++"\n" ++"\n" ++"-- Start \"ZMQ_Poller\" FFI interface\n" ++"-- method: new\n" ++"function _pub.ZMQ_Poller.new(length1)\n" ++" length1 = length1 or 10\n" ++" local self = ffi.new(\"ZMQ_Poller\")\n" ++" Cmod.poller_init(self, length1)\n" ++" return obj_type_ZMQ_Poller_push(self)\n" ++"end\n" ++"register_default_constructor(_pub,\"ZMQ_Poller\",_pub.ZMQ_Poller.new)\n" ++"\n" ++"-- method: close\n" ++"function _meth.ZMQ_Poller.close(self)\n" ++" local self = obj_type_ZMQ_Poller_delete(self)\n" ++" if not self then return end\n" ++" Cmod.poller_cleanup(self)\n" ++" return \n" ++"end\n" ++"_priv.ZMQ_Poller.__gc = _meth.ZMQ_Poller.close\n" ++"\n" ++"-- method: add\n" ++"function _meth.ZMQ_Poller.add(self, sock2, events3)\n" ++" \n" ++" \n" ++" local idx1 = 0\n" ++" local fd = 0\n" ++" local sock_type = type(sock2)\n" ++" local sock\n" ++" if sock_type == 'cdata' then\n" ++" sock = obj_type_ZMQ_Socket_check(sock2)\n" ++" elseif sock_type == 'number' then\n" ++" fd = sock2\n" ++" else\n" ++" error(\"expected number or ZMQ_Socket\")\n" ++" end\n" ++" idx1 = Cmod.poller_get_free_item(self)\n" ++" local item = self.items[idx1]\n" ++" item.socket = sock\n" ++" item.fd = fd\n" ++" item.events = events3\n" ++"\n" ++" return idx1\n" ++"end\n" ++"\n" ++"-- method: modify\n" ++"function _meth.ZMQ_Poller.modify(self, sock2, events3)\n" ++" \n" ++" \n" ++" local idx1 = 0\n" ++" local fd = 0\n" ++" local sock_type = type(sock2)\n" ++" local sock\n" ++" if sock_type == 'cdata' then\n" ++" sock = obj_type_ZMQ_Socket_check(sock2)\n" ++" -- find sock in items list.\n" ++" idx1 = Cmod.poller_find_sock_item(self, sock)\n" ++" elseif sock_type == 'number' then\n" ++" fd = sock2\n" ++" -- find fd in items list.\n" ++" idx1 = Cmod.poller_find_fd_item(self, fd);\n" ++" else\n" ++" error(\"expected number or ZMQ_Socket\")\n" ++" end\n" ++" if events3 ~= 0 then\n" ++" local item = self.items[idx1]\n" ++" item.socket = sock\n" ++" item.fd = fd\n" ++" item.events = events3\n" ++" else\n" ++" Cmod.poller_remove_item(self, idx1)\n" ++" end\n" ++"\n" ++" return idx1\n" ++"end\n" ++"\n" ++"-- method: remove\n" ++"function _meth.ZMQ_Poller.remove(self, sock2)\n" ++" \n" ++" local idx1 = 0\n" ++" local fd = 0\n" ++" local sock_type = type(sock2)\n" ++" local sock\n" ++" if sock_type == 'cdata' then\n" ++" sock = obj_type_ZMQ_Socket_check(sock2)\n" ++" -- find sock in items list.\n" ++" idx1 = Cmod.poller_find_sock_item(self, sock)\n" ++" elseif sock_type == 'number' then\n" ++" fd = sock2\n" ++" -- find fd in items list.\n" ++" idx1 = Cmod.poller_find_fd_item(self, fd);\n" ++" else\n" ++" error(\"expected number or ZMQ_Socket\")\n" ++" end\n" ++" if idx1 >= 0 then\n" ++" Cmod.poller_remove_item(self, idx1)\n" ++" end\n" ++"\n" ++" return idx1\n" ++"end\n" ++"\n" ++"-- method: poll\n" ++"function _meth.ZMQ_Poller.poll(self, timeout2)\n" ++" \n" ++" \n" ++" local count1 = 0\n" ++" local err2 = 0\n" ++" err2 = Cmod.poller_poll(self, timeout2)\n" ++" if(err2 > 0) then\n" ++" self.next = 0\n" ++" count1 = err2\n" ++" else\n" ++" self.next = -1\n" ++" count1 = 0\n" ++" end\n" ++"\n" ++" if (-1 == err2) then\n" ++" return nil,error_code__ZMQ_Error__push(err2)\n" ++" end\n" ++" return count1\n" ++"end\n" ++"\n" ++"do\n" ++" local next_revents_idx_revents_tmp = ffi.new(\"int[1]\")\n" ++"\n" ++"-- method: next_revents_idx\n" ++"function _meth.ZMQ_Poller.next_revents_idx(self)\n" ++" \n" ++" local idx1 = 0\n" ++" local revents2\n" ++" idx1 = Cmod.poller_next_revents(self, next_revents_idx_revents_tmp)\n" ++" revents2 = next_revents_idx_revents_tmp[0]\n" ++" return idx1, revents2\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: count\n" ++"function _meth.ZMQ_Poller.count(self)\n" ++" \n" ++" local count1 = 0\n" ++" count1 = self.count;\n" ++"\n" ++" return count1\n" ++"end\n" ++"\n" ++"_push.ZMQ_Poller = obj_type_ZMQ_Poller_push\n" ++"ffi.metatype(\"ZMQ_Poller\", _priv.ZMQ_Poller)\n" ++"-- End \"ZMQ_Poller\" FFI interface\n" ++"\n" ++"\n" ++"-- Start \"ZMQ_Ctx\" FFI interface\n" ++"-- method: term\n" ++"function _meth.ZMQ_Ctx.term(self)\n" ++" local self,this_flags1 = obj_type_ZMQ_Ctx_delete(self)\n" ++" if not self then return end\n" ++" local rc_zmq_term1 = 0\n" ++" rc_zmq_term1 = C.zmq_term(self)\n" ++" -- check for error.\n" ++" if (-1 == rc_zmq_term1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_term1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"_priv.ZMQ_Ctx.__gc = _meth.ZMQ_Ctx.term\n" ++"\n" ++"-- method: socket\n" ++"function _meth.ZMQ_Ctx.socket(self, type2)\n" ++" \n" ++" \n" ++" local rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN\n" ++" local rc_zmq_socket1\n" ++" rc_zmq_socket1 = C.zmq_socket(self, type2)\n" ++" if (nil == rc_zmq_socket1) then\n" ++" return nil, get_zmq_strerror()\n" ++" end\n" ++" return obj_type_ZMQ_Socket_push(rc_zmq_socket1, rc_zmq_socket_flags1)\n" ++"end\n" ++"\n", /* ----- CUT ----- */ ++"-- method: set\n" ++"if (_meth.ZMQ_Ctx.set) then\n" ++"function _meth.ZMQ_Ctx.set(self, flag2, value3)\n" ++" \n" ++" \n" ++" \n" ++" local rc_zmq_ctx_set1 = 0\n" ++" rc_zmq_ctx_set1 = C.zmq_ctx_set(self, flag2, value3)\n" ++" return rc_zmq_ctx_set1\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: get\n" ++"if (_meth.ZMQ_Ctx.get) then\n" ++"function _meth.ZMQ_Ctx.get(self, flag2)\n" ++" \n" ++" \n" ++" local rc_zmq_ctx_get1 = 0\n" ++" rc_zmq_ctx_get1 = C.zmq_ctx_get(self, flag2)\n" ++" return rc_zmq_ctx_get1\n" ++"end\n" ++"end\n" ++"\n" ++"_push.ZMQ_Ctx = obj_type_ZMQ_Ctx_push\n" ++"ffi.metatype(\"ZMQ_Ctx\", _priv.ZMQ_Ctx)\n" ++"-- End \"ZMQ_Ctx\" FFI interface\n" ++"\n" ++"\n" ++"-- Start \"ZMQ_StopWatch\" FFI interface\n" ++"-- method: start\n" ++"function _pub.ZMQ_StopWatch.start()\n" ++" local this_flags1 = OBJ_UDATA_FLAG_OWN\n" ++" local self\n" ++" self = C.zmq_stopwatch_start()\n" ++" return obj_type_ZMQ_StopWatch_push(self, this_flags1)\n" ++"end\n" ++"register_default_constructor(_pub,\"ZMQ_StopWatch\",_pub.ZMQ_StopWatch.start)\n" ++"\n" ++"-- method: stop\n" ++"function _meth.ZMQ_StopWatch.stop(self)\n" ++" local self,this_flags1 = obj_type_ZMQ_StopWatch_delete(self)\n" ++" if not self then return end\n" ++" local usecs1 = 0\n" ++" usecs1 = C.zmq_stopwatch_stop(self)\n" ++" return tonumber(usecs1)\n" ++"end\n" ++"_priv.ZMQ_StopWatch.__gc = _meth.ZMQ_StopWatch.stop\n" ++"\n" ++"_push.ZMQ_StopWatch = obj_type_ZMQ_StopWatch_push\n" ++"ffi.metatype(\"ZMQ_StopWatch\", _priv.ZMQ_StopWatch)\n" ++"-- End \"ZMQ_StopWatch\" FFI interface\n" ++"\n" ++"-- method: init\n" ++"function _M.init(io_threads1)\n" ++" io_threads1 = io_threads1 or 1\n" ++" local rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN\n" ++" local rc_zmq_init1\n" ++" rc_zmq_init1 = C.zmq_init(io_threads1)\n" ++" if (nil == rc_zmq_init1) then\n" ++" return nil, get_zmq_strerror()\n" ++" end\n" ++" return obj_type_ZMQ_Ctx_push(rc_zmq_init1, rc_zmq_init_flags1)\n" ++"end\n" ++"\n" ++"-- method: init_ctx\n" ++"function _M.init_ctx(ptr1)\n" ++" local ctx1\n" ++" local p_type = type(ptr1)\n" ++" if p_type == 'userdata' then\n" ++" ctx1 = ffi.cast('ZMQ_Ctx *', ptr1);\n" ++" elseif p_type == 'cdata' and ffi.istype('void *', ptr1) then\n" ++" ctx1 = ffi.cast('ZMQ_Ctx *', ptr1);\n" ++" else\n" ++" return error(\"expected lightuserdata/cdata\");\n" ++" end\n" ++"\n" ++" if (nil == ctx1) then\n" ++" return nil, get_zmq_strerror()\n" ++" end\n" ++" return obj_type_ZMQ_Ctx_push(ctx1, 0)\n" ++"end\n" ++"\n" ++"-- method: device\n" ++"if (_M.device) then\n" ++"function _M.device(device1, insock2, outsock3)\n" ++" \n" ++" \n" ++" \n" ++" local rc_zmq_device1 = 0\n" ++" rc_zmq_device1 = C.zmq_device(device1, insock2, outsock3)\n" ++" -- check for error.\n" ++" if (-1 == rc_zmq_device1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_device1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: proxy\n" ++"if (_M.proxy) then\n" ++"function _M.proxy(frontend1, backend2, capture3)\n" ++" \n" ++" \n" ++" capture3 = capture3 and obj_type_ZMQ_Socket_check(capture3) or nil\n" ++" local rc_zmq_proxy1 = 0\n" ++" rc_zmq_proxy1 = C.zmq_proxy(frontend1, backend2, capture3)\n" ++" -- check for error.\n" ++" if (-1 == rc_zmq_proxy1) then\n" ++" return nil, error_code__ZMQ_Error__push(rc_zmq_proxy1)\n" ++" end\n" ++" return true\n" ++"end\n" ++"end\n" ++"\n" ++"-- method: stopwatch_start\n" ++"function _M.stopwatch_start()\n" ++" local rc_zmq_stopwatch_start_flags1 = OBJ_UDATA_FLAG_OWN\n" ++" local rc_zmq_stopwatch_start1\n" ++" rc_zmq_stopwatch_start1 = C.zmq_stopwatch_start()\n" ++" return obj_type_ZMQ_StopWatch_push(rc_zmq_stopwatch_start1, rc_zmq_stopwatch_start_flags1)\n" ++"end\n" ++"\n" ++"-- method: sleep\n" ++"function _M.sleep(seconds_1)\n" ++" \n" ++" C.zmq_sleep(seconds_1)\n" ++" return \n" ++"end\n" ++"\n", NULL }; ++static char *zmq_ZErrors_key = "zmq_ZErrors_key"; ++/* ++ * This wrapper function is to make the EAGAIN/ETERM error messages more like ++ * what is returned by LuaSocket. ++ */ ++static const char *get_zmq_strerror() { ++ int err = zmq_errno(); ++ switch(err) { ++ case EAGAIN: ++ return "timeout"; ++ break; ++ case EINTR: ++ return "interrupted"; ++ break; ++#if defined(ETERM) ++ case ETERM: ++ return "closed"; ++ break; ++#endif ++ default: ++ break; ++ } ++ return zmq_strerror(err); ++} ++ ++ ++ ++/* detect really old ZeroMQ 2.0.x series. */ ++#if !defined(ZMQ_RCVMORE) ++# error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" ++#endif ++ ++typedef struct ZMQ_Socket ZMQ_Socket; ++ ++#ifdef _WIN32 ++#include ++typedef SOCKET socket_t; ++#else ++typedef int socket_t; ++#endif ++ ++#if VERSION_2_0 ++# define zmq_sendmsg zmq_send ++# define zmq_recvmsg zmq_recv + #endif ++ ++/* socket option types. */ ++#define OPT_TYPE_NONE 0 ++#define OPT_TYPE_INT 1 ++#define OPT_TYPE_UINT32 2 ++#define OPT_TYPE_UINT64 3 ++#define OPT_TYPE_INT64 4 ++#define OPT_TYPE_BLOB 5 ++#define OPT_TYPE_FD 6 ++ ++static const int opt_types[] = { ++ OPT_TYPE_NONE, /* 0 unused */ ++#if VERSION_2_0 ++#define VERSION_2_0_MAX_OPT 13 ++ OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ ++ OPT_TYPE_NONE, /* 2 unused */ ++ OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ ++ OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ ++ OPT_TYPE_BLOB, /* 5 ZMQ_IDENTITY */ ++ OPT_TYPE_BLOB, /* 6 ZMQ_SUBSCRIBE */ ++ OPT_TYPE_BLOB, /* 7 ZMQ_UNSUBSCRIBE */ ++ OPT_TYPE_INT64, /* 8 ZMQ_RATE */ ++ OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ ++ OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ ++ OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ ++ OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ ++ OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ ++#endif /* #if VERSION_2_0 */ ++#if VERSION_2_1 ++#define VERSION_2_1_MAX_OPT 21 ++ OPT_TYPE_FD, /* 14 ZMQ_FD */ ++ OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ ++ OPT_TYPE_INT, /* 16 ZMQ_TYPE */ ++ OPT_TYPE_INT, /* 17 ZMQ_LINGER */ ++ OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ ++ OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ ++ OPT_TYPE_INT64, /* 20 ZMQ_RECOVERY_IVL_MSEC */ ++ OPT_TYPE_INT, /* 21 ZMQ_RECONNECT_IVL_MAX */ ++#endif /* #if VERSION_2_1 */ ++#if VERSION_2_2 ++#define VERSION_2_2_MAX_OPT 28 ++ OPT_TYPE_NONE, /* 22 unused */ ++ OPT_TYPE_NONE, /* 23 unused */ ++ OPT_TYPE_NONE, /* 24 unused */ ++ OPT_TYPE_NONE, /* 25 unused */ ++ OPT_TYPE_NONE, /* 26 unused */ ++ OPT_TYPE_INT, /* 27 ZMQ_RCVTIMEO */ ++ OPT_TYPE_INT, /* 28 ZMQ_SNDTIMEO */ ++#endif /* #if VERSION_2_2 */ ++#if VERSION_3_0 ++#define VERSION_3_0_MAX_OPT 31 ++ OPT_TYPE_INT, /* 1 ZMQ_HWM */ ++ OPT_TYPE_NONE, /* 2 unused */ ++ OPT_TYPE_NONE, /* 3 unused */ ++ OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ ++ OPT_TYPE_BLOB, /* 5 ZMQ_IDENTITY */ ++ OPT_TYPE_BLOB, /* 6 ZMQ_SUBSCRIBE */ ++ OPT_TYPE_BLOB, /* 7 ZMQ_UNSUBSCRIBE */ ++ OPT_TYPE_INT, /* 8 ZMQ_RATE */ ++ OPT_TYPE_INT, /* 9 ZMQ_RECOVERY_IVL */ ++ OPT_TYPE_NONE, /* 10 unused */ ++ OPT_TYPE_INT, /* 11 ZMQ_SNDBUF */ ++ OPT_TYPE_INT, /* 12 ZMQ_RCVBUF */ ++ OPT_TYPE_INT, /* 13 ZMQ_RCVMORE */ ++ OPT_TYPE_FD, /* 14 ZMQ_FD */ ++ OPT_TYPE_INT, /* 15 ZMQ_EVENTS */ ++ OPT_TYPE_INT, /* 16 ZMQ_TYPE */ ++ OPT_TYPE_INT, /* 17 ZMQ_LINGER */ ++ OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ ++ OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ ++ OPT_TYPE_NONE, /* 20 unused */ ++ OPT_TYPE_INT, /* 21 ZMQ_RECONNECT_IVL_MAX */ ++ OPT_TYPE_INT64, /* 22 ZMQ_MAXMSGSIZE */ ++ OPT_TYPE_INT, /* 23 ZMQ_SNDHWM */ ++ OPT_TYPE_INT, /* 24 ZMQ_RCVHWM */ ++ OPT_TYPE_INT, /* 25 ZMQ_MULTICAST_HOPS */ ++ OPT_TYPE_NONE, /* 26 unused */ ++ OPT_TYPE_INT, /* 27 ZMQ_RCVTIMEO */ ++ OPT_TYPE_INT, /* 28 ZMQ_SNDTIMEO */ ++ OPT_TYPE_NONE, /* 29 unused */ ++ OPT_TYPE_NONE, /* 30 unused */ ++ OPT_TYPE_INT, /* 31 ZMQ_IPV4ONLY */ ++#endif /* #if VERSION_3_0 */ ++#if VERSION_3_0 ++# define MAX_OPTS VERSION_3_0_MAX_OPT ++#else ++# if VERSION_2_2 ++# define MAX_OPTS VERSION_2_2_MAX_OPT ++# elif VERSION_2_1 ++# define MAX_OPTS VERSION_2_1_MAX_OPT ++# else ++# define MAX_OPTS VERSION_2_0_MAX_OPT ++# endif + #endif ++}; ++ ++#if VERSION_2_0 ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { ++ uint64_t val = (uint64_t)value; ++ return zmq_setsockopt(sock, ZMQ_HWM, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { ++ uint64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_HWM, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_swap(ZMQ_Socket *sock, int value) { ++ int64_t val = (int64_t)value; ++ return zmq_setsockopt(sock, ZMQ_SWAP, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_swap(ZMQ_Socket *sock, int *value) { ++ int64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_SWAP, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *sock, uint64_t value) { ++ return zmq_setsockopt(sock, ZMQ_AFFINITY, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *sock, uint64_t *value) { ++ size_t val_len = sizeof(uint64_t); ++ return zmq_getsockopt(sock, ZMQ_AFFINITY, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_IDENTITY, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_identity(ZMQ_Socket *sock, char *value, size_t *len) { ++ return zmq_getsockopt(sock, ZMQ_IDENTITY, value, len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_SUBSCRIBE, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_UNSUBSCRIBE, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *sock, int value) { ++ int64_t val = (int64_t)value; ++ return zmq_setsockopt(sock, ZMQ_RATE, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rate(ZMQ_Socket *sock, int *value) { ++ int64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_RATE, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *sock, int value) { ++ int64_t val = (int64_t)value; ++ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *sock, int *value) { ++ int64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_RECOVERY_IVL, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_mcast_loop(ZMQ_Socket *sock, int value) { ++ int64_t val = (int64_t)value; ++ return zmq_setsockopt(sock, ZMQ_MCAST_LOOP, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_mcast_loop(ZMQ_Socket *sock, int *value) { ++ int64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_MCAST_LOOP, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *sock, int value) { ++ uint64_t val = (uint64_t)value; ++ return zmq_setsockopt(sock, ZMQ_SNDBUF, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *sock, int *value) { ++ uint64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_SNDBUF, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *sock, int value) { ++ uint64_t val = (uint64_t)value; ++ return zmq_setsockopt(sock, ZMQ_RCVBUF, &val, sizeof(val)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *sock, int *value) { ++ uint64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_RCVBUF, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *sock, int *value) { ++ int64_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_RCVMORE, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++#endif /* #if VERSION_2_0 */ ++#if VERSION_2_1 ++LUA_NOBJ_API ZMQ_Error lzmq_socket_fd(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_FD, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_events(ZMQ_Socket *sock, int *value) { ++ uint32_t val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ZMQ_EVENTS, &val, &val_len); ++ *value = (int)val; ++ return rc; ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_type(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_TYPE, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_LINGER, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_linger(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_LINGER, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_BACKLOG, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_BACKLOG, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl_msec(ZMQ_Socket *sock, int64_t value) { ++ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL_MSEC, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl_msec(ZMQ_Socket *sock, int64_t *value) { ++ size_t val_len = sizeof(int64_t); ++ return zmq_getsockopt(sock, ZMQ_RECOVERY_IVL_MSEC, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL_MAX, value, &val_len); ++} ++ ++#endif /* #if VERSION_2_1 */ ++#if VERSION_2_2 ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RCVTIMEO, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RCVTIMEO, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_SNDTIMEO, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_SNDTIMEO, value, &val_len); ++} ++ ++#endif /* #if VERSION_2_2 */ ++#if VERSION_3_0 ++ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { ++ int val; ++ int rc; ++ val = (int)value; ++ rc = zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); ++ if(-1 == rc) return rc; ++ val = (int)value; ++ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); ++} ++ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { ++ size_t val_len; ++ int rc; ++ val_len = sizeof(value); ++ rc = zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); ++ if(-1 == rc) return rc; ++ val_len = sizeof(value); ++ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_affinity(ZMQ_Socket *sock, uint64_t value) { ++ return zmq_setsockopt(sock, ZMQ_AFFINITY, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_affinity(ZMQ_Socket *sock, uint64_t *value) { ++ size_t val_len = sizeof(uint64_t); ++ return zmq_getsockopt(sock, ZMQ_AFFINITY, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_identity(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_IDENTITY, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_identity(ZMQ_Socket *sock, char *value, size_t *len) { ++ return zmq_getsockopt(sock, ZMQ_IDENTITY, value, len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_subscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_SUBSCRIBE, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_unsubscribe(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ZMQ_UNSUBSCRIBE, value, str_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rate(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RATE, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rate(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RATE, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_recovery_ivl(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RECOVERY_IVL, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_recovery_ivl(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RECOVERY_IVL, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndbuf(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_SNDBUF, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_sndbuf(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_SNDBUF, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvbuf(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RCVBUF, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvbuf(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RCVBUF, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvmore(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RCVMORE, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_fd(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_FD, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_events(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_EVENTS, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_type(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_TYPE, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_linger(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_LINGER, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_linger(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_LINGER, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_backlog(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_BACKLOG, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_backlog(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_BACKLOG, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_reconnect_ivl_max(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_reconnect_ivl_max(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RECONNECT_IVL_MAX, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_maxmsgsize(ZMQ_Socket *sock, int64_t value) { ++ return zmq_setsockopt(sock, ZMQ_MAXMSGSIZE, &value, sizeof(value)); ++} + +-/* detect really old ZeroMQ 2.0.x series. */ +-#if !defined(ZMQ_RCVMORE) +-#error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" ++LUA_NOBJ_API ZMQ_Error lzmq_socket_maxmsgsize(ZMQ_Socket *sock, int64_t *value) { ++ size_t val_len = sizeof(int64_t); ++ return zmq_getsockopt(sock, ZMQ_MAXMSGSIZE, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndhwm(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_sndhwm(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvhwm(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvhwm(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_multicast_hops(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_MULTICAST_HOPS, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_multicast_hops(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_MULTICAST_HOPS, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_rcvtimeo(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_RCVTIMEO, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_rcvtimeo(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_RCVTIMEO, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_sndtimeo(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_SNDTIMEO, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_sndtimeo(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_SNDTIMEO, value, &val_len); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_set_ipv4only(ZMQ_Socket *sock, int value) { ++ return zmq_setsockopt(sock, ZMQ_IPV4ONLY, &value, sizeof(value)); ++} ++ ++LUA_NOBJ_API ZMQ_Error lzmq_socket_ipv4only(ZMQ_Socket *sock, int *value) { ++ size_t val_len = sizeof(int); ++ return zmq_getsockopt(sock, ZMQ_IPV4ONLY, value, &val_len); ++} ++ ++#endif /* #if VERSION_3_0 */ ++ ++LUA_NOBJ_API ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { ++ ZMQ_Error err; ++ zmq_msg_t msg; ++ /* initialize message */ ++ err = zmq_msg_init_size(&msg, data_len); ++ if(0 == err) { ++ /* fill message */ ++ memcpy(zmq_msg_data(&msg), data, data_len); ++ /* send message */ ++ err = zmq_sendmsg(sock, &msg, flags); ++ /* close message */ ++ zmq_msg_close(&msg); ++ } ++ return err; ++} ++ ++struct ZMQ_Poller { ++ zmq_pollitem_t *items; ++ int next; ++ int count; ++ int free_list; ++ int len; ++}; ++ ++ ++typedef struct ZMQ_Poller ZMQ_Poller; ++ ++#define FREE_ITEM_EVENTS_TAG ((short)0xFFFF) ++ ++#define ITEM_TO_INDEX(items, item) (item - (items)) ++ ++static int poller_resize_items(ZMQ_Poller *poller, int len) { ++ int old_len = poller->len; ++ ++ /* make sure new length is atleast as large as items count. */ ++ len = (poller->count <= len) ? len : poller->count; ++ ++ /* if the new length is the same as the old length, then don't try to resize. */ ++ if(old_len == len) return len; ++ ++ poller->items = (zmq_pollitem_t *)realloc(poller->items, len * sizeof(zmq_pollitem_t)); ++ poller->len = len; ++ if(len > old_len) { ++ /* clear new space. */ ++ memset(&(poller->items[old_len]), 0, (len - old_len) * sizeof(zmq_pollitem_t)); ++ } ++ return len; ++} ++ ++void poller_init(ZMQ_Poller *poller, int length) { ++ poller->items = (zmq_pollitem_t *)calloc(length, sizeof(zmq_pollitem_t)); ++ poller->next = -1; ++ poller->count = 0; ++ poller->len = length; ++ poller->free_list = -1; ++} ++ ++void poller_cleanup(ZMQ_Poller *poller) { ++ free(poller->items); ++ poller->items = NULL; ++ poller->next = -1; ++ poller->count = 0; ++ poller->len = 0; ++ poller->free_list = -1; ++} ++ ++int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { ++ zmq_pollitem_t *items; ++ int count; ++ int n; ++ ++ /* find ZMQ_Socket */ ++ items = poller->items; ++ count = poller->count; ++ for(n=0; n < count; n++) { ++ if(items[n].socket == sock) return n; ++ } ++ /* not found. */ ++ return -1; ++} ++ ++int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { ++ zmq_pollitem_t *items; ++ int count; ++ int n; ++ ++ /* find fd */ ++ items = poller->items; ++ count = poller->count; ++ for(n=0; n < count; n++) { ++ if(items[n].fd == fd) return n; ++ } ++ /* not found. */ ++ return -1; ++} ++ ++void poller_remove_item(ZMQ_Poller *poller, int idx) { ++ zmq_pollitem_t *items; ++ int free_list; ++ int count; ++ ++ count = poller->count; ++ /* no item to remove. */ ++ if(idx >= count || count == 0) return; ++ ++ items = poller->items; ++ free_list = poller->free_list; ++ ++ /* link new free slot to head of free list. */ ++ if(free_list >= 0 && free_list < count) { ++ /* use socket pointer for free list's 'next' field. */ ++ items[idx].socket = &(items[free_list]); ++ } else { ++ /* free list is empty mark poller slot as the end. */ ++ items[idx].socket = NULL; ++ } ++ poller->free_list = idx; ++ /* mark poller slot as a free slot. */ ++ items[idx].events = FREE_ITEM_EVENTS_TAG; ++ /* clear old revents. */ ++ items[idx].revents = 0; ++} ++ ++int poller_get_free_item(ZMQ_Poller *poller) { ++ zmq_pollitem_t *curr; ++ zmq_pollitem_t *next; ++ int count; ++ int idx; ++ ++ count = poller->count; ++ idx = poller->free_list; ++ /* check for a free slot in the free list. */ ++ if(idx >= 0 && idx < count) { ++ /* remove free slot from free list. */ ++ curr = &(poller->items[idx]); ++ /* valid free slot. */ ++ assert(curr->events == FREE_ITEM_EVENTS_TAG); ++ /* is poller the last free slot? */ ++ next = ((zmq_pollitem_t *)curr->socket); ++ if(next != NULL) { ++ /* set next free slot as head of free list. */ ++ poller->free_list = ITEM_TO_INDEX(poller->items, next); ++ } else { ++ /* free list is empty now. */ ++ poller->free_list = -1; ++ } ++ /* clear slot */ ++ memset(curr, 0, sizeof(zmq_pollitem_t)); ++ return idx; ++ } ++ ++ idx = count; ++ poller->count = ++count; ++ /* make room for new item. */ ++ if(count >= poller->len) { ++ poller_resize_items(poller, poller->len + 10); ++ } ++ return idx; ++} ++ ++static int poller_compact_items(ZMQ_Poller *poller) { ++ zmq_pollitem_t *items; ++ int count; ++ int old_count; ++ int next; ++ ++ count = poller->count; ++ /* if no free slot, then return. */ ++ if(poller->free_list < 0) return count; ++ old_count = count; ++ ++ items = poller->items; ++ next = 0; ++ /* find first free slot. */ ++ while(next < count && items[next].events != FREE_ITEM_EVENTS_TAG) { ++ ++next; ++ } ++ ++ /* move non-free slots into free slot. */ ++ count = next; ++ ++next; ++ while(next < old_count) { ++ if(items[next].events != FREE_ITEM_EVENTS_TAG) { ++ /* found non-free slot, move it to the current free slot. */ ++ items[count] = items[next]; ++ ++count; ++ } ++ ++next; ++ } ++ ++ /* clear old used-space */ ++ memset(&(items[count]), 0, ((old_count - count) * sizeof(zmq_pollitem_t))); ++ poller->count = count; ++ poller->free_list = -1; /* free list is now empty. */ ++ ++ assert(count <= poller->len); ++ return count; ++} ++ ++int poller_poll(ZMQ_Poller *poller, long timeout) { ++ int count; ++ /* remove free slots from items list. */ ++ if(poller->free_list >= 0) { ++ count = poller_compact_items(poller); ++ } else { ++ count = poller->count; ++ } ++ /* poll for events. */ ++ return zmq_poll(poller->items, count, timeout); ++} ++ ++int poller_next_revents(ZMQ_Poller *poller, int *revents) { ++ zmq_pollitem_t *items; ++ int count; ++ int idx; ++ int next; ++ ++ idx = poller->next; ++ /* do we need to poll for more events? */ ++ if(idx < 0) { ++ return idx; ++ } ++ items = poller->items; ++ count = poller->count; ++ /* find next item with pending events. */ ++ for(;idx < count; ++idx) { ++ /* did we find a pending event? */ ++ if(items[idx].revents != 0) { ++ *revents = items[idx].revents; ++ poller->next = idx+1; ++ return idx; ++ } ++ } ++ /* processed all pending events. */ ++ poller->next = -1; ++ *revents = 0; ++ return -1; ++} ++ ++ ++typedef struct ZMQ_Ctx ZMQ_Ctx; ++ ++typedef struct ZMQ_StopWatch ZMQ_StopWatch; ++ ++ ++ ++/* method: description */ ++static int ZErrors__description__meth(lua_State *L) { ++ const char * msg1 = NULL; ++ int err_type; ++ int err_num = -1; ++ ++ err_type = lua_type(L, 2); ++ if(err_type == LUA_TSTRING) { ++ lua_pushvalue(L, 2); ++ lua_rawget(L, 1); ++ if(lua_isnumber(L, -1)) { ++ err_num = lua_tointeger(L, -1); ++ } ++ lua_pop(L, 1); ++ } else if(err_type == LUA_TNUMBER) { ++ err_num = lua_tointeger(L, 2); ++ } else { ++ return luaL_argerror(L, 2, "expected string/number"); ++ } ++ if(err_num < 0) { ++ lua_pushnil(L); ++ lua_pushliteral(L, "UNKNOWN ERROR"); ++ return 2; ++ } ++ msg1 = strerror(err_num); ++ ++ lua_pushstring(L, msg1); ++ return 1; ++} ++ ++/* method: __index */ ++static int ZErrors____index__meth(lua_State *L) { ++ int err2; ++ const char * msg1 = NULL; ++ err2 = luaL_checkinteger(L,2); ++ switch(err2) { ++ case EAGAIN: ++ msg1 = "timeout"; ++ break; ++ case EINTR: ++ msg1 = "interrupted"; ++ break; ++#if defined(ETERM) ++ case ETERM: ++ msg1 = "closed"; ++ break; + #endif ++ default: ++ msg1 = zmq_strerror(err2); ++ break; ++ } ++ lua_pushvalue(L, 2); ++ lua_pushstring(L, msg1); ++ lua_rawset(L, 1); + +-typedef struct ZMQ_Socket ZMQ_Socket; +- +-#ifdef _WIN32 +-#include +-typedef SOCKET socket_t; +-#else +-typedef int socket_t; +-#endif ++ lua_pushstring(L, msg1); ++ return 1; ++} + +-/* socket option types. */ +-#define OPT_TYPE_NONE 0 +-#define OPT_TYPE_INT 1 +-#define OPT_TYPE_UINT32 2 +-#define OPT_TYPE_UINT64 3 +-#define OPT_TYPE_INT64 4 +-#define OPT_TYPE_STR 5 +-#define OPT_TYPE_FD 6 ++static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err) { ++ const char *err_str = NULL; ++ int num; ++ if(-1 == err) { ++ /* get ZErrors table. */ ++ lua_pushlightuserdata(L, zmq_ZErrors_key); ++ lua_rawget(L, LUA_REGISTRYINDEX); ++ /* convert zmq_errno to string. */ ++ num = zmq_errno(); ++ lua_pushinteger(L, num); ++ lua_gettable(L, -2); ++ /* remove ZErrors table. */ ++ lua_remove(L, -2); ++ if(!lua_isnil(L, -1)) { ++ /* found error. */ ++ return; ++ } ++ /* Unknown error. */ ++ lua_pop(L, 1); ++ lua_pushfstring(L, "UNKNOWN ERROR(%d)", num); ++ return; ++ } + +-static const int opt_types[] = { +- OPT_TYPE_NONE, /* 0 unused */ +- OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ +- OPT_TYPE_NONE, /* 2 unused */ +- OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ +- OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ +- OPT_TYPE_STR, /* 5 ZMQ_IDENTITY */ +- OPT_TYPE_STR, /* 6 ZMQ_SUBSCRIBE */ +- OPT_TYPE_STR, /* 7 ZMQ_UNSUBSCRIBE */ +- OPT_TYPE_INT64, /* 8 ZMQ_RATE */ +- OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ +- OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ +- OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ +- OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ +- OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ ++ if(err_str) { ++ lua_pushstring(L, err_str); ++ } else { ++ lua_pushnil(L); ++ } ++} + +-#if VERSION_2_1 +- OPT_TYPE_FD, /* 14 ZMQ_FD */ +- OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ +- OPT_TYPE_INT, /* 16 ZMQ_TYPE */ +- OPT_TYPE_INT, /* 17 ZMQ_LINGER */ +- OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ +- OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ +-#endif +-}; +-#if VERSION_2_1 +-#define MAX_OPTS ZMQ_BACKLOG +-#else +-#define MAX_OPTS ZMQ_RCVMORE +-#endif ++/* method: init */ ++static int zmq_msg_t__init__meth(lua_State *L) { ++ zmq_msg_t this1_store; ++ zmq_msg_t * this1 = &(this1_store); ++ ZMQ_Error rc_zmq_msg_init2 = 0; ++ rc_zmq_msg_init2 = zmq_msg_init(this1); ++ if(!(-1 == rc_zmq_msg_init2)) { ++ obj_type_zmq_msg_t_push(L, this1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_init2); ++ return 2; ++} + ++/* method: init_size */ ++static int zmq_msg_t__init_size__meth(lua_State *L) { ++ size_t size1; ++ zmq_msg_t this1_store; ++ zmq_msg_t * this1 = &(this1_store); ++ ZMQ_Error rc_zmq_msg_init_size2 = 0; ++ size1 = luaL_checkinteger(L,1); ++ rc_zmq_msg_init_size2 = zmq_msg_init_size(this1, size1); ++ if(!(-1 == rc_zmq_msg_init_size2)) { ++ obj_type_zmq_msg_t_push(L, this1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_init_size2); ++ return 2; ++} + +-static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { +- ZMQ_Error err; +- zmq_msg_t msg; +- /* initialize message */ +- err = zmq_msg_init_size(&msg, data_len); +- if(0 == err) { ++/* method: init_data */ ++static int zmq_msg_t__init_data__meth(lua_State *L) { ++ size_t data_len1; ++ const char * data1; ++ zmq_msg_t this1_store; ++ zmq_msg_t * this1 = &(this1_store); ++ ZMQ_Error err2 = 0; ++ data1 = luaL_checklstring(L,1,&(data_len1)); ++ err2 = zmq_msg_init_size(this1, data_len1); ++ if(0 == err2) { + /* fill message */ +- memcpy(zmq_msg_data(&msg), data, data_len); +- /* send message */ +- err = zmq_send(sock, &msg, flags); +- /* close message */ +- zmq_msg_close(&msg); ++ memcpy(zmq_msg_data(this1), data1, data_len1); + } +- return err; ++ ++ if(!(-1 == err2)) { ++ obj_type_zmq_msg_t_push(L, this1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, err2); ++ return 2; + } + +-struct ZMQ_Poller { +- zmq_pollitem_t *items; +- int next; +- int count; +- int free_list; +- int len; +-}; ++/* method: _priv */ ++static int zmq_msg_t__delete__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ ZMQ_Error rc_zmq_msg_close1 = 0; ++ this1 = obj_type_zmq_msg_t_delete(L,1); ++ rc_zmq_msg_close1 = zmq_msg_close(this1); ++ /* check for error. */ ++ if((-1 == rc_zmq_msg_close1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + ++/* method: close */ ++static int zmq_msg_t__close__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ ZMQ_Error rc_zmq_msg_close1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ rc_zmq_msg_close1 = zmq_msg_close(this1); ++ /* check for error. */ ++ if((-1 == rc_zmq_msg_close1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +-typedef struct ZMQ_Poller ZMQ_Poller; ++/* method: move */ ++static int zmq_msg_t__move__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ zmq_msg_t * src2; ++ ZMQ_Error rc_zmq_msg_move1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ src2 = obj_type_zmq_msg_t_check(L,2); ++ rc_zmq_msg_move1 = zmq_msg_move(this1, src2); ++ /* check for error. */ ++ if((-1 == rc_zmq_msg_move1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_move1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +-#define FREE_ITEM_EVENTS_TAG ((short)0xFFFF) ++/* method: copy */ ++static int zmq_msg_t__copy__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ zmq_msg_t * src2; ++ ZMQ_Error rc_zmq_msg_copy1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ src2 = obj_type_zmq_msg_t_check(L,2); ++ rc_zmq_msg_copy1 = zmq_msg_copy(this1, src2); ++ /* check for error. */ ++ if((-1 == rc_zmq_msg_copy1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_msg_copy1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +-#define ITEM_TO_INDEX(items, item) (item - (items)) ++/* method: set_data */ ++static int zmq_msg_t__set_data__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ size_t data_len2; ++ const char * data2; ++ ZMQ_Error err1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ data2 = luaL_checklstring(L,2,&(data_len2)); ++ /* check message data size. */ ++ if(zmq_msg_size(this1) != data_len2) { ++ /* need to resize message. */ ++ zmq_msg_close(this1); /* close old message, to free old data. */ ++ err1 = zmq_msg_init_size(this1, data_len2); /* re-initialize message. */ ++ if(0 != err1) { ++ luaL_error(L, "set_data() failed: %s", get_zmq_strerror()); ++ } ++ } ++ /* copy data into message */ ++ memcpy(zmq_msg_data(this1), data2, data_len2); + +-static int poller_resize_items(ZMQ_Poller *poller, int len) { +- int old_len = poller->len; ++ /* check for error. */ ++ if((-1 == err1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, err1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++ ++/* method: data */ ++static int zmq_msg_t__data__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ void * rc_zmq_msg_data1 = NULL; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ rc_zmq_msg_data1 = zmq_msg_data(this1); ++ lua_pushlightuserdata(L, rc_zmq_msg_data1); ++ return 1; ++} ++ ++/* method: set_size */ ++static int zmq_msg_t__set_size__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ size_t size2; ++ ZMQ_Error err1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ size2 = luaL_checkinteger(L,2); ++ /* check message data size. */ ++ if(zmq_msg_size(this1) != size2) { ++ /* need to resize message. */ ++ zmq_msg_close(this1); /* close old message, to free old data. */ ++ err1 = zmq_msg_init_size(this1, size2); /* re-initialize message. */ ++ if(0 != err1) { ++ luaL_error(L, "set_size() failed: %s", get_zmq_strerror()); ++ } ++ } ++ ++ /* check for error. */ ++ if((-1 == err1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, err1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++ ++/* method: size */ ++static int zmq_msg_t__size__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ size_t size1 = 0; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ size1 = zmq_msg_size(this1); ++ lua_pushinteger(L, size1); ++ return 1; ++} ++ ++/* method: __tostring */ ++static int zmq_msg_t____tostring__meth(lua_State *L) { ++ zmq_msg_t * this1; ++ size_t data_len1 = 0; ++ const char * data1 = NULL; ++ this1 = obj_type_zmq_msg_t_check(L,1); ++ data1 = zmq_msg_data(this1); ++ data_len1 = zmq_msg_size(this1); ++ ++ if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); ++ return 1; ++} ++ ++/* method: close */ ++static int ZMQ_Socket__close__meth(lua_State *L) { ++ int this_flags1 = 0; ++ ZMQ_Socket * this1; ++ ZMQ_Error rc_zmq_close1 = 0; ++ this1 = obj_type_ZMQ_Socket_delete(L,1,&(this_flags1)); ++ if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } ++ rc_zmq_close1 = zmq_close(this1); ++ /* check for error. */ ++ if((-1 == rc_zmq_close1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_close1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++ ++/* method: bind */ ++static int ZMQ_Socket__bind__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t addr_len2; ++ const char * addr2; ++ ZMQ_Error rc_zmq_bind1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ addr2 = luaL_checklstring(L,2,&(addr_len2)); ++ rc_zmq_bind1 = zmq_bind(this1, addr2); ++ /* check for error. */ ++ if((-1 == rc_zmq_bind1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_bind1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- /* make sure new length is atleast as large as items count. */ +- len = (poller->count <= len) ? len : poller->count; ++/* method: unbind */ ++#if (VERSION_3_2) ++static int ZMQ_Socket__unbind__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t addr_len2; ++ const char * addr2; ++ ZMQ_Error rc_zmq_unbind1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ addr2 = luaL_checklstring(L,2,&(addr_len2)); ++ rc_zmq_unbind1 = zmq_unbind(this1, addr2); ++ /* check for error. */ ++ if((-1 == rc_zmq_unbind1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_unbind1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +- /* if the new length is the same as the old length, then don't try to resize. */ +- if(old_len == len) return len; ++/* method: connect */ ++static int ZMQ_Socket__connect__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t addr_len2; ++ const char * addr2; ++ ZMQ_Error rc_zmq_connect1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ addr2 = luaL_checklstring(L,2,&(addr_len2)); ++ rc_zmq_connect1 = zmq_connect(this1, addr2); ++ /* check for error. */ ++ if((-1 == rc_zmq_connect1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_connect1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- poller->items = (zmq_pollitem_t *)realloc(poller->items, len * sizeof(zmq_pollitem_t)); +- poller->len = len; +- if(len > old_len) { +- /* clear new space. */ +- memset(&(poller->items[old_len]), 0, (len - old_len) * sizeof(zmq_pollitem_t)); +- } +- return len; ++/* method: disconnect */ ++#if (VERSION_3_2) ++static int ZMQ_Socket__disconnect__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t addr_len2; ++ const char * addr2; ++ ZMQ_Error rc_zmq_disconnect1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ addr2 = luaL_checklstring(L,2,&(addr_len2)); ++ rc_zmq_disconnect1 = zmq_disconnect(this1, addr2); ++ /* check for error. */ ++ if((-1 == rc_zmq_disconnect1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_disconnect1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; + } ++#endif + +-static int poller_find_sock_item(ZMQ_Poller *poller, ZMQ_Socket *sock) { +- zmq_pollitem_t *items; +- int count; +- int n; ++/* method: setopt */ ++static int ZMQ_Socket__setopt__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ uint32_t opt2; ++ ZMQ_Error err1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ opt2 = luaL_checkinteger(L,2); ++ size_t val_len; ++ const void *val; + +- /* find ZMQ_Socket */ +- items = poller->items; +- count = poller->count; +- for(n=0; n < count; n++) { +- if(items[n].socket == sock) return n; ++#if defined(VERSION_2_1) || defined(VERSION_3_0) ++ socket_t fd_val; ++#endif ++ int int_val; ++ uint32_t uint32_val; ++ uint64_t uint64_val; ++ int64_t int64_val; ++ ++#if VERSION_3_0 ++ /* 3.0 backwards compatibility support for HWM. */ ++ if(opt2 == ZMQ_HWM) { ++ int_val = luaL_checklong(L, 3); ++ val = &int_val; ++ val_len = sizeof(int_val); ++ err1 = zmq_setsockopt(this1, ZMQ_SNDHWM, val, val_len); ++ if(-1 != err1) { ++ err1 = zmq_setsockopt(this1, ZMQ_RCVHWM, val, val_len); ++ } ++ goto finished; + } +- /* not found. */ +- return -1; +-} ++#endif + +-static int poller_find_fd_item(ZMQ_Poller *poller, socket_t fd) { +- zmq_pollitem_t *items; +- int count; +- int n; ++ if(opt2 > MAX_OPTS) { ++ return luaL_argerror(L, 2, "Invalid socket option."); ++ } + +- /* find fd */ +- items = poller->items; +- count = poller->count; +- for(n=0; n < count; n++) { +- if(items[n].fd == fd) return n; ++ switch(opt_types[opt2]) { ++#if defined(VERSION_2_1) || defined(VERSION_3_0) ++ case OPT_TYPE_FD: ++ fd_val = luaL_checklong(L, 3); ++ val = &fd_val; ++ val_len = sizeof(fd_val); ++ break; ++#endif ++ case OPT_TYPE_INT: ++ int_val = luaL_checklong(L, 3); ++ val = &int_val; ++ val_len = sizeof(int_val); ++ break; ++ case OPT_TYPE_UINT32: ++ uint32_val = luaL_checklong(L, 3); ++ val = &uint32_val; ++ val_len = sizeof(uint32_val); ++ break; ++ case OPT_TYPE_UINT64: ++ uint64_val = luaL_checklong(L, 3); ++ val = &uint64_val; ++ val_len = sizeof(uint64_val); ++ break; ++ case OPT_TYPE_INT64: ++ int64_val = luaL_checklong(L, 3); ++ val = &int64_val; ++ val_len = sizeof(int64_val); ++ break; ++ case OPT_TYPE_BLOB: ++ val = luaL_checklstring(L, 3, &(val_len)); ++ break; ++ default: ++ printf("Invalid socket option type, this shouldn't happen.\n"); ++ abort(); ++ break; + } +- /* not found. */ +- return -1; +-} ++ err1 = zmq_setsockopt(this1, opt2, val, val_len); ++finished: + +-static void poller_remove_item(ZMQ_Poller *poller, int idx) { +- zmq_pollitem_t *items; +- int free_list; +- int count; ++ /* check for error. */ ++ if((-1 == err1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, err1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- count = poller->count; +- /* no item to remove. */ +- if(idx >= count || count == 0) return; ++/* method: getopt */ ++static int ZMQ_Socket__getopt__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ uint32_t opt2; ++ ZMQ_Error err2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ opt2 = luaL_checkinteger(L,2); ++ size_t val_len; + +- items = poller->items; +- free_list = poller->free_list; ++#if defined(VERSION_2_1) || defined(VERSION_3_0) ++ socket_t fd_val; ++#endif ++ int int_val; ++ uint32_t uint32_val; ++ uint64_t uint64_val; ++ int64_t int64_val; ++#define STR_MAX 255 ++ char str_val[STR_MAX]; + +- /* link new free slot to head of free list. */ +- if(free_list >= 0 && free_list < count) { +- /* use socket pointer for free list's 'next' field. */ +- items[idx].socket = &(items[free_list]); +- } else { +- /* free list is empty mark poller slot as the end. */ +- items[idx].socket = NULL; ++ if(opt2 > MAX_OPTS) { ++ lua_pushnil(L); ++ lua_pushliteral(L, "Invalid socket option."); ++ return 2; + } +- poller->free_list = idx; +- /* mark poller slot as a free slot. */ +- items[idx].events = FREE_ITEM_EVENTS_TAG; +- /* clear old revents. */ +- items[idx].revents = 0; +-} +- +-static int poller_get_free_item(ZMQ_Poller *poller) { +- zmq_pollitem_t *curr; +- zmq_pollitem_t *next; +- int count; +- int idx; + +- count = poller->count; +- idx = poller->free_list; +- /* check for a free slot in the free list. */ +- if(idx >= 0 && idx < count) { +- /* remove free slot from free list. */ +- curr = &(poller->items[idx]); +- /* valid free slot. */ +- assert(curr->events == FREE_ITEM_EVENTS_TAG); +- /* is poller the last free slot? */ +- next = ((zmq_pollitem_t *)curr->socket); +- if(next != NULL) { +- /* set next free slot as head of free list. */ +- poller->free_list = ITEM_TO_INDEX(poller->items, next); +- } else { +- /* free list is empty now. */ +- poller->free_list = -1; ++ switch(opt_types[opt2]) { ++#if defined(VERSION_2_1) || defined(VERSION_3_0) ++ case OPT_TYPE_FD: ++ val_len = sizeof(fd_val); ++ err2 = zmq_getsockopt(this1, opt2, &fd_val, &val_len); ++ if(0 == err2) { ++ lua_pushinteger(L, (lua_Integer)fd_val); ++ return 1; + } +- /* clear slot */ +- memset(curr, 0, sizeof(zmq_pollitem_t)); +- return idx; ++ break; ++#endif ++ case OPT_TYPE_INT: ++ val_len = sizeof(int_val); ++ err2 = zmq_getsockopt(this1, opt2, &int_val, &val_len); ++ if(0 == err2) { ++ lua_pushinteger(L, (lua_Integer)int_val); ++ return 1; ++ } ++ break; ++ case OPT_TYPE_UINT32: ++ val_len = sizeof(uint32_val); ++ err2 = zmq_getsockopt(this1, opt2, &uint32_val, &val_len); ++ if(0 == err2) { ++ lua_pushinteger(L, (lua_Integer)uint32_val); ++ return 1; ++ } ++ break; ++ case OPT_TYPE_UINT64: ++ val_len = sizeof(uint64_val); ++ err2 = zmq_getsockopt(this1, opt2, &uint64_val, &val_len); ++ if(0 == err2) { ++ lua_pushinteger(L, (lua_Integer)uint64_val); ++ return 1; ++ } ++ break; ++ case OPT_TYPE_INT64: ++ val_len = sizeof(int64_val); ++ err2 = zmq_getsockopt(this1, opt2, &int64_val, &val_len); ++ if(0 == err2) { ++ lua_pushinteger(L, (lua_Integer)int64_val); ++ return 1; ++ } ++ break; ++ case OPT_TYPE_BLOB: ++ val_len = STR_MAX; ++ err2 = zmq_getsockopt(this1, opt2, str_val, &val_len); ++ if(0 == err2) { ++ lua_pushlstring(L, str_val, val_len); ++ return 1; ++ } ++#undef STR_MAX ++ break; ++ default: ++ printf("Invalid socket option type, this shouldn't happen.\n"); ++ abort(); ++ break; + } ++ lua_pushnil(L); + +- idx = count; +- poller->count = ++count; +- /* make room for new item. */ +- if(count >= poller->len) { +- poller_resize_items(poller, poller->len + 10); +- } +- return idx; ++ error_code__ZMQ_Error__push(L, err2); ++ return 2; + } + +-static int poller_compact_items(ZMQ_Poller *poller) { +- zmq_pollitem_t *items; +- int count; +- int old_count; +- int next; ++/* method: send_msg */ ++static int ZMQ_Socket__send_msg__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ zmq_msg_t * msg2; ++ int flags3; ++ ZMQ_Error rc_zmq_sendmsg1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ msg2 = obj_type_zmq_msg_t_check(L,2); ++ flags3 = luaL_optinteger(L,3,0); ++ rc_zmq_sendmsg1 = zmq_sendmsg(this1, msg2, flags3); ++ /* check for error. */ ++ if((-1 == rc_zmq_sendmsg1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_sendmsg1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- count = poller->count; +- /* if no free slot, then return. */ +- if(poller->free_list < 0) return count; +- old_count = count; ++/* method: send */ ++static int ZMQ_Socket__send__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t data_len2; ++ const char * data2; ++ int flags3; ++ ZMQ_Error rc_simple_zmq_send1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ data2 = luaL_checklstring(L,2,&(data_len2)); ++ flags3 = luaL_optinteger(L,3,0); ++ rc_simple_zmq_send1 = simple_zmq_send(this1, data2, data_len2, flags3); ++ /* check for error. */ ++ if((-1 == rc_simple_zmq_send1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_simple_zmq_send1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- items = poller->items; +- next = 0; +- /* find first free slot. */ +- while(next < count && items[next].events != FREE_ITEM_EVENTS_TAG) { +- ++next; +- } ++/* method: recv_msg */ ++static int ZMQ_Socket__recv_msg__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ zmq_msg_t * msg2; ++ int flags3; ++ ZMQ_Error rc_zmq_recvmsg1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ msg2 = obj_type_zmq_msg_t_check(L,2); ++ flags3 = luaL_optinteger(L,3,0); ++ rc_zmq_recvmsg1 = zmq_recvmsg(this1, msg2, flags3); ++ /* check for error. */ ++ if((-1 == rc_zmq_recvmsg1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_recvmsg1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + +- /* move non-free slots into free slot. */ +- count = next; +- ++next; +- while(next < old_count) { +- if(items[next].events != FREE_ITEM_EVENTS_TAG) { +- /* found non-free slot, move it to the current free slot. */ +- items[count] = items[next]; +- ++count; ++/* method: recv */ ++static int ZMQ_Socket__recv__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int flags2; ++ size_t data_len1 = 0; ++ const char * data1 = NULL; ++ ZMQ_Error err2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ flags2 = luaL_optinteger(L,2,0); ++ zmq_msg_t msg; ++ /* initialize message */ ++ err2 = zmq_msg_init(&msg); ++ if(0 == err2) { ++ /* receive message */ ++ err2 = zmq_recvmsg(this1, &msg, flags2); ++ if(err2 >= 0) { ++ data1 = zmq_msg_data(&msg); ++ data_len1 = zmq_msg_size(&msg); + } +- ++next; + } + +- /* clear old used-space */ +- memset(&(items[count]), 0, ((old_count - count) * sizeof(zmq_pollitem_t))); +- poller->count = count; +- poller->free_list = -1; /* free list is now empty. */ ++ if(!(-1 == err2)) { ++ if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, err2); ++ /* close message */ ++ zmq_msg_close(&msg); + +- assert(count <= poller->len); +- return count; ++ return 2; + } + +-static int poller_poll(ZMQ_Poller *poller, long timeout) { +- int count; +- /* remove free slots from items list. */ +- count = poller_compact_items(poller); +- /* poll for events. */ +- return zmq_poll(poller->items, count, timeout); ++/* method: hwm */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__hwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_hwm2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_hwm2 = lzmq_socket_hwm(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_hwm2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_hwm2); ++ return 2; + } ++#endif + ++/* method: set_hwm */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_hwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_hwm1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_hwm1 = lzmq_socket_set_hwm(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_hwm1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_hwm1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +-typedef struct ZMQ_Ctx ZMQ_Ctx; ++/* method: swap */ ++#if (VERSION_2_0) ++static int ZMQ_Socket__swap__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_swap2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_swap2 = lzmq_socket_swap(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_swap2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_swap2); ++ return 2; ++} ++#endif + +-typedef struct ZMQ_StopWatch ZMQ_StopWatch; ++/* method: set_swap */ ++#if (VERSION_2_0) ++static int ZMQ_Socket__set_swap__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_swap1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_swap1 = lzmq_socket_set_swap(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_swap1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_swap1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +-/* +- * This wrapper function is to make the EAGAIN/ETERM error messages more like +- * what is returned by LuaSocket. +- */ +-static const char *get_zmq_strerror() { +- int err = zmq_errno(); +- switch(err) { +- case EAGAIN: +- return "timeout"; +- break; +-#if defined(ETERM) +- case ETERM: +- return "closed"; +- break; ++/* method: affinity */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__affinity__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ uint64_t value1 = 0; ++ ZMQ_Error rc_lzmq_socket_affinity2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_affinity2 = lzmq_socket_affinity(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_affinity2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_affinity2); ++ return 2; ++} + #endif +- default: +- break; +- } +- return zmq_strerror(err); ++ ++/* method: set_affinity */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_affinity__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ uint64_t value2; ++ ZMQ_Error rc_lzmq_socket_set_affinity1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_affinity1 = lzmq_socket_set_affinity(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_affinity1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_affinity1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; + } ++#endif + ++/* method: identity */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__identity__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t value_len1 = 0; ++ char * value1 = NULL; ++ ZMQ_Error rc_lzmq_socket_identity2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_identity2 = lzmq_socket_identity(this1, value1, &(value_len1)); ++ if(!(-1 == rc_lzmq_socket_identity2)) { ++ if(value1 == NULL) lua_pushnil(L); else lua_pushlstring(L, value1,value_len1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_identity2); ++ return 2; ++} ++#endif + ++/* method: set_identity */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_identity__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t value_len2; ++ const char * value2; ++ ZMQ_Error rc_lzmq_socket_set_identity1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checklstring(L,2,&(value_len2)); ++ rc_lzmq_socket_set_identity1 = lzmq_socket_set_identity(this1, value2, value_len2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_identity1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_identity1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + ++/* method: subscribe */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__subscribe__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t value_len2; ++ const char * value2; ++ ZMQ_Error rc_lzmq_socket_subscribe1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checklstring(L,2,&(value_len2)); ++ rc_lzmq_socket_subscribe1 = lzmq_socket_subscribe(this1, value2, value_len2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_subscribe1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_subscribe1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +-static void error_code__ZMQ_Error__push(lua_State *L, ZMQ_Error err) { +- const char *err_str = NULL; +- if(-1 == err) { +- err_str = get_zmq_strerror(); +- } ++/* method: unsubscribe */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__unsubscribe__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ size_t value_len2; ++ const char * value2; ++ ZMQ_Error rc_lzmq_socket_unsubscribe1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checklstring(L,2,&(value_len2)); ++ rc_lzmq_socket_unsubscribe1 = lzmq_socket_unsubscribe(this1, value2, value_len2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_unsubscribe1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_unsubscribe1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +- if(err_str) { +- lua_pushstring(L, err_str); +- } else { +- lua_pushnil(L); +- } ++/* method: rate */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__rate__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_rate2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_rate2 = lzmq_socket_rate(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_rate2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rate2); ++ return 2; + } ++#endif + +-/* method: init */ +-static int zmq_msg_t__init__meth(lua_State *L) { +- int this_flags1 = OBJ_UDATA_FLAG_OWN; +- zmq_msg_t * this1; +- ZMQ_Error err2 = 0; +- zmq_msg_t tmp; +- this1 = &tmp; +- err2 = zmq_msg_init(this1); ++/* method: set_rate */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_rate__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_rate1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_rate1 = lzmq_socket_set_rate(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_rate1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rate1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +- if(!(-1 == err2)) { +- obj_type_zmq_msg_t_push(L, this1, this_flags1); ++/* method: recovery_ivl */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__recovery_ivl__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_recovery_ivl2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_recovery_ivl2 = lzmq_socket_recovery_ivl(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_recovery_ivl2)) { ++ lua_pushinteger(L, value1); + } else { + lua_pushnil(L); + } +- error_code__ZMQ_Error__push(L, err2); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_recovery_ivl2); + return 2; + } ++#endif + +-/* method: init_size */ +-static int zmq_msg_t__init_size__meth(lua_State *L) { +- size_t size1 = luaL_checkinteger(L,1); +- int this_flags1 = OBJ_UDATA_FLAG_OWN; +- zmq_msg_t * this1; +- ZMQ_Error err2 = 0; +- zmq_msg_t tmp; +- this1 = &tmp; +- err2 = zmq_msg_init_size(this1, size1); ++/* method: set_recovery_ivl */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_recovery_ivl__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_recovery_ivl1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_recovery_ivl1 = lzmq_socket_set_recovery_ivl(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_recovery_ivl1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_recovery_ivl1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + +- if(!(-1 == err2)) { +- obj_type_zmq_msg_t_push(L, this1, this_flags1); ++/* method: mcast_loop */ ++#if (VERSION_2_0) ++static int ZMQ_Socket__mcast_loop__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_mcast_loop2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_mcast_loop2 = lzmq_socket_mcast_loop(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_mcast_loop2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_mcast_loop2); ++ return 2; ++} ++#endif ++ ++/* method: set_mcast_loop */ ++#if (VERSION_2_0) ++static int ZMQ_Socket__set_mcast_loop__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_mcast_loop1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_mcast_loop1 = lzmq_socket_set_mcast_loop(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_mcast_loop1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_mcast_loop1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif ++ ++/* method: sndbuf */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__sndbuf__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_sndbuf2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_sndbuf2 = lzmq_socket_sndbuf(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_sndbuf2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndbuf2); ++ return 2; ++} ++#endif ++ ++/* method: set_sndbuf */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_sndbuf__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_sndbuf1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_sndbuf1 = lzmq_socket_set_sndbuf(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_sndbuf1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndbuf1); + } else { ++ lua_pushboolean(L, 1); + lua_pushnil(L); + } +- error_code__ZMQ_Error__push(L, err2); + return 2; + } ++#endif + +-/* method: init_data */ +-static int zmq_msg_t__init_data__meth(lua_State *L) { +- size_t data_len1; +- const char * data1 = luaL_checklstring(L,1,&(data_len1)); +- int this_flags1 = OBJ_UDATA_FLAG_OWN; +- zmq_msg_t * this1; +- ZMQ_Error err2 = 0; +- zmq_msg_t tmp; +- this1 = &tmp; +- err2 = zmq_msg_init_size(this1, data_len1); +- if(0 == err2) { +- /* fill message */ +- memcpy(zmq_msg_data(this1), data1, data_len1); +- } +- +- if(!(-1 == err2)) { +- obj_type_zmq_msg_t_push(L, this1, this_flags1); ++/* method: rcvbuf */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__rcvbuf__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_rcvbuf2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_rcvbuf2 = lzmq_socket_rcvbuf(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_rcvbuf2)) { ++ lua_pushinteger(L, value1); + } else { + lua_pushnil(L); + } +- error_code__ZMQ_Error__push(L, err2); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvbuf2); + return 2; + } ++#endif + +-/* method: delete */ +-static int zmq_msg_t__delete__meth(lua_State *L) { +- int this_flags1 = 0; +- zmq_msg_t * this1 = obj_type_zmq_msg_t_delete(L,1,&(this_flags1)); +- ZMQ_Error rc_zmq_msg_close1 = 0; +- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } +- rc_zmq_msg_close1 = zmq_msg_close(this1); ++/* method: set_rcvbuf */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__set_rcvbuf__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_rcvbuf1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_rcvbuf1 = lzmq_socket_set_rcvbuf(this1, value2); + /* check for error. */ +- if((-1 == rc_zmq_msg_close1)) { ++ if((-1 == rc_lzmq_socket_set_rcvbuf1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvbuf1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: close */ +-static int zmq_msg_t__close__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- ZMQ_Error rc_zmq_msg_close1 = 0; +- rc_zmq_msg_close1 = zmq_msg_close(this1); +- /* check for error. */ +- if((-1 == rc_zmq_msg_close1)) { +- lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_msg_close1); ++/* method: rcvmore */ ++#if (VERSION_2_0|VERSION_3_0) ++static int ZMQ_Socket__rcvmore__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_rcvmore2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_rcvmore2 = lzmq_socket_rcvmore(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_rcvmore2)) { ++ lua_pushinteger(L, value1); + } else { +- lua_pushboolean(L, 1); + lua_pushnil(L); + } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvmore2); + return 2; + } ++#endif + +-/* method: move */ +-static int zmq_msg_t__move__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- zmq_msg_t * src2 = obj_type_zmq_msg_t_check(L,2); +- ZMQ_Error rc_zmq_msg_move1 = 0; +- rc_zmq_msg_move1 = zmq_msg_move(this1, src2); +- /* check for error. */ +- if((-1 == rc_zmq_msg_move1)) { +- lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_msg_move1); ++/* method: fd */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__fd__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_fd2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_fd2 = lzmq_socket_fd(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_fd2)) { ++ lua_pushinteger(L, value1); + } else { +- lua_pushboolean(L, 1); + lua_pushnil(L); + } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_fd2); + return 2; + } ++#endif + +-/* method: copy */ +-static int zmq_msg_t__copy__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- zmq_msg_t * src2 = obj_type_zmq_msg_t_check(L,2); +- ZMQ_Error rc_zmq_msg_copy1 = 0; +- rc_zmq_msg_copy1 = zmq_msg_copy(this1, src2); +- /* check for error. */ +- if((-1 == rc_zmq_msg_copy1)) { ++/* method: events */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__events__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_events2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_events2 = lzmq_socket_events(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_events2)) { ++ lua_pushinteger(L, value1); ++ } else { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_msg_copy1); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_events2); ++ return 2; ++} ++#endif ++ ++/* method: type */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__type__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_type2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_type2 = lzmq_socket_type(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_type2)) { ++ lua_pushinteger(L, value1); + } else { +- lua_pushboolean(L, 1); + lua_pushnil(L); + } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_type2); + return 2; + } ++#endif + +-/* method: set_data */ +-static int zmq_msg_t__set_data__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- size_t data_len2; +- const char * data2 = luaL_checklstring(L,2,&(data_len2)); +- ZMQ_Error err1 = 0; +- /* check message data size. */ +- if(zmq_msg_size(this1) != data_len2) { +- /* need to resize message. */ +- zmq_msg_close(this1); /* close old message, to free old data. */ +- err1 = zmq_msg_init_size(this1, data_len2); /* re-initialize message. */ +- if(0 != err1) { +- luaL_error(L, "set_data() failed: %s", get_zmq_strerror()); +- } +- } +- /* copy data into message */ +- memcpy(zmq_msg_data(this1), data2, data_len2); ++/* method: linger */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__linger__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_linger2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_linger2 = lzmq_socket_linger(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_linger2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_linger2); ++ return 2; ++} ++#endif + ++/* method: set_linger */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__set_linger__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_linger1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_linger1 = lzmq_socket_set_linger(this1, value2); + /* check for error. */ +- if((-1 == err1)) { ++ if((-1 == rc_lzmq_socket_set_linger1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, err1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_linger1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: data */ +-static int zmq_msg_t__data__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- void * rc_zmq_msg_data1 = NULL; +- rc_zmq_msg_data1 = zmq_msg_data(this1); +- lua_pushlightuserdata(L, rc_zmq_msg_data1); +- return 1; ++/* method: reconnect_ivl */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__reconnect_ivl__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_reconnect_ivl2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_reconnect_ivl2 = lzmq_socket_reconnect_ivl(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_reconnect_ivl2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_reconnect_ivl2); ++ return 2; + } ++#endif + +-/* method: set_size */ +-static int zmq_msg_t__set_size__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- size_t size2 = luaL_checkinteger(L,2); +- ZMQ_Error err1 = 0; +- /* check message data size. */ +- if(zmq_msg_size(this1) != size2) { +- /* need to resize message. */ +- zmq_msg_close(this1); /* close old message, to free old data. */ +- err1 = zmq_msg_init_size(this1, size2); /* re-initialize message. */ +- if(0 != err1) { +- luaL_error(L, "set_size() failed: %s", get_zmq_strerror()); +- } +- } +- ++/* method: set_reconnect_ivl */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__set_reconnect_ivl__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_reconnect_ivl1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_reconnect_ivl1 = lzmq_socket_set_reconnect_ivl(this1, value2); + /* check for error. */ +- if((-1 == err1)) { ++ if((-1 == rc_lzmq_socket_set_reconnect_ivl1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, err1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_reconnect_ivl1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: size */ +-static int zmq_msg_t__size__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- size_t rc_zmq_msg_size1 = 0; +- rc_zmq_msg_size1 = zmq_msg_size(this1); +- lua_pushinteger(L, rc_zmq_msg_size1); +- return 1; +-} +- +-/* method: __tostring */ +-static int zmq_msg_t____tostring__meth(lua_State *L) { +- zmq_msg_t * this1 = obj_type_zmq_msg_t_check(L,1); +- size_t data_len1 = 0; +- const char * data1 = NULL; +- data1 = zmq_msg_data(this1); +- data_len1 = zmq_msg_size(this1); +- +- if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); +- return 1; ++/* method: backlog */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__backlog__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_backlog2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_backlog2 = lzmq_socket_backlog(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_backlog2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_backlog2); ++ return 2; + } ++#endif + +-/* method: close */ +-static int ZMQ_Socket__close__meth(lua_State *L) { +- int this_flags1 = 0; +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_delete(L,1,&(this_flags1)); +- ZMQ_Error rc_zmq_close1 = 0; +- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } +- rc_zmq_close1 = zmq_close(this1); ++/* method: set_backlog */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__set_backlog__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_backlog1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_backlog1 = lzmq_socket_set_backlog(this1, value2); + /* check for error. */ +- if((-1 == rc_zmq_close1)) { ++ if((-1 == rc_lzmq_socket_set_backlog1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_close1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_backlog1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: bind */ +-static int ZMQ_Socket__bind__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- size_t addr_len2; +- const char * addr2 = luaL_checklstring(L,2,&(addr_len2)); +- ZMQ_Error rc_zmq_bind1 = 0; +- rc_zmq_bind1 = zmq_bind(this1, addr2); +- /* check for error. */ +- if((-1 == rc_zmq_bind1)) { +- lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_bind1); ++/* method: recovery_ivl_msec */ ++#if (VERSION_2_1) ++static int ZMQ_Socket__recovery_ivl_msec__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int64_t value1 = 0; ++ ZMQ_Error rc_lzmq_socket_recovery_ivl_msec2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_recovery_ivl_msec2 = lzmq_socket_recovery_ivl_msec(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_recovery_ivl_msec2)) { ++ lua_pushinteger(L, value1); + } else { +- lua_pushboolean(L, 1); + lua_pushnil(L); + } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_recovery_ivl_msec2); + return 2; + } ++#endif + +-/* method: connect */ +-static int ZMQ_Socket__connect__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- size_t addr_len2; +- const char * addr2 = luaL_checklstring(L,2,&(addr_len2)); +- ZMQ_Error rc_zmq_connect1 = 0; +- rc_zmq_connect1 = zmq_connect(this1, addr2); ++/* method: set_recovery_ivl_msec */ ++#if (VERSION_2_1) ++static int ZMQ_Socket__set_recovery_ivl_msec__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int64_t value2; ++ ZMQ_Error rc_lzmq_socket_set_recovery_ivl_msec1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_recovery_ivl_msec1 = lzmq_socket_set_recovery_ivl_msec(this1, value2); + /* check for error. */ +- if((-1 == rc_zmq_connect1)) { ++ if((-1 == rc_lzmq_socket_set_recovery_ivl_msec1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_connect1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_recovery_ivl_msec1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } +- +-/* method: setopt */ +-static int ZMQ_Socket__setopt__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- uint32_t opt2 = luaL_checkinteger(L,2); +- ZMQ_Error err1 = 0; +- size_t val_len; +- const void *val; +- +-#if VERSION_2_1 +- socket_t fd_val; + #endif +- int int_val; +- uint32_t uint32_val; +- uint64_t uint64_val; +- int64_t int64_val; +- +- if(opt2 > MAX_OPTS) { +- return luaL_argerror(L, 2, "Invalid socket option."); +- } + +- switch(opt_types[opt2]) { +-#if VERSION_2_1 +- case OPT_TYPE_FD: +- fd_val = luaL_checklong(L, 3); +- val = &fd_val; +- val_len = sizeof(fd_val); +- break; ++/* method: reconnect_ivl_max */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__reconnect_ivl_max__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_reconnect_ivl_max2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_reconnect_ivl_max2 = lzmq_socket_reconnect_ivl_max(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_reconnect_ivl_max2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_reconnect_ivl_max2); ++ return 2; ++} + #endif +- case OPT_TYPE_INT: +- int_val = luaL_checklong(L, 3); +- val = &int_val; +- val_len = sizeof(int_val); +- break; +- case OPT_TYPE_UINT32: +- uint32_val = luaL_checklong(L, 3); +- val = &uint32_val; +- val_len = sizeof(uint32_val); +- break; +- case OPT_TYPE_UINT64: +- uint64_val = luaL_checklong(L, 3); +- val = &uint64_val; +- val_len = sizeof(uint64_val); +- break; +- case OPT_TYPE_INT64: +- int64_val = luaL_checklong(L, 3); +- val = &int64_val; +- val_len = sizeof(int64_val); +- break; +- case OPT_TYPE_STR: +- val = luaL_checklstring(L, 3, &(val_len)); +- break; +- default: +- printf("Invalid socket option type, this shouldn't happen.\n"); +- abort(); +- break; +- } +- err1 = zmq_setsockopt(this1, opt2, val, val_len); + ++/* method: set_reconnect_ivl_max */ ++#if (VERSION_2_1|VERSION_3_0) ++static int ZMQ_Socket__set_reconnect_ivl_max__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_reconnect_ivl_max1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_reconnect_ivl_max1 = lzmq_socket_set_reconnect_ivl_max(this1, value2); + /* check for error. */ +- if((-1 == err1)) { ++ if((-1 == rc_lzmq_socket_set_reconnect_ivl_max1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, err1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_reconnect_ivl_max1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } +- +-/* method: getopt */ +-static int ZMQ_Socket__getopt__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- uint32_t opt2 = luaL_checkinteger(L,2); +- ZMQ_Error err2 = 0; +- size_t val_len; +- +-#if VERSION_2_1 +- socket_t fd_val; + #endif +- int int_val; +- uint32_t uint32_val; +- uint64_t uint64_val; +- int64_t int64_val; +-#define STR_MAX 255 +- char str_val[STR_MAX]; + +- if(opt2 > MAX_OPTS) { +- lua_pushnil(L); +- lua_pushliteral(L, "Invalid socket option."); +- return 2; +- } ++/* method: maxmsgsize */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__maxmsgsize__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int64_t value1 = 0; ++ ZMQ_Error rc_lzmq_socket_maxmsgsize2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_maxmsgsize2 = lzmq_socket_maxmsgsize(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_maxmsgsize2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_maxmsgsize2); ++ return 2; ++} ++#endif + +- switch(opt_types[opt2]) { +-#if VERSION_2_1 +- case OPT_TYPE_FD: +- val_len = sizeof(fd_val); +- err2 = zmq_getsockopt(this1, opt2, &fd_val, &val_len); +- if(0 == err2) { +- lua_pushinteger(L, (lua_Integer)fd_val); +- return 1; +- } +- break; ++/* method: set_maxmsgsize */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__set_maxmsgsize__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int64_t value2; ++ ZMQ_Error rc_lzmq_socket_set_maxmsgsize1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_maxmsgsize1 = lzmq_socket_set_maxmsgsize(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_maxmsgsize1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_maxmsgsize1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + #endif +- case OPT_TYPE_INT: +- val_len = sizeof(int_val); +- err2 = zmq_getsockopt(this1, opt2, &int_val, &val_len); +- if(0 == err2) { +- lua_pushinteger(L, (lua_Integer)int_val); +- return 1; +- } +- break; +- case OPT_TYPE_UINT32: +- val_len = sizeof(uint32_val); +- err2 = zmq_getsockopt(this1, opt2, &uint32_val, &val_len); +- if(0 == err2) { +- lua_pushinteger(L, (lua_Integer)uint32_val); +- return 1; +- } +- break; +- case OPT_TYPE_UINT64: +- val_len = sizeof(uint64_val); +- err2 = zmq_getsockopt(this1, opt2, &uint64_val, &val_len); +- if(0 == err2) { +- lua_pushinteger(L, (lua_Integer)uint64_val); +- return 1; +- } +- break; +- case OPT_TYPE_INT64: +- val_len = sizeof(int64_val); +- err2 = zmq_getsockopt(this1, opt2, &int64_val, &val_len); +- if(0 == err2) { +- lua_pushinteger(L, (lua_Integer)int64_val); +- return 1; +- } +- break; +- case OPT_TYPE_STR: +- val_len = STR_MAX; +- err2 = zmq_getsockopt(this1, opt2, str_val, &val_len); +- if(0 == err2) { +- lua_pushlstring(L, str_val, val_len); +- return 1; +- } +-#undef STR_MAX +- break; +- default: +- printf("Invalid socket option type, this shouldn't happen.\n"); +- abort(); +- break; +- } +- lua_pushnil(L); + +- error_code__ZMQ_Error__push(L, err2); ++/* method: sndhwm */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__sndhwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_sndhwm2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_sndhwm2 = lzmq_socket_sndhwm(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_sndhwm2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndhwm2); + return 2; + } ++#endif + +-/* method: events */ +-static int ZMQ_Socket__events__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- uint32_t events1 = 0; +- ZMQ_Error err2 = 0; +-#if VERSION_2_1 +- size_t val_len = sizeof(events1); +- err2 = zmq_getsockopt(this1, ZMQ_EVENTS, &(events1), &val_len); +-#else +- luaL_error(L, "'events' method only supported in 0MQ version >= 2.1"); ++/* method: set_sndhwm */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__set_sndhwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_sndhwm1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_sndhwm1 = lzmq_socket_set_sndhwm(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_sndhwm1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndhwm1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} + #endif + +- if(!(-1 == err2)) { +- lua_pushinteger(L, events1); ++/* method: rcvhwm */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__rcvhwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_rcvhwm2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_rcvhwm2 = lzmq_socket_rcvhwm(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_rcvhwm2)) { ++ lua_pushinteger(L, value1); + } else { + lua_pushnil(L); + } +- error_code__ZMQ_Error__push(L, err2); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvhwm2); + return 2; + } ++#endif + +-/* method: send_msg */ +-static int ZMQ_Socket__send_msg__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- zmq_msg_t * msg2 = obj_type_zmq_msg_t_check(L,2); +- int flags3 = luaL_optinteger(L,3,0); +- ZMQ_Error rc_zmq_send1 = 0; +- rc_zmq_send1 = zmq_send(this1, msg2, flags3); ++/* method: set_rcvhwm */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__set_rcvhwm__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_rcvhwm1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_rcvhwm1 = lzmq_socket_set_rcvhwm(this1, value2); + /* check for error. */ +- if((-1 == rc_zmq_send1)) { ++ if((-1 == rc_lzmq_socket_set_rcvhwm1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_send1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvhwm1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: send */ +-static int ZMQ_Socket__send__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- size_t data_len2; +- const char * data2 = luaL_checklstring(L,2,&(data_len2)); +- int flags3 = luaL_optinteger(L,3,0); +- ZMQ_Error err1 = 0; +- err1 = simple_zmq_send(this1, data2, data_len2, flags3); ++/* method: multicast_hops */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__multicast_hops__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_multicast_hops2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_multicast_hops2 = lzmq_socket_multicast_hops(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_multicast_hops2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_multicast_hops2); ++ return 2; ++} ++#endif + ++/* method: set_multicast_hops */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__set_multicast_hops__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_multicast_hops1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_multicast_hops1 = lzmq_socket_set_multicast_hops(this1, value2); + /* check for error. */ +- if((-1 == err1)) { ++ if((-1 == rc_lzmq_socket_set_multicast_hops1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, err1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_multicast_hops1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: recv_msg */ +-static int ZMQ_Socket__recv_msg__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- zmq_msg_t * msg2 = obj_type_zmq_msg_t_check(L,2); +- int flags3 = luaL_optinteger(L,3,0); +- ZMQ_Error rc_zmq_recv1 = 0; +- rc_zmq_recv1 = zmq_recv(this1, msg2, flags3); ++/* method: rcvtimeo */ ++#if (VERSION_2_2|VERSION_3_0) ++static int ZMQ_Socket__rcvtimeo__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_rcvtimeo2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_rcvtimeo2 = lzmq_socket_rcvtimeo(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_rcvtimeo2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_rcvtimeo2); ++ return 2; ++} ++#endif ++ ++/* method: set_rcvtimeo */ ++#if (VERSION_2_2|VERSION_3_0) ++static int ZMQ_Socket__set_rcvtimeo__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_rcvtimeo1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_rcvtimeo1 = lzmq_socket_set_rcvtimeo(this1, value2); + /* check for error. */ +- if((-1 == rc_zmq_recv1)) { ++ if((-1 == rc_lzmq_socket_set_rcvtimeo1)) { + lua_pushnil(L); +- error_code__ZMQ_Error__push(L, rc_zmq_recv1); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_rcvtimeo1); + } else { + lua_pushboolean(L, 1); + lua_pushnil(L); + } + return 2; + } ++#endif + +-/* method: recv */ +-static int ZMQ_Socket__recv__meth(lua_State *L) { +- ZMQ_Socket * this1 = obj_type_ZMQ_Socket_check(L,1); +- int flags2 = luaL_optinteger(L,2,0); +- size_t data_len1 = 0; +- const char * data1 = NULL; +- ZMQ_Error err2 = 0; +- zmq_msg_t msg; +- /* initialize message */ +- err2 = zmq_msg_init(&msg); +- if(0 == err2) { +- /* receive message */ +- err2 = zmq_recv(this1, &msg, flags2); +- if(0 == err2) { +- data1 = zmq_msg_data(&msg); +- data_len1 = zmq_msg_size(&msg); +- } +- } ++/* method: sndtimeo */ ++#if (VERSION_2_2|VERSION_3_0) ++static int ZMQ_Socket__sndtimeo__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_sndtimeo2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_sndtimeo2 = lzmq_socket_sndtimeo(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_sndtimeo2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_sndtimeo2); ++ return 2; ++} ++#endif + +- if(!(-1 == err2)) { +- if(data1 == NULL) lua_pushnil(L); else lua_pushlstring(L, data1,data_len1); ++/* method: set_sndtimeo */ ++#if (VERSION_2_2|VERSION_3_0) ++static int ZMQ_Socket__set_sndtimeo__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_sndtimeo1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_sndtimeo1 = lzmq_socket_set_sndtimeo(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_sndtimeo1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_sndtimeo1); + } else { ++ lua_pushboolean(L, 1); + lua_pushnil(L); + } +- error_code__ZMQ_Error__push(L, err2); +- /* close message */ +- zmq_msg_close(&msg); ++ return 2; ++} ++#endif ++ ++/* method: ipv4only */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__ipv4only__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value1 = 0; ++ ZMQ_Error rc_lzmq_socket_ipv4only2 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ rc_lzmq_socket_ipv4only2 = lzmq_socket_ipv4only(this1, &(value1)); ++ if(!(-1 == rc_lzmq_socket_ipv4only2)) { ++ lua_pushinteger(L, value1); ++ } else { ++ lua_pushnil(L); ++ } ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_ipv4only2); ++ return 2; ++} ++#endif + ++/* method: set_ipv4only */ ++#if (VERSION_3_0) ++static int ZMQ_Socket__set_ipv4only__meth(lua_State *L) { ++ ZMQ_Socket * this1; ++ int value2; ++ ZMQ_Error rc_lzmq_socket_set_ipv4only1 = 0; ++ this1 = obj_type_ZMQ_Socket_check(L,1); ++ value2 = luaL_checkinteger(L,2); ++ rc_lzmq_socket_set_ipv4only1 = lzmq_socket_set_ipv4only(this1, value2); ++ /* check for error. */ ++ if((-1 == rc_lzmq_socket_set_ipv4only1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_lzmq_socket_set_ipv4only1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } + return 2; + } ++#endif + + /* method: new */ + static int ZMQ_Poller__new__meth(lua_State *L) { +- unsigned int length1 = luaL_optinteger(L,1,10); +- int this_flags1 = OBJ_UDATA_FLAG_OWN; +- ZMQ_Poller * this1; +- ZMQ_Poller poller; +- this1 = &poller; +- this1->items = (zmq_pollitem_t *)calloc(length1, sizeof(zmq_pollitem_t)); +- this1->next = -1; +- this1->count = 0; +- this1->len = length1; +- this1->free_list = -1; +- +- obj_type_ZMQ_Poller_push(L, this1, this_flags1); ++ unsigned int length1; ++ ZMQ_Poller this1_store; ++ ZMQ_Poller * this1 = &(this1_store); ++ length1 = luaL_optinteger(L,1,10); ++ poller_init(this1, length1); ++ obj_type_ZMQ_Poller_push(L, this1); + return 1; + } + + /* method: close */ + static int ZMQ_Poller__close__meth(lua_State *L) { +- int this_flags1 = 0; +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_delete(L,1,&(this_flags1)); +- if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } +- free(this1->items); +- this1->items = NULL; +- this1->next = -1; +- this1->count = 0; +- this1->len = 0; +- this1->free_list = -1; +- ++ ZMQ_Poller * this1; ++ this1 = obj_type_ZMQ_Poller_delete(L,1); ++ poller_cleanup(this1); + return 0; + } + + /* method: add */ + static int ZMQ_Poller__add__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); +- short events3 = luaL_checkinteger(L,3); ++ ZMQ_Poller * this1; ++ short events3; + int idx1 = 0; + zmq_pollitem_t *item; + ZMQ_Socket *sock = NULL; + socket_t fd = 0; + ++ this1 = obj_type_ZMQ_Poller_check(L,1); ++ events3 = luaL_checkinteger(L,3); + if(lua_isuserdata(L, 2)) { + sock = obj_type_ZMQ_Socket_check(L, 2); + } else if(lua_isnumber(L, 2)) { +@@ -2777,13 +6443,15 @@ static int ZMQ_Poller__add__meth(lua_State *L) { + + /* method: modify */ + static int ZMQ_Poller__modify__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); +- short events3 = luaL_checkinteger(L,3); ++ ZMQ_Poller * this1; ++ short events3; + int idx1 = 0; + zmq_pollitem_t *item; + ZMQ_Socket *sock = NULL; + socket_t fd = 0; + ++ this1 = obj_type_ZMQ_Poller_check(L,1); ++ events3 = luaL_checkinteger(L,3); + if(lua_isuserdata(L, 2)) { + sock = obj_type_ZMQ_Socket_check(L, 2); + /* find sock in items list. */ +@@ -2815,98 +6483,76 @@ static int ZMQ_Poller__modify__meth(lua_State *L) { + + /* method: remove */ + static int ZMQ_Poller__remove__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); ++ ZMQ_Poller * this1; ++ int idx1 = 0; + ZMQ_Socket *sock; + socket_t fd; +- int idx; + ++ this1 = obj_type_ZMQ_Poller_check(L,1); + /* ZMQ_Socket or fd */ + if(lua_isuserdata(L, 2)) { + sock = obj_type_ZMQ_Socket_check(L, 2); + /* find sock in items list. */ +- idx = poller_find_sock_item(this1, sock); ++ idx1 = poller_find_sock_item(this1, sock); + } else if(lua_isnumber(L, 2)) { + fd = lua_tonumber(L, 2); + /* find fd in items list. */ +- idx = poller_find_fd_item(this1, fd); ++ idx1 = poller_find_fd_item(this1, fd); + } else { + return luaL_typerror(L, 2, "number or ZMQ_Socket"); + } + /* if sock/fd was found. */ +- if(idx >= 0) { +- poller_remove_item(this1, idx); ++ if(idx1 >= 0) { ++ poller_remove_item(this1, idx1); + } + +- return 0; ++ lua_pushinteger(L, idx1); ++ return 1; + } + + /* method: poll */ + static int ZMQ_Poller__poll__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); +- long timeout2 = luaL_checkinteger(L,2); +- ZMQ_Error err1 = 0; +- /* poll for events */ +- err1 = poller_poll(this1, timeout2); +- if(err1 > 0) { ++ ZMQ_Poller * this1; ++ long timeout2; ++ int count1 = 0; ++ ZMQ_Error err2 = 0; ++ this1 = obj_type_ZMQ_Poller_check(L,1); ++ timeout2 = luaL_checkinteger(L,2); ++ err2 = poller_poll(this1, timeout2); ++ if(err2 > 0) { + this1->next = 0; ++ count1 = err2; + } else { + this1->next = -1; ++ count1 = 0; + } + +- /* check for error. */ +- if((-1 == err1)) { +- lua_pushnil(L); +- error_code__ZMQ_Error__push(L, err1); ++ if(!(-1 == err2)) { ++ lua_pushinteger(L, count1); + } else { +- lua_pushboolean(L, 1); + lua_pushnil(L); + } ++ error_code__ZMQ_Error__push(L, err2); + return 2; + } + +-/* method: next_revents */ +-static int ZMQ_Poller__next_revents__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); +- short revents2 = 0; +- zmq_pollitem_t *items; +- int count; +- int idx; +- +- revents2 = -1; +- idx = this1->next; +- if(idx >= 0) { +- count = this1->count; +- items = this1->items; +- /* find next item with pending events. */ +- while(idx < count && items[idx].revents == 0) ++idx; +- /* did we find a pending event? */ +- if(idx < count) { +- /* push the event's sock/fd. */ +- if(items[idx].socket != NULL) { +- obj_type_ZMQ_Socket_push(L, items[idx].socket, 0); +- } else { +- lua_pushnumber(L, items[idx].fd); +- } +- revents2 = items[idx].revents; +- /* is this the last event. */ +- ++idx; +- this1->next = (idx < count) ? idx : -1; +- } +- } +- if(revents2 < 0) { +- /* no more pending events. */ +- lua_pushnil(L); +- this1->next = -1; +- } +- ++/* method: next_revents_idx */ ++static int ZMQ_Poller__next_revents_idx__meth(lua_State *L) { ++ ZMQ_Poller * this1; ++ int idx1 = 0; ++ int revents2 = 0; ++ this1 = obj_type_ZMQ_Poller_check(L,1); ++ idx1 = poller_next_revents(this1, &(revents2)); ++ lua_pushinteger(L, idx1); + lua_pushinteger(L, revents2); + return 2; + } + + /* method: count */ + static int ZMQ_Poller__count__meth(lua_State *L) { +- ZMQ_Poller * this1 = obj_type_ZMQ_Poller_check(L,1); ++ ZMQ_Poller * this1; + int count1 = 0; ++ this1 = obj_type_ZMQ_Poller_check(L,1); + count1 = this1->count; + + lua_pushinteger(L, count1); +@@ -2916,8 +6562,9 @@ static int ZMQ_Poller__count__meth(lua_State *L) { + /* method: term */ + static int ZMQ_Ctx__term__meth(lua_State *L) { + int this_flags1 = 0; +- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_delete(L,1,&(this_flags1)); ++ ZMQ_Ctx * this1; + ZMQ_Error rc_zmq_term1 = 0; ++ this1 = obj_type_ZMQ_Ctx_delete(L,1,&(this_flags1)); + if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } + rc_zmq_term1 = zmq_term(this1); + /* check for error. */ +@@ -2933,8 +6580,9 @@ static int ZMQ_Ctx__term__meth(lua_State *L) { + + /* method: lightuserdata */ + static int ZMQ_Ctx__lightuserdata__meth(lua_State *L) { +- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_check(L,1); ++ ZMQ_Ctx * this1; + void * ptr1 = NULL; ++ this1 = obj_type_ZMQ_Ctx_check(L,1); + ptr1 = this1; + + lua_pushlightuserdata(L, ptr1); +@@ -2943,20 +6591,53 @@ static int ZMQ_Ctx__lightuserdata__meth(lua_State *L) { + + /* method: socket */ + static int ZMQ_Ctx__socket__meth(lua_State *L) { +- ZMQ_Ctx * this1 = obj_type_ZMQ_Ctx_check(L,1); +- int type2 = luaL_checkinteger(L,2); ++ ZMQ_Ctx * this1; ++ int type2; + int rc_zmq_socket_flags1 = OBJ_UDATA_FLAG_OWN; + ZMQ_Socket * rc_zmq_socket1; ++ this1 = obj_type_ZMQ_Ctx_check(L,1); ++ type2 = luaL_checkinteger(L,2); + rc_zmq_socket1 = zmq_socket(this1, type2); + if((NULL == rc_zmq_socket1)) { + lua_pushnil(L); + lua_pushstring(L, get_zmq_strerror()); ++ return 2; + } else { + obj_type_ZMQ_Socket_push(L, rc_zmq_socket1, rc_zmq_socket_flags1); + } + return 1; + } + ++/* method: set */ ++#if (VERSION_3_2) ++static int ZMQ_Ctx__set__meth(lua_State *L) { ++ ZMQ_Ctx * this1; ++ int flag2; ++ int value3; ++ int rc_zmq_ctx_set1 = 0; ++ this1 = obj_type_ZMQ_Ctx_check(L,1); ++ flag2 = luaL_checkinteger(L,2); ++ value3 = luaL_checkinteger(L,3); ++ rc_zmq_ctx_set1 = zmq_ctx_set(this1, flag2, value3); ++ lua_pushinteger(L, rc_zmq_ctx_set1); ++ return 1; ++} ++#endif ++ ++/* method: get */ ++#if (VERSION_3_2) ++static int ZMQ_Ctx__get__meth(lua_State *L) { ++ ZMQ_Ctx * this1; ++ int flag2; ++ int rc_zmq_ctx_get1 = 0; ++ this1 = obj_type_ZMQ_Ctx_check(L,1); ++ flag2 = luaL_checkinteger(L,2); ++ rc_zmq_ctx_get1 = zmq_ctx_get(this1, flag2); ++ lua_pushinteger(L, rc_zmq_ctx_get1); ++ return 1; ++} ++#endif ++ + /* method: start */ + static int ZMQ_StopWatch__start__meth(lua_State *L) { + int this_flags1 = OBJ_UDATA_FLAG_OWN; +@@ -2969,8 +6650,9 @@ static int ZMQ_StopWatch__start__meth(lua_State *L) { + /* method: stop */ + static int ZMQ_StopWatch__stop__meth(lua_State *L) { + int this_flags1 = 0; +- ZMQ_StopWatch * this1 = obj_type_ZMQ_StopWatch_delete(L,1,&(this_flags1)); ++ ZMQ_StopWatch * this1; + unsigned long usecs1 = 0; ++ this1 = obj_type_ZMQ_StopWatch_delete(L,1,&(this_flags1)); + if(!(this_flags1 & OBJ_UDATA_FLAG_OWN)) { return 0; } + usecs1 = zmq_stopwatch_stop(this1); + lua_pushinteger(L, usecs1); +@@ -2996,13 +6678,15 @@ static int zmq__version__func(lua_State *L) { + + /* method: init */ + static int zmq__init__func(lua_State *L) { +- int io_threads1 = luaL_checkinteger(L,1); ++ int io_threads1; + int rc_zmq_init_flags1 = OBJ_UDATA_FLAG_OWN; + ZMQ_Ctx * rc_zmq_init1; ++ io_threads1 = luaL_optinteger(L,1,1); + rc_zmq_init1 = zmq_init(io_threads1); + if((NULL == rc_zmq_init1)) { + lua_pushnil(L); + lua_pushstring(L, get_zmq_strerror()); ++ return 2; + } else { + obj_type_ZMQ_Ctx_push(L, rc_zmq_init1, rc_zmq_init_flags1); + } +@@ -3021,6 +6705,7 @@ static int zmq__init_ctx__func(lua_State *L) { + if((NULL == ctx1)) { + lua_pushnil(L); + lua_pushstring(L, get_zmq_strerror()); ++ return 2; + } else { + obj_type_ZMQ_Ctx_push(L, ctx1, 0); + } +@@ -3028,11 +6713,15 @@ static int zmq__init_ctx__func(lua_State *L) { + } + + /* method: device */ ++#if (VERSION_2_0|VERSION_3_2) + static int zmq__device__func(lua_State *L) { +- int device1 = luaL_checkinteger(L,1); +- ZMQ_Socket * insock2 = obj_type_ZMQ_Socket_check(L,2); +- ZMQ_Socket * outsock3 = obj_type_ZMQ_Socket_check(L,3); ++ int device1; ++ ZMQ_Socket * insock2; ++ ZMQ_Socket * outsock3; + ZMQ_Error rc_zmq_device1 = 0; ++ device1 = luaL_checkinteger(L,1); ++ insock2 = obj_type_ZMQ_Socket_check(L,2); ++ outsock3 = obj_type_ZMQ_Socket_check(L,3); + rc_zmq_device1 = zmq_device(device1, insock2, outsock3); + /* check for error. */ + if((-1 == rc_zmq_device1)) { +@@ -3044,6 +6733,30 @@ static int zmq__device__func(lua_State *L) { + } + return 2; + } ++#endif ++ ++/* method: proxy */ ++#if (VERSION_3_2) ++static int zmq__proxy__func(lua_State *L) { ++ ZMQ_Socket * frontend1; ++ ZMQ_Socket * backend2; ++ ZMQ_Socket * capture3; ++ ZMQ_Error rc_zmq_proxy1 = 0; ++ frontend1 = obj_type_ZMQ_Socket_check(L,1); ++ backend2 = obj_type_ZMQ_Socket_check(L,2); ++ capture3 = obj_type_ZMQ_Socket_optional(L,3); ++ rc_zmq_proxy1 = zmq_proxy(frontend1, backend2, capture3); ++ /* check for error. */ ++ if((-1 == rc_zmq_proxy1)) { ++ lua_pushnil(L); ++ error_code__ZMQ_Error__push(L, rc_zmq_proxy1); ++ } else { ++ lua_pushboolean(L, 1); ++ lua_pushnil(L); ++ } ++ return 2; ++} ++#endif + + /* method: stopwatch_start */ + static int zmq__stopwatch_start__func(lua_State *L) { +@@ -3056,32 +6769,452 @@ static int zmq__stopwatch_start__func(lua_State *L) { + + /* method: sleep */ + static int zmq__sleep__func(lua_State *L) { +- int seconds_1 = luaL_checkinteger(L,1); ++ int seconds_1; ++ seconds_1 = luaL_checkinteger(L,1); + zmq_sleep(seconds_1); + return 0; + } + +-/* method: dump_ffi */ +-static int zmq__dump_ffi__func(lua_State *L) { +- size_t ffi_code_len1 = 0; +- const char * ffi_code1 = NULL; +- ffi_code1 = zmq_ffi_lua_code; +- ffi_code_len1 = sizeof(zmq_ffi_lua_code) - 1; + +- if(ffi_code1 == NULL) lua_pushnil(L); else lua_pushlstring(L, ffi_code1,ffi_code_len1); +- return 1; +-} + ++static const luaL_Reg obj_ZErrors_pub_funcs[] = { ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZErrors_methods[] = { ++ {"description", ZErrors__description__meth}, ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZErrors_metas[] = { ++ {"__index", ZErrors____index__meth}, ++ {NULL, NULL} ++}; ++ ++static const obj_const obj_ZErrors_constants[] = { ++#ifdef ELNRNG ++ {"ELNRNG", NULL, ELNRNG, CONST_NUMBER}, ++#endif ++#ifdef EPFNOSUPPORT ++ {"EPFNOSUPPORT", NULL, EPFNOSUPPORT, CONST_NUMBER}, ++#endif ++#ifdef EBADR ++ {"EBADR", NULL, EBADR, CONST_NUMBER}, ++#endif ++#ifdef ENOLINK ++ {"ENOLINK", NULL, ENOLINK, CONST_NUMBER}, ++#endif ++#ifdef ENOSTR ++ {"ENOSTR", NULL, ENOSTR, CONST_NUMBER}, ++#endif ++#ifdef ERESTART ++ {"ERESTART", NULL, ERESTART, CONST_NUMBER}, ++#endif ++#ifdef EUCLEAN ++ {"EUCLEAN", NULL, EUCLEAN, CONST_NUMBER}, ++#endif ++#ifdef ELIBSCN ++ {"ELIBSCN", NULL, ELIBSCN, CONST_NUMBER}, ++#endif ++#ifdef EROFS ++ {"EROFS", NULL, EROFS, CONST_NUMBER}, ++#endif ++#ifdef EBADE ++ {"EBADE", NULL, EBADE, CONST_NUMBER}, ++#endif ++#ifdef ENOTSOCK ++ {"ENOTSOCK", NULL, ENOTSOCK, CONST_NUMBER}, ++#endif ++#ifdef ENOTCONN ++ {"ENOTCONN", NULL, ENOTCONN, CONST_NUMBER}, ++#endif ++#ifdef EREMOTE ++ {"EREMOTE", NULL, EREMOTE, CONST_NUMBER}, ++#endif ++#ifdef ECOMM ++ {"ECOMM", NULL, ECOMM, CONST_NUMBER}, ++#endif ++#ifdef ENODATA ++ {"ENODATA", NULL, ENODATA, CONST_NUMBER}, ++#endif ++#ifdef EPERM ++ {"EPERM", NULL, EPERM, CONST_NUMBER}, ++#endif ++#ifdef EBADRQC ++ {"EBADRQC", NULL, EBADRQC, CONST_NUMBER}, ++#endif ++#ifdef ENOSR ++ {"ENOSR", NULL, ENOSR, CONST_NUMBER}, ++#endif ++#ifdef ELIBMAX ++ {"ELIBMAX", NULL, ELIBMAX, CONST_NUMBER}, ++#endif ++#ifdef EDOTDOT ++ {"EDOTDOT", NULL, EDOTDOT, CONST_NUMBER}, ++#endif ++#ifdef EFSM ++ {"EFSM", NULL, EFSM, CONST_NUMBER}, ++#endif ++#ifdef ENOPROTOOPT ++ {"ENOPROTOOPT", NULL, ENOPROTOOPT, CONST_NUMBER}, ++#endif ++#ifdef EBFONT ++ {"EBFONT", NULL, EBFONT, CONST_NUMBER}, ++#endif ++#ifdef ENOCOMPATPROTO ++ {"ENOCOMPATPROTO", NULL, ENOCOMPATPROTO, CONST_NUMBER}, ++#endif ++#ifdef EKEYREVOKED ++ {"EKEYREVOKED", NULL, EKEYREVOKED, CONST_NUMBER}, ++#endif ++#ifdef ESRMNT ++ {"ESRMNT", NULL, ESRMNT, CONST_NUMBER}, ++#endif ++#ifdef EOVERFLOW ++ {"EOVERFLOW", NULL, EOVERFLOW, CONST_NUMBER}, ++#endif ++#ifdef EDQUOT ++ {"EDQUOT", NULL, EDQUOT, CONST_NUMBER}, ++#endif ++#ifdef EFBIG ++ {"EFBIG", NULL, EFBIG, CONST_NUMBER}, ++#endif ++#ifdef EIDRM ++ {"EIDRM", NULL, EIDRM, CONST_NUMBER}, ++#endif ++#ifdef EDOM ++ {"EDOM", NULL, EDOM, CONST_NUMBER}, ++#endif ++#ifdef EPROTO ++ {"EPROTO", NULL, EPROTO, CONST_NUMBER}, ++#endif ++#ifdef EMULTIHOP ++ {"EMULTIHOP", NULL, EMULTIHOP, CONST_NUMBER}, ++#endif ++#ifdef ENOCSI ++ {"ENOCSI", NULL, ENOCSI, CONST_NUMBER}, ++#endif ++#ifdef EDEADLOCK ++ {"EDEADLOCK", NULL, EDEADLOCK, CONST_NUMBER}, ++#endif ++#ifdef ENOPKG ++ {"ENOPKG", NULL, ENOPKG, CONST_NUMBER}, ++#endif ++#ifdef EPIPE ++ {"EPIPE", NULL, EPIPE, CONST_NUMBER}, ++#endif ++#ifdef EADDRINUSE ++ {"EADDRINUSE", NULL, EADDRINUSE, CONST_NUMBER}, ++#endif ++#ifdef EFAULT ++ {"EFAULT", NULL, EFAULT, CONST_NUMBER}, ++#endif ++#ifdef EDEADLK ++ {"EDEADLK", NULL, EDEADLK, CONST_NUMBER}, ++#endif ++#ifdef ENFILE ++ {"ENFILE", NULL, ENFILE, CONST_NUMBER}, ++#endif ++#ifdef EAGAIN ++ {"EAGAIN", NULL, EAGAIN, CONST_NUMBER}, ++#endif ++#ifdef ECONNABORTED ++ {"ECONNABORTED", NULL, ECONNABORTED, CONST_NUMBER}, ++#endif ++#ifdef EMLINK ++ {"EMLINK", NULL, EMLINK, CONST_NUMBER}, ++#endif ++#ifdef EBADMSG ++ {"EBADMSG", NULL, EBADMSG, CONST_NUMBER}, ++#endif ++#ifdef ERFKILL ++ {"ERFKILL", NULL, ERFKILL, CONST_NUMBER}, ++#endif ++#ifdef ENOTTY ++ {"ENOTTY", NULL, ENOTTY, CONST_NUMBER}, ++#endif ++#ifdef ELIBACC ++ {"ELIBACC", NULL, ELIBACC, CONST_NUMBER}, ++#endif ++#ifdef ETIME ++ {"ETIME", NULL, ETIME, CONST_NUMBER}, ++#endif ++#ifdef ECHILD ++ {"ECHILD", NULL, ECHILD, CONST_NUMBER}, ++#endif ++#ifdef ENOTRECOVERABLE ++ {"ENOTRECOVERABLE", NULL, ENOTRECOVERABLE, CONST_NUMBER}, ++#endif ++#ifdef EISCONN ++ {"EISCONN", NULL, EISCONN, CONST_NUMBER}, ++#endif ++#ifdef ENAVAIL ++ {"ENAVAIL", NULL, ENAVAIL, CONST_NUMBER}, ++#endif ++#ifdef EDESTADDRREQ ++ {"EDESTADDRREQ", NULL, EDESTADDRREQ, CONST_NUMBER}, ++#endif ++#ifdef EREMOTEIO ++ {"EREMOTEIO", NULL, EREMOTEIO, CONST_NUMBER}, ++#endif ++#ifdef ESTALE ++ {"ESTALE", NULL, ESTALE, CONST_NUMBER}, ++#endif ++#ifdef ESTRPIPE ++ {"ESTRPIPE", NULL, ESTRPIPE, CONST_NUMBER}, ++#endif ++#ifdef EHOSTUNREACH ++ {"EHOSTUNREACH", NULL, EHOSTUNREACH, CONST_NUMBER}, ++#endif ++#ifdef ENOTBLK ++ {"ENOTBLK", NULL, ENOTBLK, CONST_NUMBER}, ++#endif ++#ifdef EEXIST ++ {"EEXIST", NULL, EEXIST, CONST_NUMBER}, ++#endif ++#ifdef ENOTDIR ++ {"ENOTDIR", NULL, ENOTDIR, CONST_NUMBER}, ++#endif ++#ifdef EWOULDBLOCK ++ {"EWOULDBLOCK", NULL, EWOULDBLOCK, CONST_NUMBER}, ++#endif ++#ifdef EREMCHG ++ {"EREMCHG", NULL, EREMCHG, CONST_NUMBER}, ++#endif ++#ifdef ELOOP ++ {"ELOOP", NULL, ELOOP, CONST_NUMBER}, ++#endif ++#ifdef ENOTUNIQ ++ {"ENOTUNIQ", NULL, ENOTUNIQ, CONST_NUMBER}, ++#endif ++#ifdef EMEDIUMTYPE ++ {"EMEDIUMTYPE", NULL, EMEDIUMTYPE, CONST_NUMBER}, ++#endif ++#ifdef ENOLCK ++ {"ENOLCK", NULL, ENOLCK, CONST_NUMBER}, ++#endif ++#ifdef EUNATCH ++ {"EUNATCH", NULL, EUNATCH, CONST_NUMBER}, ++#endif ++#ifdef EPROTONOSUPPORT ++ {"EPROTONOSUPPORT", NULL, EPROTONOSUPPORT, CONST_NUMBER}, ++#endif ++#ifdef EHOSTDOWN ++ {"EHOSTDOWN", NULL, EHOSTDOWN, CONST_NUMBER}, ++#endif ++#ifdef EINTR ++ {"EINTR", NULL, EINTR, CONST_NUMBER}, ++#endif ++#ifdef ETIMEDOUT ++ {"ETIMEDOUT", NULL, ETIMEDOUT, CONST_NUMBER}, ++#endif ++#ifdef EOWNERDEAD ++ {"EOWNERDEAD", NULL, EOWNERDEAD, CONST_NUMBER}, ++#endif ++#ifdef EL2HLT ++ {"EL2HLT", NULL, EL2HLT, CONST_NUMBER}, ++#endif ++#ifdef ETERM ++ {"ETERM", NULL, ETERM, CONST_NUMBER}, ++#endif ++#ifdef EBADSLT ++ {"EBADSLT", NULL, EBADSLT, CONST_NUMBER}, ++#endif ++#ifdef ESHUTDOWN ++ {"ESHUTDOWN", NULL, ESHUTDOWN, CONST_NUMBER}, ++#endif ++#ifdef EIO ++ {"EIO", NULL, EIO, CONST_NUMBER}, ++#endif ++#ifdef ENOANO ++ {"ENOANO", NULL, ENOANO, CONST_NUMBER}, ++#endif ++#ifdef EACCES ++ {"EACCES", NULL, EACCES, CONST_NUMBER}, ++#endif ++#ifdef EOPNOTSUPP ++ {"EOPNOTSUPP", NULL, EOPNOTSUPP, CONST_NUMBER}, ++#endif ++#ifdef EKEYREJECTED ++ {"EKEYREJECTED", NULL, EKEYREJECTED, CONST_NUMBER}, ++#endif ++#ifdef ESOCKTNOSUPPORT ++ {"ESOCKTNOSUPPORT", NULL, ESOCKTNOSUPPORT, CONST_NUMBER}, ++#endif ++#ifdef ENOKEY ++ {"ENOKEY", NULL, ENOKEY, CONST_NUMBER}, ++#endif ++#ifdef ELIBBAD ++ {"ELIBBAD", NULL, ELIBBAD, CONST_NUMBER}, ++#endif ++#ifdef ENODEV ++ {"ENODEV", NULL, ENODEV, CONST_NUMBER}, ++#endif ++#ifdef ECANCELED ++ {"ECANCELED", NULL, ECANCELED, CONST_NUMBER}, ++#endif ++#ifdef ENOBUFS ++ {"ENOBUFS", NULL, ENOBUFS, CONST_NUMBER}, ++#endif ++#ifdef ENETUNREACH ++ {"ENETUNREACH", NULL, ENETUNREACH, CONST_NUMBER}, ++#endif ++#ifdef EL3HLT ++ {"EL3HLT", NULL, EL3HLT, CONST_NUMBER}, ++#endif ++#ifdef ENXIO ++ {"ENXIO", NULL, ENXIO, CONST_NUMBER}, ++#endif ++#ifdef ENETRESET ++ {"ENETRESET", NULL, ENETRESET, CONST_NUMBER}, ++#endif ++#ifdef ENOENT ++ {"ENOENT", NULL, ENOENT, CONST_NUMBER}, ++#endif ++#ifdef ENOMSG ++ {"ENOMSG", NULL, ENOMSG, CONST_NUMBER}, ++#endif ++#ifdef EL3RST ++ {"EL3RST", NULL, EL3RST, CONST_NUMBER}, ++#endif ++#ifdef EMFILE ++ {"EMFILE", NULL, EMFILE, CONST_NUMBER}, ++#endif ++#ifdef ENOEXEC ++ {"ENOEXEC", NULL, ENOEXEC, CONST_NUMBER}, ++#endif ++#ifdef ENOTEMPTY ++ {"ENOTEMPTY", NULL, ENOTEMPTY, CONST_NUMBER}, ++#endif ++#ifdef EMTHREAD ++ {"EMTHREAD", NULL, EMTHREAD, CONST_NUMBER}, ++#endif ++#ifdef EISNAM ++ {"EISNAM", NULL, EISNAM, CONST_NUMBER}, ++#endif ++#ifdef EINVAL ++ {"EINVAL", NULL, EINVAL, CONST_NUMBER}, ++#endif ++#ifdef ERANGE ++ {"ERANGE", NULL, ERANGE, CONST_NUMBER}, ++#endif ++#ifdef E2BIG ++ {"E2BIG", NULL, E2BIG, CONST_NUMBER}, ++#endif ++#ifdef ENOTNAM ++ {"ENOTNAM", NULL, ENOTNAM, CONST_NUMBER}, ++#endif ++#ifdef ENONET ++ {"ENONET", NULL, ENONET, CONST_NUMBER}, ++#endif ++#ifdef EADDRNOTAVAIL ++ {"EADDRNOTAVAIL", NULL, EADDRNOTAVAIL, CONST_NUMBER}, ++#endif ++#ifdef ENOSYS ++ {"ENOSYS", NULL, ENOSYS, CONST_NUMBER}, ++#endif ++#ifdef EINPROGRESS ++ {"EINPROGRESS", NULL, EINPROGRESS, CONST_NUMBER}, ++#endif ++#ifdef EBUSY ++ {"EBUSY", NULL, EBUSY, CONST_NUMBER}, ++#endif ++#ifdef EBADFD ++ {"EBADFD", NULL, EBADFD, CONST_NUMBER}, ++#endif ++#ifdef EISDIR ++ {"EISDIR", NULL, EISDIR, CONST_NUMBER}, ++#endif ++#ifdef EADV ++ {"EADV", NULL, EADV, CONST_NUMBER}, ++#endif ++#ifdef ECONNRESET ++ {"ECONNRESET", NULL, ECONNRESET, CONST_NUMBER}, ++#endif ++#ifdef ENOSPC ++ {"ENOSPC", NULL, ENOSPC, CONST_NUMBER}, ++#endif ++#ifdef ETOOMANYREFS ++ {"ETOOMANYREFS", NULL, ETOOMANYREFS, CONST_NUMBER}, ++#endif ++#ifdef EXFULL ++ {"EXFULL", NULL, EXFULL, CONST_NUMBER}, ++#endif ++#ifdef EPROTOTYPE ++ {"EPROTOTYPE", NULL, EPROTOTYPE, CONST_NUMBER}, ++#endif ++#ifdef ESRCH ++ {"ESRCH", NULL, ESRCH, CONST_NUMBER}, ++#endif ++#ifdef EMSGSIZE ++ {"EMSGSIZE", NULL, EMSGSIZE, CONST_NUMBER}, ++#endif ++#ifdef EAFNOSUPPORT ++ {"EAFNOSUPPORT", NULL, EAFNOSUPPORT, CONST_NUMBER}, ++#endif ++#ifdef ESPIPE ++ {"ESPIPE", NULL, ESPIPE, CONST_NUMBER}, ++#endif ++#ifdef ENETDOWN ++ {"ENETDOWN", NULL, ENETDOWN, CONST_NUMBER}, ++#endif ++#ifdef ECHRNG ++ {"ECHRNG", NULL, ECHRNG, CONST_NUMBER}, ++#endif ++#ifdef ENOMEM ++ {"ENOMEM", NULL, ENOMEM, CONST_NUMBER}, ++#endif ++#ifdef ECONNREFUSED ++ {"ECONNREFUSED", NULL, ECONNREFUSED, CONST_NUMBER}, ++#endif ++#ifdef ETXTBSY ++ {"ETXTBSY", NULL, ETXTBSY, CONST_NUMBER}, ++#endif ++#ifdef EKEYEXPIRED ++ {"EKEYEXPIRED", NULL, EKEYEXPIRED, CONST_NUMBER}, ++#endif ++#ifdef ENOMEDIUM ++ {"ENOMEDIUM", NULL, ENOMEDIUM, CONST_NUMBER}, ++#endif ++#ifdef EUSERS ++ {"EUSERS", NULL, EUSERS, CONST_NUMBER}, ++#endif ++#ifdef EILSEQ ++ {"EILSEQ", NULL, EILSEQ, CONST_NUMBER}, ++#endif ++#ifdef ELIBEXEC ++ {"ELIBEXEC", NULL, ELIBEXEC, CONST_NUMBER}, ++#endif ++#ifdef EALREADY ++ {"EALREADY", NULL, EALREADY, CONST_NUMBER}, ++#endif ++#ifdef ENAMETOOLONG ++ {"ENAMETOOLONG", NULL, ENAMETOOLONG, CONST_NUMBER}, ++#endif ++#ifdef EXDEV ++ {"EXDEV", NULL, EXDEV, CONST_NUMBER}, ++#endif ++#ifdef EBADF ++ {"EBADF", NULL, EBADF, CONST_NUMBER}, ++#endif ++#ifdef EL2NSYNC ++ {"EL2NSYNC", NULL, EL2NSYNC, CONST_NUMBER}, ++#endif ++ {NULL, NULL, 0.0 , 0} ++}; + ++static const reg_impl obj_ZErrors_implements[] = { ++ {NULL, NULL} ++}; + +-static const luaL_reg obj_zmq_msg_t_pub_funcs[] = { ++static const luaL_Reg obj_zmq_msg_t_pub_funcs[] = { + {"init", zmq_msg_t__init__meth}, + {"init_size", zmq_msg_t__init_size__meth}, + {"init_data", zmq_msg_t__init_data__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_zmq_msg_t_methods[] = { ++static const luaL_Reg obj_zmq_msg_t_methods[] = { + {"close", zmq_msg_t__close__meth}, + {"move", zmq_msg_t__move__meth}, + {"copy", zmq_msg_t__copy__meth}, +@@ -3092,7 +7225,7 @@ static const luaL_reg obj_zmq_msg_t_methods[] = { + {NULL, NULL} + }; + +-static const luaL_reg obj_zmq_msg_t_metas[] = { ++static const luaL_Reg obj_zmq_msg_t_metas[] = { + {"__gc", zmq_msg_t__delete__meth}, + {"__tostring", zmq_msg_t____tostring__meth}, + {"__eq", obj_simple_udata_default_equal}, +@@ -3111,25 +7244,182 @@ static const obj_const obj_zmq_msg_t_constants[] = { + {NULL, NULL, 0.0 , 0} + }; + +-static const luaL_reg obj_ZMQ_Socket_pub_funcs[] = { ++static const reg_impl obj_zmq_msg_t_implements[] = { ++ { "BufferIF", &(zmq_msg_t_Buffer) }, ++ ++ { "MutableBufferIF", &(zmq_msg_t_MutableBuffer) }, ++ ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZMQ_Socket_pub_funcs[] = { + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Socket_methods[] = { ++static const luaL_Reg obj_ZMQ_Socket_methods[] = { + {"close", ZMQ_Socket__close__meth}, + {"bind", ZMQ_Socket__bind__meth}, ++#if (VERSION_3_2) ++ {"unbind", ZMQ_Socket__unbind__meth}, ++#endif + {"connect", ZMQ_Socket__connect__meth}, ++#if (VERSION_3_2) ++ {"disconnect", ZMQ_Socket__disconnect__meth}, ++#endif + {"setopt", ZMQ_Socket__setopt__meth}, + {"getopt", ZMQ_Socket__getopt__meth}, +- {"events", ZMQ_Socket__events__meth}, + {"send_msg", ZMQ_Socket__send_msg__meth}, + {"send", ZMQ_Socket__send__meth}, + {"recv_msg", ZMQ_Socket__recv_msg__meth}, + {"recv", ZMQ_Socket__recv__meth}, ++#if (VERSION_2_0|VERSION_3_0) ++ {"hwm", ZMQ_Socket__hwm__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_hwm", ZMQ_Socket__set_hwm__meth}, ++#endif ++#if (VERSION_2_0) ++ {"swap", ZMQ_Socket__swap__meth}, ++#endif ++#if (VERSION_2_0) ++ {"set_swap", ZMQ_Socket__set_swap__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"affinity", ZMQ_Socket__affinity__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_affinity", ZMQ_Socket__set_affinity__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"identity", ZMQ_Socket__identity__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_identity", ZMQ_Socket__set_identity__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"subscribe", ZMQ_Socket__subscribe__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"unsubscribe", ZMQ_Socket__unsubscribe__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"rate", ZMQ_Socket__rate__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_rate", ZMQ_Socket__set_rate__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"recovery_ivl", ZMQ_Socket__recovery_ivl__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_recovery_ivl", ZMQ_Socket__set_recovery_ivl__meth}, ++#endif ++#if (VERSION_2_0) ++ {"mcast_loop", ZMQ_Socket__mcast_loop__meth}, ++#endif ++#if (VERSION_2_0) ++ {"set_mcast_loop", ZMQ_Socket__set_mcast_loop__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"sndbuf", ZMQ_Socket__sndbuf__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_sndbuf", ZMQ_Socket__set_sndbuf__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"rcvbuf", ZMQ_Socket__rcvbuf__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"set_rcvbuf", ZMQ_Socket__set_rcvbuf__meth}, ++#endif ++#if (VERSION_2_0|VERSION_3_0) ++ {"rcvmore", ZMQ_Socket__rcvmore__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"fd", ZMQ_Socket__fd__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"events", ZMQ_Socket__events__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"type", ZMQ_Socket__type__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"linger", ZMQ_Socket__linger__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"set_linger", ZMQ_Socket__set_linger__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"reconnect_ivl", ZMQ_Socket__reconnect_ivl__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"set_reconnect_ivl", ZMQ_Socket__set_reconnect_ivl__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"backlog", ZMQ_Socket__backlog__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"set_backlog", ZMQ_Socket__set_backlog__meth}, ++#endif ++#if (VERSION_2_1) ++ {"recovery_ivl_msec", ZMQ_Socket__recovery_ivl_msec__meth}, ++#endif ++#if (VERSION_2_1) ++ {"set_recovery_ivl_msec", ZMQ_Socket__set_recovery_ivl_msec__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"reconnect_ivl_max", ZMQ_Socket__reconnect_ivl_max__meth}, ++#endif ++#if (VERSION_2_1|VERSION_3_0) ++ {"set_reconnect_ivl_max", ZMQ_Socket__set_reconnect_ivl_max__meth}, ++#endif ++#if (VERSION_3_0) ++ {"maxmsgsize", ZMQ_Socket__maxmsgsize__meth}, ++#endif ++#if (VERSION_3_0) ++ {"set_maxmsgsize", ZMQ_Socket__set_maxmsgsize__meth}, ++#endif ++#if (VERSION_3_0) ++ {"sndhwm", ZMQ_Socket__sndhwm__meth}, ++#endif ++#if (VERSION_3_0) ++ {"set_sndhwm", ZMQ_Socket__set_sndhwm__meth}, ++#endif ++#if (VERSION_3_0) ++ {"rcvhwm", ZMQ_Socket__rcvhwm__meth}, ++#endif ++#if (VERSION_3_0) ++ {"set_rcvhwm", ZMQ_Socket__set_rcvhwm__meth}, ++#endif ++#if (VERSION_3_0) ++ {"multicast_hops", ZMQ_Socket__multicast_hops__meth}, ++#endif ++#if (VERSION_3_0) ++ {"set_multicast_hops", ZMQ_Socket__set_multicast_hops__meth}, ++#endif ++#if (VERSION_2_2|VERSION_3_0) ++ {"rcvtimeo", ZMQ_Socket__rcvtimeo__meth}, ++#endif ++#if (VERSION_2_2|VERSION_3_0) ++ {"set_rcvtimeo", ZMQ_Socket__set_rcvtimeo__meth}, ++#endif ++#if (VERSION_2_2|VERSION_3_0) ++ {"sndtimeo", ZMQ_Socket__sndtimeo__meth}, ++#endif ++#if (VERSION_2_2|VERSION_3_0) ++ {"set_sndtimeo", ZMQ_Socket__set_sndtimeo__meth}, ++#endif ++#if (VERSION_3_0) ++ {"ipv4only", ZMQ_Socket__ipv4only__meth}, ++#endif ++#if (VERSION_3_0) ++ {"set_ipv4only", ZMQ_Socket__set_ipv4only__meth}, ++#endif + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Socket_metas[] = { ++static const luaL_Reg obj_ZMQ_Socket_metas[] = { + {"__gc", ZMQ_Socket__close__meth}, + {"__tostring", obj_udata_default_tostring}, + {"__eq", obj_udata_default_equal}, +@@ -3148,23 +7438,27 @@ static const obj_const obj_ZMQ_Socket_constants[] = { + {NULL, NULL, 0.0 , 0} + }; + +-static const luaL_reg obj_ZMQ_Poller_pub_funcs[] = { ++static const reg_impl obj_ZMQ_Socket_implements[] = { ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZMQ_Poller_pub_funcs[] = { + {"new", ZMQ_Poller__new__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Poller_methods[] = { ++static const luaL_Reg obj_ZMQ_Poller_methods[] = { + {"close", ZMQ_Poller__close__meth}, + {"add", ZMQ_Poller__add__meth}, + {"modify", ZMQ_Poller__modify__meth}, + {"remove", ZMQ_Poller__remove__meth}, + {"poll", ZMQ_Poller__poll__meth}, +- {"next_revents", ZMQ_Poller__next_revents__meth}, ++ {"next_revents_idx", ZMQ_Poller__next_revents_idx__meth}, + {"count", ZMQ_Poller__count__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Poller_metas[] = { ++static const luaL_Reg obj_ZMQ_Poller_metas[] = { + {"__gc", ZMQ_Poller__close__meth}, + {"__tostring", obj_simple_udata_default_tostring}, + {"__eq", obj_simple_udata_default_equal}, +@@ -3183,18 +7477,28 @@ static const obj_const obj_ZMQ_Poller_constants[] = { + {NULL, NULL, 0.0 , 0} + }; + +-static const luaL_reg obj_ZMQ_Ctx_pub_funcs[] = { ++static const reg_impl obj_ZMQ_Poller_implements[] = { + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Ctx_methods[] = { ++static const luaL_Reg obj_ZMQ_Ctx_pub_funcs[] = { ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZMQ_Ctx_methods[] = { + {"term", ZMQ_Ctx__term__meth}, + {"lightuserdata", ZMQ_Ctx__lightuserdata__meth}, + {"socket", ZMQ_Ctx__socket__meth}, ++#if (VERSION_3_2) ++ {"set", ZMQ_Ctx__set__meth}, ++#endif ++#if (VERSION_3_2) ++ {"get", ZMQ_Ctx__get__meth}, ++#endif + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_Ctx_metas[] = { ++static const luaL_Reg obj_ZMQ_Ctx_metas[] = { + {"__gc", ZMQ_Ctx__term__meth}, + {"__tostring", obj_udata_default_tostring}, + {"__eq", obj_udata_default_equal}, +@@ -3213,17 +7517,21 @@ static const obj_const obj_ZMQ_Ctx_constants[] = { + {NULL, NULL, 0.0 , 0} + }; + +-static const luaL_reg obj_ZMQ_StopWatch_pub_funcs[] = { ++static const reg_impl obj_ZMQ_Ctx_implements[] = { ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg obj_ZMQ_StopWatch_pub_funcs[] = { + {"start", ZMQ_StopWatch__start__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_StopWatch_methods[] = { ++static const luaL_Reg obj_ZMQ_StopWatch_methods[] = { + {"stop", ZMQ_StopWatch__stop__meth}, + {NULL, NULL} + }; + +-static const luaL_reg obj_ZMQ_StopWatch_metas[] = { ++static const luaL_Reg obj_ZMQ_StopWatch_metas[] = { + {"__gc", ZMQ_StopWatch__stop__meth}, + {"__tostring", obj_udata_default_tostring}, + {"__eq", obj_udata_default_equal}, +@@ -3242,87 +7550,226 @@ static const obj_const obj_ZMQ_StopWatch_constants[] = { + {NULL, NULL, 0.0 , 0} + }; + +-static const luaL_reg zmq_function[] = { ++static const reg_impl obj_ZMQ_StopWatch_implements[] = { ++ {NULL, NULL} ++}; ++ ++static const luaL_Reg zmq_function[] = { + {"version", zmq__version__func}, + {"init", zmq__init__func}, + {"init_ctx", zmq__init_ctx__func}, ++#if (VERSION_2_0|VERSION_3_2) + {"device", zmq__device__func}, ++#endif ++#if (VERSION_3_2) ++ {"proxy", zmq__proxy__func}, ++#endif + {"stopwatch_start", zmq__stopwatch_start__func}, + {"sleep", zmq__sleep__func}, +- {"dump_ffi", zmq__dump_ffi__func}, + {NULL, NULL} + }; + + static const obj_const zmq_constants[] = { +- {"TYPE", NULL, 16, CONST_NUMBER}, +- {"RCVMORE", NULL, 13, CONST_NUMBER}, +- {"LINGER", NULL, 17, CONST_NUMBER}, +- {"SWAP", NULL, 3, CONST_NUMBER}, +- {"MSG_SHARED", NULL, 128, CONST_NUMBER}, +- {"SNDBUF", NULL, 11, CONST_NUMBER}, +- {"STREAMER", NULL, 1, CONST_NUMBER}, +- {"NOBLOCK", NULL, 1, CONST_NUMBER}, +- {"RCVBUF", NULL, 12, CONST_NUMBER}, +- {"FORWARDER", NULL, 2, CONST_NUMBER}, +- {"RATE", NULL, 8, CONST_NUMBER}, +- {"IDENTITY", NULL, 5, CONST_NUMBER}, +- {"SUB", NULL, 2, CONST_NUMBER}, +- {"FD", NULL, 14, CONST_NUMBER}, +- {"PUB", NULL, 1, CONST_NUMBER}, +- {"DELIMITER", NULL, 31, CONST_NUMBER}, +- {"BACKLOG", NULL, 19, CONST_NUMBER}, +- {"SNDMORE", NULL, 2, CONST_NUMBER}, +- {"POLLIN", NULL, 1, CONST_NUMBER}, +- {"REP", NULL, 4, CONST_NUMBER}, +- {"POLLERR", NULL, 4, CONST_NUMBER}, +- {"MAX_VSM_SIZE", NULL, 30, CONST_NUMBER}, +- {"PUSH", NULL, 8, CONST_NUMBER}, +- {"HWM", NULL, 1, CONST_NUMBER}, +- {"MSG_MORE", NULL, 1, CONST_NUMBER}, +- {"REQ", NULL, 3, CONST_NUMBER}, +- {"UNSUBSCRIBE", NULL, 7, CONST_NUMBER}, +- {"PULL", NULL, 7, CONST_NUMBER}, +- {"PAIR", NULL, 0, CONST_NUMBER}, +- {"QUEUE", NULL, 3, CONST_NUMBER}, +- {"EVENTS", NULL, 15, CONST_NUMBER}, +- {"XREQ", NULL, 5, CONST_NUMBER}, +- {"XREP", NULL, 6, CONST_NUMBER}, +- {"SUBSCRIBE", NULL, 6, CONST_NUMBER}, +- {"MCAST_LOOP", NULL, 10, CONST_NUMBER}, +- {"VSM", NULL, 32, CONST_NUMBER}, +- {"RECOVERY_IVL", NULL, 9, CONST_NUMBER}, +- {"RECONNECT_IVL", NULL, 18, CONST_NUMBER}, +- {"POLLOUT", NULL, 2, CONST_NUMBER}, +- {"AFFINITY", NULL, 4, CONST_NUMBER}, ++#ifdef ZMQ_TYPE ++ {"TYPE", NULL, ZMQ_TYPE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RCVMORE ++ {"RCVMORE", NULL, ZMQ_RCVMORE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_LINGER ++ {"LINGER", NULL, ZMQ_LINGER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_REP ++ {"REP", NULL, ZMQ_REP, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MAX_VSM_SIZE ++ {"MAX_VSM_SIZE", NULL, ZMQ_MAX_VSM_SIZE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MSG_SHARED ++ {"MSG_SHARED", NULL, ZMQ_MSG_SHARED, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MULTICAST_HOPS ++ {"MULTICAST_HOPS", NULL, ZMQ_MULTICAST_HOPS, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_XSUB ++ {"XSUB", NULL, ZMQ_XSUB, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_PAIR ++ {"PAIR", NULL, ZMQ_PAIR, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MSG_MORE ++ {"MSG_MORE", NULL, ZMQ_MSG_MORE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_STREAMER ++ {"STREAMER", NULL, ZMQ_STREAMER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MAXMSGSIZE ++ {"MAXMSGSIZE", NULL, ZMQ_MAXMSGSIZE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_DEALER ++ {"DEALER", NULL, ZMQ_DEALER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_ROUTER ++ {"ROUTER", NULL, ZMQ_ROUTER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_NOBLOCK ++ {"NOBLOCK", NULL, ZMQ_NOBLOCK, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RCVBUF ++ {"RCVBUF", NULL, ZMQ_RCVBUF, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_FORWARDER ++ {"FORWARDER", NULL, ZMQ_FORWARDER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RATE ++ {"RATE", NULL, ZMQ_RATE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_IDENTITY ++ {"IDENTITY", NULL, ZMQ_IDENTITY, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_PULL ++ {"PULL", NULL, ZMQ_PULL, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_IO_THREADS ++ {"IO_THREADS", NULL, ZMQ_IO_THREADS, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RCVHWM ++ {"RCVHWM", NULL, ZMQ_RCVHWM, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SNDHWM ++ {"SNDHWM", NULL, ZMQ_SNDHWM, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_AFFINITY ++ {"AFFINITY", NULL, ZMQ_AFFINITY, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SUB ++ {"SUB", NULL, ZMQ_SUB, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_UNSUBSCRIBE ++ {"UNSUBSCRIBE", NULL, ZMQ_UNSUBSCRIBE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_PUSH ++ {"PUSH", NULL, ZMQ_PUSH, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_XREQ ++ {"XREQ", NULL, ZMQ_XREQ, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RCVLABEL ++ {"RCVLABEL", NULL, ZMQ_RCVLABEL, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_PUB ++ {"PUB", NULL, ZMQ_PUB, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_DELIMITER ++ {"DELIMITER", NULL, ZMQ_DELIMITER, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_BACKLOG ++ {"BACKLOG", NULL, ZMQ_BACKLOG, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SNDMORE ++ {"SNDMORE", NULL, ZMQ_SNDMORE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_EVENTS ++ {"EVENTS", NULL, ZMQ_EVENTS, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SNDBUF ++ {"SNDBUF", NULL, ZMQ_SNDBUF, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MAX_SOCKETS ++ {"MAX_SOCKETS", NULL, ZMQ_MAX_SOCKETS, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_POLLIN ++ {"POLLIN", NULL, ZMQ_POLLIN, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_FD ++ {"FD", NULL, ZMQ_FD, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_POLLERR ++ {"POLLERR", NULL, ZMQ_POLLERR, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RCVTIMEO ++ {"RCVTIMEO", NULL, ZMQ_RCVTIMEO, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SNDTIMEO ++ {"SNDTIMEO", NULL, ZMQ_SNDTIMEO, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_HWM ++ {"HWM", NULL, ZMQ_HWM, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_XPUB ++ {"XPUB", NULL, ZMQ_XPUB, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_REQ ++ {"REQ", NULL, ZMQ_REQ, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RECONNECT_IVL_MAX ++ {"RECONNECT_IVL_MAX", NULL, ZMQ_RECONNECT_IVL_MAX, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RECONNECT_IVL_MSEC ++ {"RECONNECT_IVL_MSEC", NULL, ZMQ_RECONNECT_IVL_MSEC, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SNDLABEL ++ {"SNDLABEL", NULL, ZMQ_SNDLABEL, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_QUEUE ++ {"QUEUE", NULL, ZMQ_QUEUE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_VSM ++ {"VSM", NULL, ZMQ_VSM, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SWAP ++ {"SWAP", NULL, ZMQ_SWAP, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_XREP ++ {"XREP", NULL, ZMQ_XREP, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_SUBSCRIBE ++ {"SUBSCRIBE", NULL, ZMQ_SUBSCRIBE, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_MCAST_LOOP ++ {"MCAST_LOOP", NULL, ZMQ_MCAST_LOOP, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_DONTWAIT ++ {"DONTWAIT", NULL, ZMQ_DONTWAIT, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RECOVERY_IVL ++ {"RECOVERY_IVL", NULL, ZMQ_RECOVERY_IVL, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_RECONNECT_IVL ++ {"RECONNECT_IVL", NULL, ZMQ_RECONNECT_IVL, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_POLLOUT ++ {"POLLOUT", NULL, ZMQ_POLLOUT, CONST_NUMBER}, ++#endif ++#ifdef ZMQ_POLL_MSEC ++ {"POLL_MSEC", NULL, ZMQ_POLL_MSEC, CONST_NUMBER}, ++#endif + {NULL, NULL, 0.0 , 0} + }; + +-static const ffi_export_symbol zmq_ffi_export[] = { +-{ "get_zmq_strerror", get_zmq_strerror }, +-{ "simple_zmq_send", simple_zmq_send }, +-{ "poller_find_sock_item", poller_find_sock_item }, +-{ "poller_find_fd_item", poller_find_fd_item }, +-{ "poller_get_free_item", poller_get_free_item }, +-{ "poller_poll", poller_poll }, +-{ "poller_remove_item", poller_remove_item }, +- {NULL, NULL} +-}; +- + + + static const reg_sub_module reg_sub_modules[] = { +- { &(obj_type_zmq_msg_t), 0, obj_zmq_msg_t_pub_funcs, obj_zmq_msg_t_methods, obj_zmq_msg_t_metas, obj_zmq_msg_t_bases, obj_zmq_msg_t_fields, obj_zmq_msg_t_constants}, +- { &(obj_type_ZMQ_Socket), 0, obj_ZMQ_Socket_pub_funcs, obj_ZMQ_Socket_methods, obj_ZMQ_Socket_metas, obj_ZMQ_Socket_bases, obj_ZMQ_Socket_fields, obj_ZMQ_Socket_constants}, +- { &(obj_type_ZMQ_Poller), 0, obj_ZMQ_Poller_pub_funcs, obj_ZMQ_Poller_methods, obj_ZMQ_Poller_metas, obj_ZMQ_Poller_bases, obj_ZMQ_Poller_fields, obj_ZMQ_Poller_constants}, +- { &(obj_type_ZMQ_Ctx), 0, obj_ZMQ_Ctx_pub_funcs, obj_ZMQ_Ctx_methods, obj_ZMQ_Ctx_metas, obj_ZMQ_Ctx_bases, obj_ZMQ_Ctx_fields, obj_ZMQ_Ctx_constants}, +- { &(obj_type_ZMQ_StopWatch), 0, obj_ZMQ_StopWatch_pub_funcs, obj_ZMQ_StopWatch_methods, obj_ZMQ_StopWatch_metas, obj_ZMQ_StopWatch_bases, obj_ZMQ_StopWatch_fields, obj_ZMQ_StopWatch_constants}, +- {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL} ++ { &(obj_type_ZErrors), REG_META, obj_ZErrors_pub_funcs, obj_ZErrors_methods, obj_ZErrors_metas, NULL, NULL, obj_ZErrors_constants, NULL, 0}, ++ { &(obj_type_zmq_msg_t), REG_OBJECT, obj_zmq_msg_t_pub_funcs, obj_zmq_msg_t_methods, obj_zmq_msg_t_metas, obj_zmq_msg_t_bases, obj_zmq_msg_t_fields, obj_zmq_msg_t_constants, obj_zmq_msg_t_implements, 0}, ++ { &(obj_type_ZMQ_Socket), REG_OBJECT, obj_ZMQ_Socket_pub_funcs, obj_ZMQ_Socket_methods, obj_ZMQ_Socket_metas, obj_ZMQ_Socket_bases, obj_ZMQ_Socket_fields, obj_ZMQ_Socket_constants, obj_ZMQ_Socket_implements, 0}, ++ { &(obj_type_ZMQ_Poller), REG_OBJECT, obj_ZMQ_Poller_pub_funcs, obj_ZMQ_Poller_methods, obj_ZMQ_Poller_metas, obj_ZMQ_Poller_bases, obj_ZMQ_Poller_fields, obj_ZMQ_Poller_constants, obj_ZMQ_Poller_implements, 0}, ++ { &(obj_type_ZMQ_Ctx), REG_OBJECT, obj_ZMQ_Ctx_pub_funcs, obj_ZMQ_Ctx_methods, obj_ZMQ_Ctx_metas, obj_ZMQ_Ctx_bases, obj_ZMQ_Ctx_fields, obj_ZMQ_Ctx_constants, obj_ZMQ_Ctx_implements, 0}, ++ { &(obj_type_ZMQ_StopWatch), REG_OBJECT, obj_ZMQ_StopWatch_pub_funcs, obj_ZMQ_StopWatch_methods, obj_ZMQ_StopWatch_metas, obj_ZMQ_StopWatch_bases, obj_ZMQ_StopWatch_fields, obj_ZMQ_StopWatch_constants, obj_ZMQ_StopWatch_implements, 0}, ++ {NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0} + }; + + + + + ++#if LUAJIT_FFI ++static const ffi_export_symbol zmq_ffi_export[] = { ++ {NULL, { NULL } } ++}; ++#endif ++ ++ + + + static const luaL_Reg submodule_libs[] = { +@@ -3355,20 +7802,29 @@ LUA_NOBJ_API int luaopen_zmq(lua_State *L) { + const luaL_Reg *submodules = submodule_libs; + int priv_table = -1; + +-#if LUAJIT_FFI ++ /* register interfaces */ ++ obj_register_interfaces(L, obj_interfaces); ++ + /* private table to hold reference to object metatables. */ + lua_newtable(L); + priv_table = lua_gettop(L); +-#endif ++ lua_pushlightuserdata(L, obj_udata_private_key); ++ lua_pushvalue(L, priv_table); ++ lua_rawset(L, LUA_REGISTRYINDEX); /* store private table in registry. */ + + /* create object cache. */ + create_object_instance_cache(L); + + /* module table. */ ++#if REG_MODULES_AS_GLOBALS + luaL_register(L, "zmq", zmq_function); ++#else ++ lua_newtable(L); ++ luaL_setfuncs(L, zmq_function, 0); ++#endif + + /* register module constants. */ +- obj_type_register_constants(L, zmq_constants, -1); ++ obj_type_register_constants(L, zmq_constants, -1, 0); + + for(; submodules->func != NULL ; submodules++) { + lua_pushcfunction(L, submodules->func); +@@ -3389,9 +7845,19 @@ LUA_NOBJ_API int luaopen_zmq(lua_State *L) { + } + + #if LUAJIT_FFI +- nobj_try_loading_ffi(L, "zmq", zmq_ffi_lua_code, +- zmq_ffi_export, priv_table); ++ if(nobj_check_ffi_support(L)) { ++ nobj_try_loading_ffi(L, "zmq.nobj.ffi.lua", zmq_ffi_lua_code, ++ zmq_ffi_export, priv_table); ++ } + #endif ++ ++ /* Cache reference to zmq.ZErrors table for errno->string convertion. */ ++ lua_pushlightuserdata(L, zmq_ZErrors_key); ++ lua_getfield(L, -2, "ZErrors"); ++ lua_rawset(L, LUA_REGISTRYINDEX); ++ ++ ++ + return 1; + } + +diff --git a/src/socket.nobj.lua b/src/socket.nobj.lua +index 207f52b..9c9b067 100644 +--- a/src/socket.nobj.lua ++++ b/src/socket.nobj.lua +@@ -18,21 +18,416 @@ + -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + -- THE SOFTWARE. + ++------------------------------------------------------------------------------------- ++-- ++-- Generate ZeroMQ socket option code customized for each version of zmq (2.0,2.1,3.x) ++-- ++------------------------------------------------------------------------------------- ++ ++local OPT_TYPES = { ++NONE = "NONE", ++INT = "int", ++UINT32 = "uint32_t", ++UINT64 = "uint64_t", ++INT64 = "int64_t", ++BLOB = "const char *", ++FD = "int", ++} ++local get_set_prefix = { ++rw = { c_get = "lzmq_socket_", get='', c_set = "lzmq_socket_set_", set='set_' }, ++r = { c_get = "lzmq_socket_", get='' }, ++w = { c_set = "lzmq_socket_", set='' }, ++} ++ ++local socket_options = { ++ { ver_def = 'VERSION_2_0', major = 2, minor = 0, ++ [1] = { name="hwm", otype="UINT64", mode="rw", ltype="int" }, ++ [2] = { }, ++ [3] = { name="swap", otype="INT64", mode="rw", ltype="int" }, ++ [4] = { name="affinity", otype="UINT64", mode="rw", ltype="uint64_t" }, ++ [5] = { name="identity", otype="BLOB", mode="rw", ltype="const char *" }, ++ [6] = { name="subscribe", otype="BLOB", mode="w", ltype="const char *" }, ++ [7] = { name="unsubscribe", otype="BLOB", mode="w", ltype="const char *" }, ++ [8] = { name="rate", otype="INT64", mode="rw", ltype="int" }, ++ [9] = { name="recovery_ivl", otype="INT64", mode="rw", ltype="int" }, ++ [10] = { name="mcast_loop", otype="INT64", mode="rw", ltype="int" }, ++ [11] = { name="sndbuf", otype="UINT64", mode="rw", ltype="int" }, ++ [12] = { name="rcvbuf", otype="UINT64", mode="rw", ltype="int" }, ++ [13] = { name="rcvmore", otype="INT64", mode="r", ltype="int" }, ++ }, ++ { ver_def = 'VERSION_2_1', major = 2, minor = 1, ++ [14] = { name="fd", otype="FD", mode="r", ltype="int" }, ++ [15] = { name="events", otype="UINT32", mode="r", ltype="int" }, ++ [16] = { name="type", otype="INT", mode="r", ltype="int" }, ++ [17] = { name="linger", otype="INT", mode="rw", ltype="int" }, ++ [18] = { name="reconnect_ivl", otype="INT", mode="rw", ltype="int" }, ++ [19] = { name="backlog", otype="INT", mode="rw", ltype="int" }, ++ [20] = { name="recovery_ivl_msec", otype="INT64", mode="rw", ltype="int64_t" }, ++ [21] = { name="reconnect_ivl_max", otype="INT", mode="rw", ltype="int" }, ++ }, ++ { ver_def = 'VERSION_2_2', major = 2, minor = 2, ++ [22] = { }, ++ [23] = { }, ++ [24] = { }, ++ [25] = { }, ++ [26] = { }, ++ [27] = { name="rcvtimeo", otype="INT", mode="rw", ltype="int" }, ++ [28] = { name="sndtimeo", otype="INT", mode="rw", ltype="int" }, ++ }, ++ { ver_def = 'VERSION_3_0', major = 3, minor = 0, ++ [1] = { name="hwm", otype="INT", mode="rw", ++custom = [[ ++ZMQ_Error lzmq_socket_set_hwm(ZMQ_Socket *sock, int value) { ++ int val; ++ int rc; ++ val = (int)value; ++ rc = zmq_setsockopt(sock, ZMQ_SNDHWM, &value, sizeof(value)); ++ if(-1 == rc) return rc; ++ val = (int)value; ++ return zmq_setsockopt(sock, ZMQ_RCVHWM, &value, sizeof(value)); ++} ++ZMQ_Error lzmq_socket_hwm(ZMQ_Socket *sock, int *value) { ++ size_t val_len; ++ int rc; ++ val_len = sizeof(value); ++ rc = zmq_getsockopt(sock, ZMQ_SNDHWM, value, &val_len); ++ if(-1 == rc) return rc; ++ val_len = sizeof(value); ++ return zmq_getsockopt(sock, ZMQ_RCVHWM, value, &val_len); ++} ++ ++]] }, ++ [2] = { }, ++ [3] = { }, ++ [4] = { name="affinity", otype="UINT64", mode="rw", ltype="uint64_t" }, ++ [5] = { name="identity", otype="BLOB", mode="rw", ltype="const char *" }, ++ [6] = { name="subscribe", otype="BLOB", mode="w", ltype="const char *" }, ++ [7] = { name="unsubscribe", otype="BLOB", mode="w", ltype="const char *" }, ++ [8] = { name="rate", otype="INT", mode="rw", ltype="int" }, ++ [9] = { name="recovery_ivl", otype="INT", mode="rw", ltype="int" }, ++ [10] = { }, ++ [11] = { name="sndbuf", otype="INT", mode="rw", ltype="int" }, ++ [12] = { name="rcvbuf", otype="INT", mode="rw", ltype="int" }, ++ [13] = { name="rcvmore", otype="INT", mode="r", ltype="int" }, ++ [14] = { name="fd", otype="FD", mode="r", ltype="int" }, ++ [15] = { name="events", otype="INT", mode="r", ltype="int" }, ++ [16] = { name="type", otype="INT", mode="r", ltype="int" }, ++ [17] = { name="linger", otype="INT", mode="rw", ltype="int" }, ++ [18] = { name="reconnect_ivl", otype="INT", mode="rw", ltype="int" }, ++ [19] = { name="backlog", otype="INT", mode="rw", ltype="int" }, ++ [20] = { }, ++ [21] = { name="reconnect_ivl_max", otype="INT", mode="rw", ltype="int" }, ++ [22] = { name="maxmsgsize", otype="INT64", mode="rw", ltype="int64_t" }, ++ [23] = { name="sndhwm", otype="INT", mode="rw", ltype="int" }, ++ [24] = { name="rcvhwm", otype="INT", mode="rw", ltype="int" }, ++ [25] = { name="multicast_hops", otype="INT", mode="rw", ltype="int" }, ++ [26] = { }, ++ [27] = { name="rcvtimeo", otype="INT", mode="rw", ltype="int" }, ++ [28] = { name="sndtimeo", otype="INT", mode="rw", ltype="int" }, ++ [29] = { }, ++ [30] = { }, ++ [31] = { name="ipv4only", otype="INT", mode="rw", ltype="int" }, ++ }, ++} ++local max_options = 50 ++ ++local function foreach_opt(func) ++ for i=1,#socket_options do ++ local ver_opts = socket_options[i] ++ for num=1,max_options do ++ local opt = ver_opts[num] ++ if opt then ++ func(num, opt, ver_opts) ++ end ++ end ++ end ++end ++local add=function(t,val) return table.insert(t,val) end ++local function template(data, templ) ++ return templ:gsub("%${(.-)}", data) ++end ++ ++local socket_methods = {} ++local ffi_opt_names = {} ++local max_methods = 0 ++local function get_methods(opt, ver) ++ local num = opt.num ++ -- check if methods have been created ++ local methods = socket_methods[num] ++ ++ if not methods then ++ add(ffi_opt_names, "\t\t[".. num .. "] = '" .. opt.name .. "',\n") ++ -- need to create methods info. ++ methods = { ++ num=num, ++ name=opt.name, ++ get=opt.get, set=opt.set, c_get=opt.c_get, c_set=opt.c_set, ++ ltype=opt.ltype, otype=opt.otype, mode=opt.mode, ++ versions = {}, ++ } ++ ++ -- initialize all version as not-supported. ++ for i=1,#socket_options do ++ local ver_opts = socket_options[i] ++ methods[ver_opts.ver_def] = false ++ end ++ ++ if num > max_methods then max_methods = num end ++ ++ socket_methods[num] = methods ++ end ++ ++ -- mark this version as supporting the option. ++ methods[ver.ver_def] = true ++ add(methods.versions, ver) ++ ++ return methods ++end ++ ++-- do pre-processing of options. ++foreach_opt(function(num, opt, ver) ++ opt.num = num ++ if not opt.name then ++ opt.name = 'none' ++ opt.otype = 'NONE' ++ opt.DEF = 'unused' ++ return ++ end ++ -- track max option number for each version. ++ if not ver.max_opt or ver.max_opt < num then ++ ver.max_opt = num ++ end ++ opt.DEF = "ZMQ_" .. opt.name:upper() ++ -- ctype & ffi_type ++ local ctype = OPT_TYPES[opt.otype] ++ opt.ctype = ctype ++ if opt.otype == 'BLOB' then ++ opt.ffi_type = 'string' ++ opt.set_len_param = ', size_t value_len' ++ opt.set_val_name = 'value' ++ opt.set_len_name = 'value_len' ++ elseif ctype ~= 'NONE' then ++ opt.ffi_type = ctype .. '[1]' ++ opt.set_len_param = '' ++ opt.set_val_name = '&value' ++ opt.set_len_name = 'sizeof(value)' ++ end ++ -- getter/setter names ++ for meth,prefix in pairs(get_set_prefix[opt.mode]) do ++ opt[meth] = prefix .. opt.name ++ end ++ -- create common list of option get/set methods. ++ local methods = get_methods(opt, ver) ++end) ++ ++local options_c_code = {} ++local opt_types = {} ++ ++local function if_def(def) ++ local code = "#if " .. def .. "\n" ++ add(options_c_code, code) ++ add(opt_types, code) ++end ++local function endif(def) ++ local code = "#endif /* #if " .. def .. " */\n" ++ add(options_c_code, code) ++ add(opt_types, code) ++end ++ ++-- build C code for socket options setters/getters ++local last_ver ++foreach_opt(function(num, opt, ver) ++ if ver ~= last_ver then ++ if last_ver then ++ endif(last_ver.ver_def) ++ end ++ last_ver = ver ++ if_def(ver.ver_def) ++ add(opt_types, template(ver,[[ ++#define ${ver_def}_MAX_OPT ${max_opt} ++]])) ++ end ++ add(opt_types, template(opt,[[ ++ OPT_TYPE_${otype}, /* ${num} ${DEF} */ ++]])) ++ if opt.name == 'none' then return end ++ -- generate setter ++ local set = '' ++ local get = '' ++ if opt.c_set then ++ if opt.otype == 'BLOB' then ++ set = [[ ++LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, const char *value, size_t str_len) { ++ return zmq_setsockopt(sock, ${DEF}, value, str_len); ++]] ++ elseif opt.ctype == opt.ltype then ++ set = [[ ++LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, ${ltype} value) { ++ return zmq_setsockopt(sock, ${DEF}, &value, sizeof(value)); ++]] ++ else ++ set = [[ ++LUA_NOBJ_API ZMQ_Error ${c_set}(ZMQ_Socket *sock, ${ltype} value) { ++ ${ctype} val = (${ctype})value; ++ return zmq_setsockopt(sock, ${DEF}, &val, sizeof(val)); ++]] ++ end ++ set = set .. "}\n\n" ++ end ++ -- generate getter ++ if opt.c_get then ++ if opt.otype == 'BLOB' then ++ get = [[ ++LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, char *value, size_t *len) { ++ return zmq_getsockopt(sock, ${DEF}, value, len); ++]] ++ elseif opt.ctype == opt.ltype then ++ get = [[ ++LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, ${ltype} *value) { ++ size_t val_len = sizeof(${ltype}); ++ return zmq_getsockopt(sock, ${DEF}, value, &val_len); ++]] ++ else ++ get = [[ ++LUA_NOBJ_API ZMQ_Error ${c_get}(ZMQ_Socket *sock, ${ltype} *value) { ++ ${ctype} val; ++ size_t val_len = sizeof(val); ++ int rc = zmq_getsockopt(sock, ${DEF}, &val, &val_len); ++ *value = (${ltype})val; ++ return rc; ++]] ++ end ++ get = get .. "}\n\n" ++ end ++ local templ ++ if opt.custom then ++ templ = opt.custom ++ else ++ templ = set .. get ++ end ++ add(options_c_code, template(opt,templ)) ++end) ++endif(last_ver.ver_def) ++ ++add(opt_types, [[ ++#if VERSION_3_0 ++# define MAX_OPTS VERSION_3_0_MAX_OPT ++#else ++# if VERSION_2_2 ++# define MAX_OPTS VERSION_2_2_MAX_OPT ++# elif VERSION_2_1 ++# define MAX_OPTS VERSION_2_1_MAX_OPT ++# else ++# define MAX_OPTS VERSION_2_0_MAX_OPT ++# endif ++#endif ++}; ++ ++]]) ++ ++options_c_code = table.concat(options_c_code) ++opt_types = table.concat(opt_types) ++ffi_opt_names = table.concat(ffi_opt_names) ++ ++local function tunpack(tab, idx, max) ++ if idx == max then return tab[idx] end ++ return tab[idx], tunpack(tab, idx + 1, max) ++end ++ ++local function build_meth_if_def(meth) ++ local v = {} ++ for i=1,#socket_options do ++ local ver_opts = socket_options[i] ++ if meth[ver_opts.ver_def] then ++ v[#v+1] = ver_opts.ver_def ++ end ++ end ++ return v ++end ++ ++local function build_option_methods() ++ local m = {} ++ ++ for i=1,max_methods do ++ local meth = socket_methods[i] ++ if meth then ++ local ltype = meth.ltype ++ local name ++ -- get list of version defs for this method. ++ local if_defs = build_meth_if_def(meth) ++ -- generate getter method. ++ name = meth.get ++ if name then ++ local args = { ltype, "&value" } ++ local val_out = { ltype, "&value" } ++ if meth.otype == 'BLOB' then ++ val_out = { 'char *', "value", has_length = true } ++ args = { 'char *', "value", "size_t", "&#value" } ++ end ++ m[#m+1] = method (name) { if_defs = if_defs, ++ var_out(val_out), ++ c_export_method_call "ZMQ_Error" (meth.c_get) (args), ++ } ++ end ++ -- generate setter method. ++ name = meth.set ++ if name then ++ local args = { ltype, "value" } ++ if meth.otype == 'BLOB' then ++ args = { ltype, "value", "size_t", "#value" } ++ end ++ m[#m+1] = method (name) { if_defs = if_defs, ++ c_export_method_call "ZMQ_Error" (meth.c_set) (args), ++ } ++ end ++ end ++ end ++ ++ return tunpack(m, 1, #m) ++end ++ ++------------------------------------------------------------------------------------- ++-- ++-- ZeroMQ socket object. ++-- ++------------------------------------------------------------------------------------- ++ + object "ZMQ_Socket" { + error_on_null = "get_zmq_strerror()", +- c_source [[ +-/* detect zmq version >= 2.1.0 */ +-#define VERSION_2_1 0 +-#if defined(ZMQ_VERSION) +-#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0)) +-#undef VERSION_2_1 +-#define VERSION_2_1 1 +-#endif +-#endif ++ ffi_source "ffi_pre_cdef" [[ ++ ++-- detect zmq version ++local VERSION_2_0 = true ++local VERSION_2_1 = false ++local VERSION_2_2 = false ++local VERSION_3_0 = false ++local zver = _M.version() ++if zver[1] == 3 then ++ VERSION_2_0 = false ++ VERSION_3_0 = true ++elseif zver[1] == 2 and zver[2] == 2 then ++ VERSION_2_2 = true ++ VERSION_2_1 = true ++elseif zver[1] == 2 and zver[2] == 1 then ++ VERSION_2_1 = true ++end ++ ++if VERSION_2_0 then ++ ffi.cdef[==[ ++typedef int ZMQ_Error; ++typedef struct ZMQ_Socket ZMQ_Socket; ++typedef struct zmq_msg_t zmq_msg_t; ++ ++ZMQ_Error zmq_sendmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__("zmq_send"); ++ZMQ_Error zmq_recvmsg(ZMQ_Socket *sock, zmq_msg_t *msg, int flags) __asm__("zmq_recv"); ++]==] ++end ++]], ++ c_source ([[ + + /* detect really old ZeroMQ 2.0.x series. */ + #if !defined(ZMQ_RCVMORE) +-#error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" ++# error "Your version of ZeroMQ is too old. Please upgrade to version 2.1 or to the latest 2.0.x" + #endif + + typedef struct ZMQ_Socket ZMQ_Socket; +@@ -44,47 +439,23 @@ typedef SOCKET socket_t; + typedef int socket_t; + #endif + ++#if VERSION_2_0 ++# define zmq_sendmsg zmq_send ++# define zmq_recvmsg zmq_recv ++#endif ++ + /* socket option types. */ + #define OPT_TYPE_NONE 0 + #define OPT_TYPE_INT 1 + #define OPT_TYPE_UINT32 2 + #define OPT_TYPE_UINT64 3 + #define OPT_TYPE_INT64 4 +-#define OPT_TYPE_STR 5 ++#define OPT_TYPE_BLOB 5 + #define OPT_TYPE_FD 6 + + static const int opt_types[] = { +- OPT_TYPE_NONE, /* 0 unused */ +- OPT_TYPE_UINT64, /* 1 ZMQ_HWM */ +- OPT_TYPE_NONE, /* 2 unused */ +- OPT_TYPE_INT64, /* 3 ZMQ_SWAP */ +- OPT_TYPE_UINT64, /* 4 ZMQ_AFFINITY */ +- OPT_TYPE_STR, /* 5 ZMQ_IDENTITY */ +- OPT_TYPE_STR, /* 6 ZMQ_SUBSCRIBE */ +- OPT_TYPE_STR, /* 7 ZMQ_UNSUBSCRIBE */ +- OPT_TYPE_INT64, /* 8 ZMQ_RATE */ +- OPT_TYPE_INT64, /* 9 ZMQ_RECOVERY_IVL */ +- OPT_TYPE_INT64, /* 10 ZMQ_MCAST_LOOP */ +- OPT_TYPE_UINT64, /* 11 ZMQ_SNDBUF */ +- OPT_TYPE_UINT64, /* 12 ZMQ_RCVBUF */ +- OPT_TYPE_INT64, /* 13 ZMQ_RCVMORE */ +- +-#if VERSION_2_1 +- OPT_TYPE_FD, /* 14 ZMQ_FD */ +- OPT_TYPE_UINT32, /* 15 ZMQ_EVENTS */ +- OPT_TYPE_INT, /* 16 ZMQ_TYPE */ +- OPT_TYPE_INT, /* 17 ZMQ_LINGER */ +- OPT_TYPE_INT, /* 18 ZMQ_RECONNECT_IVL */ +- OPT_TYPE_INT, /* 19 ZMQ_BACKLOG */ +-#endif +-}; +-#if VERSION_2_1 +-#define MAX_OPTS ZMQ_BACKLOG +-#else +-#define MAX_OPTS ZMQ_RCVMORE +-#endif +- +-]], ++ OPT_TYPE_NONE, /* 0 unused */ ++]] .. opt_types .. options_c_code), + + destructor "close" { + c_method_call "ZMQ_Error" "zmq_close" {} +@@ -92,44 +463,47 @@ static const int opt_types[] = { + method "bind" { + c_method_call "ZMQ_Error" "zmq_bind" { "const char *", "addr" } + }, ++ method "unbind" { ++ if_defs = { "VERSION_3_2" }, ++ c_method_call "ZMQ_Error" "zmq_unbind" { "const char *", "addr" } ++ }, + method "connect" { + c_method_call "ZMQ_Error" "zmq_connect" { "const char *", "addr" } + }, ++ method "disconnect" { ++ if_defs = { "VERSION_3_2" }, ++ c_method_call "ZMQ_Error" "zmq_disconnect" { "const char *", "addr" } ++ }, + ffi_cdef[[ + int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); + int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); + ]], +- ffi_source[[ +-local option_types = { +-[zmq.HWM] = 'uint64_t[1]', +-[zmq.SWAP] = 'int64_t[1]', +-[zmq.AFFINITY] = 'uint64_t[1]', +-[zmq.IDENTITY] = 'string', +-[zmq.SUBSCRIBE] = 'string', +-[zmq.UNSUBSCRIBE] = 'string', +-[zmq.RATE] = 'int64_t[1]', +-[zmq.RECOVERY_IVL] = 'int64_t[1]', +-[zmq.MCAST_LOOP] = 'int64_t[1]', +-[zmq.SNDBUF] = 'uint64_t[1]', +-[zmq.RCVBUF] = 'uint64_t[1]', +-[zmq.RCVMORE] = 'int64_t[1]', +-[zmq.FD] = 'int[1]', +-[zmq.EVENTS] = 'uint32_t[1]', +-[zmq.TYPE] = 'int[1]', +-[zmq.LINGER] = 'int[1]', +-[zmq.RECONNECT_IVL] = 'int[1]', +-[zmq.BACKLOG] = 'int[1]', +-} +-local option_len = {} +-local option_tmps = {} +-for k,v in pairs(option_types) do +- if v ~= 'string' then +- option_len[k] = ffi.sizeof(v) +- option_tmps[k] = ffi.new(v, 0) +- end ++ ffi_source([[ ++local option_gets = {} ++local option_sets = {} ++ ++do ++ local opt_name ++ local methods = _meth.${object_name} ++ setmetatable(option_gets,{__index = function(tab,opt) ++ local opt_name = opt_name[opt] ++ if not opt_name then return nil end ++ local method = methods[opt_name] ++ rawset(tab, opt, method) ++ return method ++ end}) ++ setmetatable(option_sets,{__index = function(tab,opt) ++ local opt_name = opt_name[opt] ++ if not opt_name then return nil end ++ local method = methods['set_' .. opt_name] or methods[opt_name] ++ rawset(tab, opt, method) ++ return method ++ end}) ++ opt_name = { ++]] .. ffi_opt_names .. [[} + end + +-]], ++]]), + method "setopt" { + var_in{ "uint32_t", "opt" }, + var_in{ "", "val" }, +@@ -138,7 +512,7 @@ end + size_t val_len; + const void *val; + +-#if VERSION_2_1 ++#if defined(VERSION_2_1) || defined(VERSION_3_0) + socket_t fd_val; + #endif + int int_val; +@@ -146,12 +520,26 @@ end + uint64_t uint64_val; + int64_t int64_val; + ++#if VERSION_3_0 ++ /* 3.0 backwards compatibility support for HWM. */ ++ if(${opt} == ZMQ_HWM) { ++ int_val = luaL_checklong(L, ${val::idx}); ++ val = &int_val; ++ val_len = sizeof(int_val); ++ ${err} = zmq_setsockopt(${this}, ZMQ_SNDHWM, val, val_len); ++ if(-1 != ${err}) { ++ ${err} = zmq_setsockopt(${this}, ZMQ_RCVHWM, val, val_len); ++ } ++ goto finished; ++ } ++#endif ++ + if(${opt} > MAX_OPTS) { + return luaL_argerror(L, ${opt::idx}, "Invalid socket option."); + } + + switch(opt_types[${opt}]) { +-#if VERSION_2_1 ++#if defined(VERSION_2_1) || defined(VERSION_3_0) + case OPT_TYPE_FD: + fd_val = luaL_checklong(L, ${val::idx}); + val = &fd_val; +@@ -178,7 +566,7 @@ end + val = &int64_val; + val_len = sizeof(int64_val); + break; +- case OPT_TYPE_STR: ++ case OPT_TYPE_BLOB: + val = luaL_checklstring(L, ${val::idx}, &(val_len)); + break; + default: +@@ -187,20 +575,15 @@ end + break; + } + ${err} = zmq_setsockopt(${this}, ${opt}, val, val_len); ++finished: + ]], + ffi_source[[ +- local ctype = option_types[${opt}] +- local tval +- local tval_len = 0 +- if ctype == 'string' then +- tval = tostring(${val}) +- tval_len = #${val} ++ local set = option_sets[${opt}] ++ if set then ++ return set(${this},${val}) + else +- tval = option_tmps[${opt}] +- tval[0] = ${val} +- tval_len = option_len[${opt}] ++ error("Invalid socket option.") + end +- ${err} = C.zmq_setsockopt(${this}, ${opt}, tval, tval_len) + ]], + }, + ffi_source[[ +@@ -213,7 +596,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) + c_source[[ + size_t val_len; + +-#if VERSION_2_1 ++#if defined(VERSION_2_1) || defined(VERSION_3_0) + socket_t fd_val; + #endif + int int_val; +@@ -230,7 +613,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) + } + + switch(opt_types[${opt}]) { +-#if VERSION_2_1 ++#if defined(VERSION_2_1) || defined(VERSION_3_0) + case OPT_TYPE_FD: + val_len = sizeof(fd_val); + ${err} = zmq_getsockopt(${this}, ${opt}, &fd_val, &val_len); +@@ -272,7 +655,7 @@ local tmp_val_len = ffi.new('size_t[1]', 4) + return 1; + } + break; +- case OPT_TYPE_STR: ++ case OPT_TYPE_BLOB: + val_len = STR_MAX; + ${err} = zmq_getsockopt(${this}, ${opt}, str_val, &val_len); + if(0 == ${err}) { +@@ -289,62 +672,23 @@ local tmp_val_len = ffi.new('size_t[1]', 4) + lua_pushnil(L); + ]], + ffi_source[[ +- local ctype = option_types[${opt}] +- local val +- local val_len = tmp_val_len +- if ctype == 'string' then +- val_len[0] = 255 +- val = ffi.new('uint8_t[?]', val_len[0]) +- ffi.fill(val, val_len[0]) ++ local get = option_gets[${opt}] ++ if get then ++ return get(${this}) + else +- val = option_tmps[${opt}] +- val[0] = 0 +- val_len[0] = option_len[${opt}] +- end +- ${err} = C.zmq_getsockopt(${this}, ${opt}, val, val_len) +- if ${err} == 0 then +- if ctype == 'string' then +- val_len = val_len[0] +- return ffi.string(val, val_len) +- else +- return tonumber(val[0]) +- end ++ error("Invalid socket option.") + end + ]], + }, +- ffi_source[[ +--- temp. values for 'events' function. +-local events_tmp = ffi.new('uint32_t[1]', 0) +-local events_tmp_size = ffi.sizeof('uint32_t') +-local events_tmp_len = ffi.new('size_t[1]', events_tmp_size) +-local ZMQ_EVENTS = _M.EVENTS +-]], +- method "events" { +- var_out{ "uint32_t", "events" }, +- var_out{ "ZMQ_Error", "err" }, +- c_source[[ +-#if VERSION_2_1 +- size_t val_len = sizeof(${events}); +- ${err} = zmq_getsockopt(${this}, ZMQ_EVENTS, &(${events}), &val_len); +-#else +- luaL_error(L, "'events' method only supported in 0MQ version >= 2.1"); +-#endif +-]], +- ffi_source[[ +- events_tmp_len[0] = events_tmp_size +- ${err} = C.zmq_getsockopt(${this}, ZMQ_EVENTS, events_tmp, events_tmp_len); +- ${events} = events_tmp[0] +-]], +- }, + -- + -- zmq_send + -- + method "send_msg" { +- c_method_call "ZMQ_Error" "zmq_send" { "zmq_msg_t *", "msg", "int", "flags?" }, ++ c_method_call "ZMQ_Error" "zmq_sendmsg" { "zmq_msg_t *", "msg", "int", "flags?" }, + }, + -- create helper function for `zmq_send` + c_source[[ +-static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { ++LUA_NOBJ_API ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data_len, int flags) { + ZMQ_Error err; + zmq_msg_t msg; + /* initialize message */ +@@ -353,32 +697,22 @@ static ZMQ_Error simple_zmq_send(ZMQ_Socket *sock, const char *data, size_t data + /* fill message */ + memcpy(zmq_msg_data(&msg), data, data_len); + /* send message */ +- err = zmq_send(sock, &msg, flags); ++ err = zmq_sendmsg(sock, &msg, flags); + /* close message */ + zmq_msg_close(&msg); + } + return err; + } + ]], +- -- export helper function. +- ffi_export_function "ZMQ_Error" "simple_zmq_send" +- "(ZMQ_Socket *sock, const char *data, size_t data_len, int flags)", + method "send" { +- var_in{ "const char *", "data" }, +- var_in{ "int", "flags?" }, +- var_out{ "ZMQ_Error", "err" }, +- c_source[[ +- ${err} = simple_zmq_send(${this}, ${data}, ${data_len}, ${flags}); +-]], +- ffi_source[[ +- ${err} = simple_zmq_send(${this}, ${data}, ${data_len}, ${flags}); +-]], ++ c_export_method_call "ZMQ_Error" "simple_zmq_send" ++ { "const char *", "data", "size_t", "#data", "int", "flags?"} + }, + -- + -- zmq_recv + -- + method "recv_msg" { +- c_method_call "ZMQ_Error" "zmq_recv" { "zmq_msg_t *", "msg", "int", "flags?" }, ++ c_method_call "ZMQ_Error" "zmq_recvmsg" { "zmq_msg_t *", "msg", "int", "flags?" }, + }, + ffi_source[[ + local tmp_msg = ffi.new('zmq_msg_t') +@@ -393,8 +727,8 @@ local tmp_msg = ffi.new('zmq_msg_t') + ${err} = zmq_msg_init(&msg); + if(0 == ${err}) { + /* receive message */ +- ${err} = zmq_recv(${this}, &msg, ${flags}); +- if(0 == ${err}) { ++ ${err} = zmq_recvmsg(${this}, &msg, ${flags}); ++ if(${err} >= 0) { + ${data} = zmq_msg_data(&msg); + ${data_len} = zmq_msg_size(&msg); + } +@@ -412,8 +746,8 @@ local tmp_msg = ffi.new('zmq_msg_t') + end + + -- receive message +- ${err} = C.zmq_recv(${this}, msg, ${flags}) +- if 0 == ${err} then ++ ${err} = C.zmq_recvmsg(${this}, msg, ${flags}) ++ if ${err} >= 0 then + local data = ffi.string(C.zmq_msg_data(msg), C.zmq_msg_size(msg)) + -- close message + C.zmq_msg_close(msg) +@@ -425,5 +759,8 @@ local tmp_msg = ffi.new('zmq_msg_t') + C.zmq_msg_close(msg) + ]], + }, ++ ++ -- build option set/get methods. THIS MUST BE LAST. ++ build_option_methods(), + } + +diff --git a/src/threads.lua b/src/threads.lua +index 99257ea..dbdd3e7 100644 +--- a/src/threads.lua ++++ b/src/threads.lua +@@ -25,21 +25,6 @@ + local zmq = require"zmq" + local llthreads = require"llthreads" + +-local setmetatable = setmetatable +-local tonumber = tonumber +-local assert = assert +- +-local thread_mt = {} +-thread_mt.__index = thread_mt +- +-function thread_mt:start(detached) +- return self.thread:start(detached) +-end +- +-function thread_mt:join() +- return self.thread:join() +-end +- + local bootstrap_pre = [[ + local action, action_arg, parent_ctx = ... + local func +@@ -79,32 +64,31 @@ local function new_thread(ctx, action, action_arg, ...) + if ctx then + ctx = ctx:lightuserdata() + end +- local thread = llthreads.new(bootstrap_code, action, action_arg, ctx, ...) +- return setmetatable({ +- thread = thread, +- }, thread_mt) ++ return llthreads.new(bootstrap_code, action, action_arg, ctx, ...) + end + +-module(...) ++local M = {} + +-function set_bootstrap_prelude(code) ++function M.set_bootstrap_prelude(code) + bootstrap_code = bootstrap_pre .. code .. bootstrap_post + end + +-function runfile(ctx, file, ...) ++function M.runfile(ctx, file, ...) + return new_thread(ctx, 'runfile', file, ...) + end + +-function runstring(ctx, code, ...) ++function M.runstring(ctx, code, ...) + return new_thread(ctx, 'runstring', code, ...) + end + + local parent_ctx = nil +-function set_parent_ctx(ctx) ++function M.set_parent_ctx(ctx) + parent_ctx = ctx + end + +-function get_parent_ctx(ctx) ++function M.get_parent_ctx(ctx) + return parent_ctx + end + ++zmq.threads = M ++return M +diff --git a/tests/test_inproc.lua b/tests/test_inproc.lua +new file mode 100644 +index 0000000..a3c2d70 +--- /dev/null ++++ b/tests/test_inproc.lua +@@ -0,0 +1,75 @@ ++-- Copyright (c) 2011 Robert G. Jakabosky ++-- ++-- Permission is hereby granted, free of charge, to any person obtaining a copy ++-- of this software and associated documentation files (the "Software"), to deal ++-- in the Software without restriction, including without limitation the rights ++-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++-- copies of the Software, and to permit persons to whom the Software is ++-- furnished to do so, subject to the following conditions: ++-- ++-- The above copyright notice and this permission notice shall be included in ++-- all copies or substantial portions of the Software. ++-- ++-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++-- THE SOFTWARE. ++ ++if #arg < 1 then ++ print("usage: lua " .. arg[0] .. " [message-size] [roundtrip-count] [bind-to] [connect-to]") ++end ++ ++local message_size = tonumber(arg[1] or 1) ++local roundtrip_count = tonumber(arg[2] or 100) ++local bind_to = arg[3] or 'inproc://thread_lat_test' ++local connect_to = arg[4] or 'inproc://thread_lat_test' ++ ++local zmq = require"zmq" ++ ++local ctx = zmq.init(1) ++local server = assert(ctx:socket(zmq.REQ)) ++assert(server:bind(bind_to)) ++ ++local client = ctx:socket(zmq.REP) ++client:connect(connect_to) ++ ++local data = ("0"):rep(message_size) ++local msg = zmq.zmq_msg_t.init_size(message_size) ++local client_msg = zmq.zmq_msg_t() ++ ++print(string.format("message size: %i [B]", message_size)) ++print(string.format("roundtrip count: %i", roundtrip_count)) ++ ++local timer = zmq.stopwatch_start() ++ ++for i = 1, roundtrip_count do ++ -- server send ++ assert(server:send_msg(msg)) ++ ++ -- client recv ++ assert(client:recv_msg(client_msg)) ++ assert(client_msg:size() == message_size, "Invalid message size") ++ -- client send ++ assert(client:send_msg(client_msg)) ++ ++ -- server recv ++ assert(server:recv_msg(msg)) ++ assert(msg:size() == message_size, "Invalid message size") ++end ++ ++local elapsed = timer:stop() ++ ++server:close() ++client:close() ++ctx:term() ++ ++local latency = elapsed / roundtrip_count / 2 ++ ++print(string.format("mean latency: %.3f [us]", latency)) ++local secs = elapsed / (1000 * 1000) ++print(string.format("elapsed = %f", secs)) ++print(string.format("msg/sec = %f", roundtrip_count / secs)) ++ +diff --git a/ws/LICENSE_GPL.txt b/ws/LICENSE_GPL.txt +new file mode 100644 +index 0000000..94a9ed0 +--- /dev/null ++++ b/ws/LICENSE_GPL.txt +@@ -0,0 +1,674 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 3, 29 June 2007 ++ ++ Copyright (C) 2007 Free Software Foundation, Inc. ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The GNU General Public License is a free, copyleft license for ++software and other kinds of works. ++ ++ The licenses for most software and other practical works are designed ++to take away your freedom to share and change the works. By contrast, ++the GNU General Public License is intended to guarantee your freedom to ++share and change all versions of a program--to make sure it remains free ++software for all its users. We, the Free Software Foundation, use the ++GNU General Public License for most of our software; it applies also to ++any other work released this way by its authors. You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++them if you wish), that you receive source code or can get it if you ++want it, that you can change the software or use pieces of it in new ++free programs, and that you know you can do these things. ++ ++ To protect your rights, we need to prevent others from denying you ++these rights or asking you to surrender the rights. Therefore, you have ++certain responsibilities if you distribute copies of the software, or if ++you modify it: responsibilities to respect the freedom of others. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must pass on to the recipients the same ++freedoms that you received. You must make sure that they, too, receive ++or can get the source code. And you must show them these terms so they ++know their rights. ++ ++ Developers that use the GNU GPL protect your rights with two steps: ++(1) assert copyright on the software, and (2) offer you this License ++giving you legal permission to copy, distribute and/or modify it. ++ ++ For the developers' and authors' protection, the GPL clearly explains ++that there is no warranty for this free software. For both users' and ++authors' sake, the GPL requires that modified versions be marked as ++changed, so that their problems will not be attributed erroneously to ++authors of previous versions. ++ ++ Some devices are designed to deny users access to install or run ++modified versions of the software inside them, although the manufacturer ++can do so. This is fundamentally incompatible with the aim of ++protecting users' freedom to change the software. The systematic ++pattern of such abuse occurs in the area of products for individuals to ++use, which is precisely where it is most unacceptable. Therefore, we ++have designed this version of the GPL to prohibit the practice for those ++products. If such problems arise substantially in other domains, we ++stand ready to extend this provision to those domains in future versions ++of the GPL, as needed to protect the freedom of users. ++ ++ Finally, every program is threatened constantly by software patents. ++States should not allow patents to restrict development and use of ++software on general-purpose computers, but in those that do, we wish to ++avoid the special danger that patents applied to a free program could ++make it effectively proprietary. To prevent this, the GPL assures that ++patents cannot be used to render the program non-free. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ TERMS AND CONDITIONS ++ ++ 0. Definitions. ++ ++ "This License" refers to version 3 of the GNU General Public License. ++ ++ "Copyright" also means copyright-like laws that apply to other kinds of ++works, such as semiconductor masks. ++ ++ "The Program" refers to any copyrightable work licensed under this ++License. Each licensee is addressed as "you". "Licensees" and ++"recipients" may be individuals or organizations. ++ ++ To "modify" a work means to copy from or adapt all or part of the work ++in a fashion requiring copyright permission, other than the making of an ++exact copy. The resulting work is called a "modified version" of the ++earlier work or a work "based on" the earlier work. ++ ++ A "covered work" means either the unmodified Program or a work based ++on the Program. ++ ++ To "propagate" a work means to do anything with it that, without ++permission, would make you directly or secondarily liable for ++infringement under applicable copyright law, except executing it on a ++computer or modifying a private copy. Propagation includes copying, ++distribution (with or without modification), making available to the ++public, and in some countries other activities as well. ++ ++ To "convey" a work means any kind of propagation that enables other ++parties to make or receive copies. Mere interaction with a user through ++a computer network, with no transfer of a copy, is not conveying. ++ ++ An interactive user interface displays "Appropriate Legal Notices" ++to the extent that it includes a convenient and prominently visible ++feature that (1) displays an appropriate copyright notice, and (2) ++tells the user that there is no warranty for the work (except to the ++extent that warranties are provided), that licensees may convey the ++work under this License, and how to view a copy of this License. If ++the interface presents a list of user commands or options, such as a ++menu, a prominent item in the list meets this criterion. ++ ++ 1. Source Code. ++ ++ The "source code" for a work means the preferred form of the work ++for making modifications to it. "Object code" means any non-source ++form of a work. ++ ++ A "Standard Interface" means an interface that either is an official ++standard defined by a recognized standards body, or, in the case of ++interfaces specified for a particular programming language, one that ++is widely used among developers working in that language. ++ ++ The "System Libraries" of an executable work include anything, other ++than the work as a whole, that (a) is included in the normal form of ++packaging a Major Component, but which is not part of that Major ++Component, and (b) serves only to enable use of the work with that ++Major Component, or to implement a Standard Interface for which an ++implementation is available to the public in source code form. A ++"Major Component", in this context, means a major essential component ++(kernel, window system, and so on) of the specific operating system ++(if any) on which the executable work runs, or a compiler used to ++produce the work, or an object code interpreter used to run it. ++ ++ The "Corresponding Source" for a work in object code form means all ++the source code needed to generate, install, and (for an executable ++work) run the object code and to modify the work, including scripts to ++control those activities. However, it does not include the work's ++System Libraries, or general-purpose tools or generally available free ++programs which are used unmodified in performing those activities but ++which are not part of the work. For example, Corresponding Source ++includes interface definition files associated with source files for ++the work, and the source code for shared libraries and dynamically ++linked subprograms that the work is specifically designed to require, ++such as by intimate data communication or control flow between those ++subprograms and other parts of the work. ++ ++ The Corresponding Source need not include anything that users ++can regenerate automatically from other parts of the Corresponding ++Source. ++ ++ The Corresponding Source for a work in source code form is that ++same work. ++ ++ 2. Basic Permissions. ++ ++ All rights granted under this License are granted for the term of ++copyright on the Program, and are irrevocable provided the stated ++conditions are met. This License explicitly affirms your unlimited ++permission to run the unmodified Program. The output from running a ++covered work is covered by this License only if the output, given its ++content, constitutes a covered work. This License acknowledges your ++rights of fair use or other equivalent, as provided by copyright law. ++ ++ You may make, run and propagate covered works that you do not ++convey, without conditions so long as your license otherwise remains ++in force. You may convey covered works to others for the sole purpose ++of having them make modifications exclusively for you, or provide you ++with facilities for running those works, provided that you comply with ++the terms of this License in conveying all material for which you do ++not control copyright. Those thus making or running the covered works ++for you must do so exclusively on your behalf, under your direction ++and control, on terms that prohibit them from making any copies of ++your copyrighted material outside their relationship with you. ++ ++ Conveying under any other circumstances is permitted solely under ++the conditions stated below. Sublicensing is not allowed; section 10 ++makes it unnecessary. ++ ++ 3. Protecting Users' Legal Rights From Anti-Circumvention Law. ++ ++ No covered work shall be deemed part of an effective technological ++measure under any applicable law fulfilling obligations under article ++11 of the WIPO copyright treaty adopted on 20 December 1996, or ++similar laws prohibiting or restricting circumvention of such ++measures. ++ ++ When you convey a covered work, you waive any legal power to forbid ++circumvention of technological measures to the extent such circumvention ++is effected by exercising rights under this License with respect to ++the covered work, and you disclaim any intention to limit operation or ++modification of the work as a means of enforcing, against the work's ++users, your or third parties' legal rights to forbid circumvention of ++technological measures. ++ ++ 4. Conveying Verbatim Copies. ++ ++ You may convey verbatim copies of the Program's source code as you ++receive it, in any medium, provided that you conspicuously and ++appropriately publish on each copy an appropriate copyright notice; ++keep intact all notices stating that this License and any ++non-permissive terms added in accord with section 7 apply to the code; ++keep intact all notices of the absence of any warranty; and give all ++recipients a copy of this License along with the Program. ++ ++ You may charge any price or no price for each copy that you convey, ++and you may offer support or warranty protection for a fee. ++ ++ 5. Conveying Modified Source Versions. ++ ++ You may convey a work based on the Program, or the modifications to ++produce it from the Program, in the form of source code under the ++terms of section 4, provided that you also meet all of these conditions: ++ ++ a) The work must carry prominent notices stating that you modified ++ it, and giving a relevant date. ++ ++ b) The work must carry prominent notices stating that it is ++ released under this License and any conditions added under section ++ 7. This requirement modifies the requirement in section 4 to ++ "keep intact all notices". ++ ++ c) You must license the entire work, as a whole, under this ++ License to anyone who comes into possession of a copy. This ++ License will therefore apply, along with any applicable section 7 ++ additional terms, to the whole of the work, and all its parts, ++ regardless of how they are packaged. This License gives no ++ permission to license the work in any other way, but it does not ++ invalidate such permission if you have separately received it. ++ ++ d) If the work has interactive user interfaces, each must display ++ Appropriate Legal Notices; however, if the Program has interactive ++ interfaces that do not display Appropriate Legal Notices, your ++ work need not make them do so. ++ ++ A compilation of a covered work with other separate and independent ++works, which are not by their nature extensions of the covered work, ++and which are not combined with it such as to form a larger program, ++in or on a volume of a storage or distribution medium, is called an ++"aggregate" if the compilation and its resulting copyright are not ++used to limit the access or legal rights of the compilation's users ++beyond what the individual works permit. Inclusion of a covered work ++in an aggregate does not cause this License to apply to the other ++parts of the aggregate. ++ ++ 6. Conveying Non-Source Forms. ++ ++ You may convey a covered work in object code form under the terms ++of sections 4 and 5, provided that you also convey the ++machine-readable Corresponding Source under the terms of this License, ++in one of these ways: ++ ++ a) Convey the object code in, or embodied in, a physical product ++ (including a physical distribution medium), accompanied by the ++ Corresponding Source fixed on a durable physical medium ++ customarily used for software interchange. ++ ++ b) Convey the object code in, or embodied in, a physical product ++ (including a physical distribution medium), accompanied by a ++ written offer, valid for at least three years and valid for as ++ long as you offer spare parts or customer support for that product ++ model, to give anyone who possesses the object code either (1) a ++ copy of the Corresponding Source for all the software in the ++ product that is covered by this License, on a durable physical ++ medium customarily used for software interchange, for a price no ++ more than your reasonable cost of physically performing this ++ conveying of source, or (2) access to copy the ++ Corresponding Source from a network server at no charge. ++ ++ c) Convey individual copies of the object code with a copy of the ++ written offer to provide the Corresponding Source. This ++ alternative is allowed only occasionally and noncommercially, and ++ only if you received the object code with such an offer, in accord ++ with subsection 6b. ++ ++ d) Convey the object code by offering access from a designated ++ place (gratis or for a charge), and offer equivalent access to the ++ Corresponding Source in the same way through the same place at no ++ further charge. You need not require recipients to copy the ++ Corresponding Source along with the object code. If the place to ++ copy the object code is a network server, the Corresponding Source ++ may be on a different server (operated by you or a third party) ++ that supports equivalent copying facilities, provided you maintain ++ clear directions next to the object code saying where to find the ++ Corresponding Source. Regardless of what server hosts the ++ Corresponding Source, you remain obligated to ensure that it is ++ available for as long as needed to satisfy these requirements. ++ ++ e) Convey the object code using peer-to-peer transmission, provided ++ you inform other peers where the object code and Corresponding ++ Source of the work are being offered to the general public at no ++ charge under subsection 6d. ++ ++ A separable portion of the object code, whose source code is excluded ++from the Corresponding Source as a System Library, need not be ++included in conveying the object code work. ++ ++ A "User Product" is either (1) a "consumer product", which means any ++tangible personal property which is normally used for personal, family, ++or household purposes, or (2) anything designed or sold for incorporation ++into a dwelling. In determining whether a product is a consumer product, ++doubtful cases shall be resolved in favor of coverage. For a particular ++product received by a particular user, "normally used" refers to a ++typical or common use of that class of product, regardless of the status ++of the particular user or of the way in which the particular user ++actually uses, or expects or is expected to use, the product. A product ++is a consumer product regardless of whether the product has substantial ++commercial, industrial or non-consumer uses, unless such uses represent ++the only significant mode of use of the product. ++ ++ "Installation Information" for a User Product means any methods, ++procedures, authorization keys, or other information required to install ++and execute modified versions of a covered work in that User Product from ++a modified version of its Corresponding Source. The information must ++suffice to ensure that the continued functioning of the modified object ++code is in no case prevented or interfered with solely because ++modification has been made. ++ ++ If you convey an object code work under this section in, or with, or ++specifically for use in, a User Product, and the conveying occurs as ++part of a transaction in which the right of possession and use of the ++User Product is transferred to the recipient in perpetuity or for a ++fixed term (regardless of how the transaction is characterized), the ++Corresponding Source conveyed under this section must be accompanied ++by the Installation Information. But this requirement does not apply ++if neither you nor any third party retains the ability to install ++modified object code on the User Product (for example, the work has ++been installed in ROM). ++ ++ The requirement to provide Installation Information does not include a ++requirement to continue to provide support service, warranty, or updates ++for a work that has been modified or installed by the recipient, or for ++the User Product in which it has been modified or installed. Access to a ++network may be denied when the modification itself materially and ++adversely affects the operation of the network or violates the rules and ++protocols for communication across the network. ++ ++ Corresponding Source conveyed, and Installation Information provided, ++in accord with this section must be in a format that is publicly ++documented (and with an implementation available to the public in ++source code form), and must require no special password or key for ++unpacking, reading or copying. ++ ++ 7. Additional Terms. ++ ++ "Additional permissions" are terms that supplement the terms of this ++License by making exceptions from one or more of its conditions. ++Additional permissions that are applicable to the entire Program shall ++be treated as though they were included in this License, to the extent ++that they are valid under applicable law. If additional permissions ++apply only to part of the Program, that part may be used separately ++under those permissions, but the entire Program remains governed by ++this License without regard to the additional permissions. ++ ++ When you convey a copy of a covered work, you may at your option ++remove any additional permissions from that copy, or from any part of ++it. (Additional permissions may be written to require their own ++removal in certain cases when you modify the work.) You may place ++additional permissions on material, added by you to a covered work, ++for which you have or can give appropriate copyright permission. ++ ++ Notwithstanding any other provision of this License, for material you ++add to a covered work, you may (if authorized by the copyright holders of ++that material) supplement the terms of this License with terms: ++ ++ a) Disclaiming warranty or limiting liability differently from the ++ terms of sections 15 and 16 of this License; or ++ ++ b) Requiring preservation of specified reasonable legal notices or ++ author attributions in that material or in the Appropriate Legal ++ Notices displayed by works containing it; or ++ ++ c) Prohibiting misrepresentation of the origin of that material, or ++ requiring that modified versions of such material be marked in ++ reasonable ways as different from the original version; or ++ ++ d) Limiting the use for publicity purposes of names of licensors or ++ authors of the material; or ++ ++ e) Declining to grant rights under trademark law for use of some ++ trade names, trademarks, or service marks; or ++ ++ f) Requiring indemnification of licensors and authors of that ++ material by anyone who conveys the material (or modified versions of ++ it) with contractual assumptions of liability to the recipient, for ++ any liability that these contractual assumptions directly impose on ++ those licensors and authors. ++ ++ All other non-permissive additional terms are considered "further ++restrictions" within the meaning of section 10. If the Program as you ++received it, or any part of it, contains a notice stating that it is ++governed by this License along with a term that is a further ++restriction, you may remove that term. If a license document contains ++a further restriction but permits relicensing or conveying under this ++License, you may add to a covered work material governed by the terms ++of that license document, provided that the further restriction does ++not survive such relicensing or conveying. ++ ++ If you add terms to a covered work in accord with this section, you ++must place, in the relevant source files, a statement of the ++additional terms that apply to those files, or a notice indicating ++where to find the applicable terms. ++ ++ Additional terms, permissive or non-permissive, may be stated in the ++form of a separately written license, or stated as exceptions; ++the above requirements apply either way. ++ ++ 8. Termination. ++ ++ You may not propagate or modify a covered work except as expressly ++provided under this License. Any attempt otherwise to propagate or ++modify it is void, and will automatically terminate your rights under ++this License (including any patent licenses granted under the third ++paragraph of section 11). ++ ++ However, if you cease all violation of this License, then your ++license from a particular copyright holder is reinstated (a) ++provisionally, unless and until the copyright holder explicitly and ++finally terminates your license, and (b) permanently, if the copyright ++holder fails to notify you of the violation by some reasonable means ++prior to 60 days after the cessation. ++ ++ Moreover, your license from a particular copyright holder is ++reinstated permanently if the copyright holder notifies you of the ++violation by some reasonable means, this is the first time you have ++received notice of violation of this License (for any work) from that ++copyright holder, and you cure the violation prior to 30 days after ++your receipt of the notice. ++ ++ Termination of your rights under this section does not terminate the ++licenses of parties who have received copies or rights from you under ++this License. If your rights have been terminated and not permanently ++reinstated, you do not qualify to receive new licenses for the same ++material under section 10. ++ ++ 9. Acceptance Not Required for Having Copies. ++ ++ You are not required to accept this License in order to receive or ++run a copy of the Program. Ancillary propagation of a covered work ++occurring solely as a consequence of using peer-to-peer transmission ++to receive a copy likewise does not require acceptance. However, ++nothing other than this License grants you permission to propagate or ++modify any covered work. These actions infringe copyright if you do ++not accept this License. Therefore, by modifying or propagating a ++covered work, you indicate your acceptance of this License to do so. ++ ++ 10. Automatic Licensing of Downstream Recipients. ++ ++ Each time you convey a covered work, the recipient automatically ++receives a license from the original licensors, to run, modify and ++propagate that work, subject to this License. You are not responsible ++for enforcing compliance by third parties with this License. ++ ++ An "entity transaction" is a transaction transferring control of an ++organization, or substantially all assets of one, or subdividing an ++organization, or merging organizations. If propagation of a covered ++work results from an entity transaction, each party to that ++transaction who receives a copy of the work also receives whatever ++licenses to the work the party's predecessor in interest had or could ++give under the previous paragraph, plus a right to possession of the ++Corresponding Source of the work from the predecessor in interest, if ++the predecessor has it or can get it with reasonable efforts. ++ ++ You may not impose any further restrictions on the exercise of the ++rights granted or affirmed under this License. For example, you may ++not impose a license fee, royalty, or other charge for exercise of ++rights granted under this License, and you may not initiate litigation ++(including a cross-claim or counterclaim in a lawsuit) alleging that ++any patent claim is infringed by making, using, selling, offering for ++sale, or importing the Program or any portion of it. ++ ++ 11. Patents. ++ ++ A "contributor" is a copyright holder who authorizes use under this ++License of the Program or a work on which the Program is based. The ++work thus licensed is called the contributor's "contributor version". ++ ++ A contributor's "essential patent claims" are all patent claims ++owned or controlled by the contributor, whether already acquired or ++hereafter acquired, that would be infringed by some manner, permitted ++by this License, of making, using, or selling its contributor version, ++but do not include claims that would be infringed only as a ++consequence of further modification of the contributor version. For ++purposes of this definition, "control" includes the right to grant ++patent sublicenses in a manner consistent with the requirements of ++this License. ++ ++ Each contributor grants you a non-exclusive, worldwide, royalty-free ++patent license under the contributor's essential patent claims, to ++make, use, sell, offer for sale, import and otherwise run, modify and ++propagate the contents of its contributor version. ++ ++ In the following three paragraphs, a "patent license" is any express ++agreement or commitment, however denominated, not to enforce a patent ++(such as an express permission to practice a patent or covenant not to ++sue for patent infringement). To "grant" such a patent license to a ++party means to make such an agreement or commitment not to enforce a ++patent against the party. ++ ++ If you convey a covered work, knowingly relying on a patent license, ++and the Corresponding Source of the work is not available for anyone ++to copy, free of charge and under the terms of this License, through a ++publicly available network server or other readily accessible means, ++then you must either (1) cause the Corresponding Source to be so ++available, or (2) arrange to deprive yourself of the benefit of the ++patent license for this particular work, or (3) arrange, in a manner ++consistent with the requirements of this License, to extend the patent ++license to downstream recipients. "Knowingly relying" means you have ++actual knowledge that, but for the patent license, your conveying the ++covered work in a country, or your recipient's use of the covered work ++in a country, would infringe one or more identifiable patents in that ++country that you have reason to believe are valid. ++ ++ If, pursuant to or in connection with a single transaction or ++arrangement, you convey, or propagate by procuring conveyance of, a ++covered work, and grant a patent license to some of the parties ++receiving the covered work authorizing them to use, propagate, modify ++or convey a specific copy of the covered work, then the patent license ++you grant is automatically extended to all recipients of the covered ++work and works based on it. ++ ++ A patent license is "discriminatory" if it does not include within ++the scope of its coverage, prohibits the exercise of, or is ++conditioned on the non-exercise of one or more of the rights that are ++specifically granted under this License. You may not convey a covered ++work if you are a party to an arrangement with a third party that is ++in the business of distributing software, under which you make payment ++to the third party based on the extent of your activity of conveying ++the work, and under which the third party grants, to any of the ++parties who would receive the covered work from you, a discriminatory ++patent license (a) in connection with copies of the covered work ++conveyed by you (or copies made from those copies), or (b) primarily ++for and in connection with specific products or compilations that ++contain the covered work, unless you entered into that arrangement, ++or that patent license was granted, prior to 28 March 2007. ++ ++ Nothing in this License shall be construed as excluding or limiting ++any implied license or other defenses to infringement that may ++otherwise be available to you under applicable patent law. ++ ++ 12. No Surrender of Others' Freedom. ++ ++ If conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot convey a ++covered work so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you may ++not convey it at all. For example, if you agree to terms that obligate you ++to collect a royalty for further conveying from those to whom you convey ++the Program, the only way you could satisfy both those terms and this ++License would be to refrain entirely from conveying the Program. ++ ++ 13. Use with the GNU Affero General Public License. ++ ++ Notwithstanding any other provision of this License, you have ++permission to link or combine any covered work with a work licensed ++under version 3 of the GNU Affero General Public License into a single ++combined work, and to convey the resulting work. The terms of this ++License will continue to apply to the part which is the covered work, ++but the special requirements of the GNU Affero General Public License, ++section 13, concerning interaction through a network will apply to the ++combination as such. ++ ++ 14. Revised Versions of this License. ++ ++ The Free Software Foundation may publish revised and/or new versions of ++the GNU General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++ Each version is given a distinguishing version number. If the ++Program specifies that a certain numbered version of the GNU General ++Public License "or any later version" applies to it, you have the ++option of following the terms and conditions either of that numbered ++version or of any later version published by the Free Software ++Foundation. If the Program does not specify a version number of the ++GNU General Public License, you may choose any version ever published ++by the Free Software Foundation. ++ ++ If the Program specifies that a proxy can decide which future ++versions of the GNU General Public License can be used, that proxy's ++public statement of acceptance of a version permanently authorizes you ++to choose that version for the Program. ++ ++ Later license versions may give you additional or different ++permissions. However, no additional obligations are imposed on any ++author or copyright holder as a result of your choosing to follow a ++later version. ++ ++ 15. Disclaimer of Warranty. ++ ++ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY ++APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT ++HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY ++OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, ++THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM ++IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ++ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. Limitation of Liability. ++ ++ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS ++THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY ++GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE ++USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF ++DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD ++PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), ++EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGES. ++ ++ 17. Interpretation of Sections 15 and 16. ++ ++ If the disclaimer of warranty and limitation of liability provided ++above cannot be given local legal effect according to their terms, ++reviewing courts shall apply local law that most closely approximates ++an absolute waiver of all civil liability in connection with the ++Program, unless a warranty or assumption of liability accompanies a ++copy of the Program in return for a fee. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++state the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++ If the program does terminal interaction, make it output a short ++notice like this when it starts in an interactive mode: ++ ++ Copyright (C) ++ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, your program's commands ++might be different; for a GUI interface, you would use an "about box". ++ ++ You should also get your employer (if you work as a programmer) or school, ++if any, to sign a "copyright disclaimer" for the program, if necessary. ++For more information on this, and how to apply and follow the GNU GPL, see ++. ++ ++ The GNU General Public License does not permit incorporating your program ++into proprietary programs. If your program is a subroutine library, you ++may consider it more useful to permit linking proprietary applications with ++the library. If this is what you want to do, use the GNU Lesser General ++Public License instead of this License. But first, please read ++. +diff --git a/ws/dissector.lua b/ws/dissector.lua +new file mode 100644 +index 0000000..58fd043 +--- /dev/null ++++ b/ws/dissector.lua +@@ -0,0 +1,306 @@ ++-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. ++ ++-- cache globals to local for speed. ++local format=string.format ++local tostring=tostring ++local tonumber=tonumber ++local sqrt=math.sqrt ++local pairs=pairs ++ ++-- wireshark API globals ++local Pref = Pref ++local Proto = Proto ++local ProtoField = ProtoField ++local DissectorTable = DissectorTable ++local ByteArray = ByteArray ++local PI_MALFORMED = PI_MALFORMED ++local PI_ERROR = PI_ERROR ++ ++-- zmq protocol example ++-- declare our protocol ++local zmq_proto = Proto("zmq","ZMQ","ZeroMQ Protocol") ++ ++-- setup preferences ++zmq_proto.prefs["tcp_port_start"] = ++ Pref.string("TCP port range start", "5555", "First TCP port to decode as this protocol") ++zmq_proto.prefs["tcp_port_end"] = ++ Pref.string("TCP port range end", "5555", "Last TCP port to decode as this protocol") ++-- current preferences settings. ++local current_settings = { ++tcp_port_start = -1, ++tcp_port_end = -1, ++} ++ ++-- setup protocol fields. ++zmq_proto.fields = {} ++local fds = zmq_proto.fields ++fds.frame = ProtoField.new("Frame", "zmq.frame", "ftypes.BYTES", nil, "base.NONE") ++fds.length = ProtoField.new("Frame Length", "zmq.frame.len", "ftypes.UINT64", nil, "base.DEC") ++fds.length8 = ProtoField.new("Frame 8bit Length", "zmq.frame.len8", "ftypes.UINT8", nil, "base.DEC") ++fds.length64 = ProtoField.new("Frame 64bit Length", "zmq.frame.len64", "ftypes.UINT64", nil, "base.DEC") ++fds.flags = ProtoField.new("Frame Flags", "zmq.frame.flags", "ftypes.UINT8", nil, "base.HEX", "0xFF") ++fds.flags_more = ProtoField.new("More", "zmq.frame.flags.more", "ftypes.UINT8", nil, "base.HEX", "0x01") ++fds.body = ProtoField.new("Frame body", "zmq.frame.body", "ftypes.BYTES", nil, "base.NONE") ++ ++-- un-register zmq to handle tcp port range ++local function unregister_tcp_port_range(start_port, end_port) ++ if not start_port or start_port <= 0 or not end_port or end_port <= 0 then ++ return ++ end ++ local tcp_port_table = DissectorTable.get("tcp.port") ++ for port = start_port,end_port do ++ tcp_port_table:remove(port,zmq_proto) ++ end ++end ++ ++-- register zmq to handle tcp port range ++local function register_tcp_port_range(start_port, end_port) ++ if not start_port or start_port <= 0 or not end_port or end_port <= 0 then ++ return ++ end ++ local tcp_port_table = DissectorTable.get("tcp.port") ++ for port = start_port,end_port do ++ tcp_port_table:add(port,zmq_proto) ++ end ++end ++ ++-- handle preferences changes. ++function zmq_proto.init(arg1, arg2) ++ local old_start, old_end ++ local new_start, new_end ++ -- check if preferences have changed. ++ for pref_name,old_v in pairs(current_settings) do ++ local new_v = zmq_proto.prefs[pref_name] ++ if new_v ~= old_v then ++ if pref_name == "tcp_port_start" then ++ old_start = old_v ++ new_start = new_v ++ elseif pref_name == "tcp_port_end" then ++ old_end = old_v ++ new_end = new_v ++ end ++ -- save new value. ++ current_settings[pref_name] = new_v ++ end ++ end ++ -- un-register old port range ++ if old_start and old_end then ++ unregister_tcp_port_range(tonumber(old_start), tonumber(old_end)) ++ end ++ -- register new port range. ++ if new_start and new_end then ++ register_tcp_port_range(tonumber(new_start), tonumber(new_end)) ++ end ++end ++ ++-- parse flag bits. ++local BITS = { ++ MORE = 0x01, ++ RESERVED = 0x7E, ++} ++local flag_names = {"MORE"} ++local bits_lookup = {} ++local bits_list = { ++ {}, ++ {MORE = true}, ++ {MORE = true, RESERVED = true}, ++ {RESERVED = true}, ++} ++local function parse_flags(flags) ++ return bits_lookup[flags] or bits_lookup[1] ++end ++ ++-- make bits object ++local function make_bits(bits) ++ local proxy = newproxy(true) ++ local meta = getmetatable(proxy) ++ meta.__index = bits ++ meta.__tostring = function() ++ return bits.flags ++ end ++ -- combind bits into string description. ++ local flags = nil ++ for i=1,#flag_names do ++ local name = flag_names[i] ++ if bits[name] then ++ if flags then ++ flags = flags .. ',' .. name ++ else ++ flags = name ++ end ++ end ++ end ++ -- combind bits into one byte value. ++ local byte = 0x00 ++ for k,v in pairs(bits) do ++ local bit = assert(BITS[k], "Invalid bit name.") ++ byte = byte + BITS[k] ++ end ++ bits.flags = flags or '' ++ bits.byte = byte ++ return proxy ++end ++-- make bits objects in bis_lookup ++for i=1,#bits_list do ++ local bits = bits_list[i] ++ bits = make_bits(bits) ++ bits_lookup[bits.byte] = bits ++end ++ ++local function zmq_dissect_frame(buffer, pinfo, frame_tree, tap) ++ local rang,offset ++ -- Frame length ++ offset = 0 ++ local len_off = offset ++ local len8_rang = buffer(offset,1) ++ local len_rang = len8_rang ++ local frame_len = len8_rang:uint() ++ -- 8bit length field ++ local ti = frame_tree:add(fds.length8, len8_rang) ++ ti:set_hidden() ++ offset = offset + 1 ++ if frame_len == 255 then ++ local len64_rang = buffer(offset, 8) ++ len_rang = buffer(len_off, 9) ++ frame_len = tonumber(tostring(len64_rang:uint64())) ++ -- 64bit length field. ++ local ti = frame_tree:add(fds.length64, len64_rang) ++ ti:set_hidden() ++ offset = offset + 8 ++ local ti = frame_tree:add(fds.length, len_rang) ++ ti:set_text(format("Frame Length: %d", frame_length)) ++ else ++ frame_tree:add(fds.length, len_rang) ++ end ++ -- Frame flags ++ rang = buffer(offset,1) ++ local flags = rang:uint() ++ local flags_bits = parse_flags(flags) ++ local flags_list = flags_bits.flags ++ local flags_tree = frame_tree:add(fds.flags, rang) ++ flags_tree:set_text(format('Flags: 0x%02X (%s)', flags, flags_list)) ++ flags_tree:add(fds.flags_more, rang) ++ offset = offset + 1 ++ if flags_bits.MORE then ++ tap.more = tap.more + 1 ++ else ++ -- if the 'more' flag is not set then this is the last frame in a message. ++ tap.msgs = tap.msgs + 1 ++ end ++ -- Frame body ++ local body_len = frame_len - 1 ++ local body = '' ++ if body_len > 0 then ++ tap.body_bytes = tap.body_bytes + body_len ++ rang = buffer(offset, body_len) ++ local ti = frame_tree:add_le(fds.body, rang) ++ if body_len <= 4 then ++ body = format("%08x", rang:uint()) ++ else ++ body = tostring(rang) ++ end ++ ti:set_text(format("%s", body)) ++ end ++ offset = offset + body_len ++ -- frame summary ++ if body_len > 0 then ++ if flags_bits.MORE then ++ frame_tree:set_text(format("Frame: [MORE] Body[%u]=%s", body_len, body)) ++ else ++ frame_tree:set_text(format("Frame: Body[%u]=%s", body_len, body)) ++ end ++ else ++ if flags_bits.MORE then ++ frame_tree:set_text(format("Frame: [MORE] No data")) ++ else ++ frame_tree:set_text(format("Frame: No data")) ++ end ++ end ++end ++ ++local DESEGMENT_ONE_MORE_SEGMENT = 0x0fffffff ++local DESEGMENT_UNTIL_FIN = 0x0ffffffe ++ ++-- packet dissector ++function zmq_proto.dissector(tvb,pinfo,tree) ++ local offset = 0 ++ local tvb_length = tvb:len() ++ local reported_length = tvb:reported_len() ++ local length_remaining ++ local zmq_tree ++ local rang ++ local frames = 0 ++ local tap = {} ++ ++ tap.frames = 0 ++ tap.msgs = 0 ++ tap.more = 0 ++ tap.body_bytes = 0 ++ ++ while(offset < reported_length and offset < tvb_length) do ++ length_remaining = tvb_length - offset ++ -- check for fixed part of PDU ++ if length_remaining < 2 then ++ pinfo.desegment_offset = offset ++ pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT ++ break ++ end ++ -- decode frame length ++ -- decode single byte frame length ++ rang = tvb(offset, 1) ++ local frame_len = rang:le_uint() ++ local pdu_len = frame_len + 1 ++ if frame_len == 255 then ++ -- make sure there is enough bytes ++ if length_remaining < 10 then ++ pinfo.desegment_offset = offset ++ pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT ++ break ++ end ++ -- decode extra long frame length. ++ rang = tvb(offset + 1, 8) ++ frame_len = tonumber(tostring(rang:uint64())) ++ pdu_len = frame_len + 9 ++ end ++ -- provide hints to tcp ++ if not pinfo.visited then ++ local remaining_bytes = reported_length - offset ++ if pdu_len > remaining_bytes then ++ pinfo.want_pdu_tracking = 2 ++ pinfo.bytes_until_next_pdu = pdu_len - remaining_bytes ++ end ++ end ++ -- check if we need more bytes to dissect this frame. ++ if length_remaining < pdu_len then ++ pinfo.desegment_offset = offset ++ pinfo.desegment_len = (pdu_len - length_remaining) ++ break ++ end ++ -- dissect zmq frame ++ if not zmq_tree then ++ zmq_tree = tree:add(zmq_proto,tvb(),"ZMQ frames") ++ end ++ rang = tvb(offset, pdu_len) ++ local frame_tree = zmq_tree:add(fds.frame, rang) ++ zmq_dissect_frame(rang:tvb(), pinfo, frame_tree, tap) ++ frames = frames + 1 ++ -- step to next frame. ++ local offset_before = offset ++ offset = offset + pdu_len ++ if offset < offset_before then break end ++ end ++ if zmq_tree then ++ zmq_tree:set_text(format("ZMQ frames=%u", frames)) ++ end ++ if frames > 0 then ++ tap.frames = frames ++ pinfo.tap_data = tap ++ end ++ -- Info column ++ pinfo.cols.protocol = "ZMQ" ++ pinfo.cols.info = format('ZMQ frames=%u',frames) ++end ++ ++-- register zmq to handle tcp ports 5550-5560 ++register_tcp_port_range(5550,5560) ++ +diff --git a/ws/init.lua b/ws/init.lua +new file mode 100644 +index 0000000..0282fba +--- /dev/null ++++ b/ws/init.lua +@@ -0,0 +1,16 @@ ++ ++local prequire = function(name) ++ local status, result1 = pcall(require, name) ++ if not status then ++ debug("Failed to load " .. name .. ": " .. result1) ++ end ++ return result1 ++end ++ ++prequire("zmq.ws.dissector") ++ ++-- if running from wireshark, register all taps. ++if gui_enabled() then ++ prequire("zmq.ws.stats_tap") ++end ++ +diff --git a/ws/stats_tap.lua b/ws/stats_tap.lua +new file mode 100644 +index 0000000..1d39f16 +--- /dev/null ++++ b/ws/stats_tap.lua +@@ -0,0 +1,58 @@ ++-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. ++ ++local tap = require"zmq.ws.tap" ++ ++local format = string.format ++ ++local stats_tap_mt = {} ++stats_tap_mt.__index = stats_tap_mt ++ ++function stats_tap_mt:packet(pinfo, tvb, tree, data) ++ -- count all ZeroMQ packets ++ self.count = self.count + 1 ++ data = data or pinfo.tap_data ++ if not data then ++ return ++ end ++ -- frames ++ self.frames = self.frames + (data.frames or 0) ++ -- frames with more flag set ++ self.more = self.more + (data.more or 0) ++ -- whole messages. ++ self.msgs = self.msgs + (data.msgs or 0) ++ -- total bytes in frame bodies. ++ self.body_bytes = self.body_bytes + (data.body_bytes or 0) ++end ++ ++function stats_tap_mt:draw() ++ return format([[ ++ZeroMQ Packets: %d ++Frames: %d ++Messages: %d ++Flags: More: %d ++Payload bytes: %d ++]], ++ self.count, ++ self.frames, ++ self.msgs, ++ self.more, ++ self.body_bytes) ++end ++ ++function stats_tap_mt:reset() ++ self.count = 0 ++ self.frames = 0 ++ self.msgs = 0 ++ self.more = 0 ++ self.body_bytes = 0 ++end ++ ++local function create_stats_tap() ++ local tap = setmetatable({}, stats_tap_mt) ++ ++ tap:reset() -- initialize tap. ++ return tap, 'zmq', 'lua' ++end ++ ++tap("ZeroMQ stats tap", create_stats_tap) ++ +diff --git a/ws/tap.lua b/ws/tap.lua +new file mode 100644 +index 0000000..096332d +--- /dev/null ++++ b/ws/tap.lua +@@ -0,0 +1,84 @@ ++-- Copyright (c) 2011, Robert G. Jakabosky All rights reserved. ++ ++local gui_enabled = gui_enabled ++local register_menu = register_menu ++local MENU_TOOLS_UNSORTED = MENU_TOOLS_UNSORTED ++ ++local win_instances = 0 ++ ++local function create_window_tap(name, create) ++ win_instances = win_instances + 1 ++ ++ local td, tap_filter, tap_type = create() ++ ++ -- tap's output window. ++ local win = TextWindow.new(name .. " " .. win_instances) ++ ++ -- this tap will be local to the menu_function that called it ++ local tap = Listener.new(tap_type, tap_filter) ++ ++ -- callback to remove the tap when the text window closes ++ function remove_tap() ++ if tap and tap.remove then ++ tap:remove() ++ end ++ end ++ ++ -- make sure the tap doesn't hang around after the window was closed ++ win:set_atclose(remove_tap) ++ ++ -- this function will be called for every packet ++ function tap.packet(pinfo,tvb, tree, tapdata) ++ return td:packet(pinfo, tvb, tree, tapdata) ++ end ++ ++ -- this function will be called once every few seconds to redraw the window ++ function tap.draw() ++ local text = td:draw() ++ win:set(text) ++ end ++ ++ -- this function will be called at the end of the capture run. ++ function tap.reset() ++ return td:reset() ++ end ++end ++ ++local function create_tshark_tap(name, create) ++ ++ local td, tap_filter, tap_type = create() ++ ++ -- this tap will be local to the menu_function that called it ++ local tap = Listener.new(tap_type, tap_filter) ++ ++ -- this function will be called for every packet ++ function tap.packet(pinfo,tvb,tapdata) ++ return td:packet(pinfo, tvb, tapdata) ++ end ++ ++ -- this function will be called once every few seconds to redraw the window ++ function tap.draw() ++ local text = td:draw() ++ debug(name .. " results:\n" .. text) ++ end ++ ++ -- this function will be called at the end of the capture run. ++ function tap.reset() ++ return td:reset() ++ end ++end ++ ++return function (name, create) ++ if gui_enabled() then ++ -- menu callback. ++ local create_tap = function() ++ create_window_tap(name, create) ++ end ++ -- register menu item if running from wireshark ++ register_menu(name, create_tap, MENU_TOOLS_UNSORTED) ++ else ++ -- we are running from tshark, create a non-gui tap now. ++ create_tshark_tap(name, create) ++ end ++end ++ +diff --git a/zmq.nobj.lua b/zmq.nobj.lua +index 83c0aa5..e46193c 100644 +--- a/zmq.nobj.lua ++++ b/zmq.nobj.lua +@@ -23,110 +23,178 @@ set_variable_format "%s%d" + + c_module "zmq" { + -- module settings. ++module_globals = true, -- support old code that doesn't do: local zmq = require"zmq" + use_globals = false, + hide_meta_info = true, + luajit_ffi = true, +- +-sys_include "string.h", +-include "zmq.h", ++-- needed for functions exported from module. ++luajit_ffi_load_cmodule = true, + + ffi_load { + "zmq", -- default lib name. + Windows = "libzmq", -- lib name for on windows. + }, + +-c_source[[ +-/* +- * This wrapper function is to make the EAGAIN/ETERM error messages more like +- * what is returned by LuaSocket. +- */ +-static const char *get_zmq_strerror() { +- int err = zmq_errno(); +- switch(err) { +- case EAGAIN: +- return "timeout"; +- break; +-#if defined(ETERM) +- case ETERM: +- return "closed"; +- break; ++sys_include "string.h", ++include "zmq.h", ++ ++c_source "typedefs" [[ ++/* detect zmq version */ ++#define VERSION_2_0 1 ++#define VERSION_2_1 0 ++#define VERSION_2_2 0 ++#define VERSION_3_0 0 ++#define VERSION_3_2 0 ++#if defined(ZMQ_VERSION_MAJOR) ++# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 2) ++# undef VERSION_2_2 ++# define VERSION_2_2 1 ++# undef VERSION_2_1 ++# define VERSION_2_1 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 2) && (ZMQ_VERSION_MINOR == 1) ++# undef VERSION_2_1 ++# define VERSION_2_1 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 3) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_2 ++# define VERSION_3_2 1 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 2) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_2 ++# define VERSION_3_2 1 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif ++# if (ZMQ_VERSION_MAJOR == 3) ++# undef VERSION_2_0 ++# define VERSION_2_0 0 ++# undef VERSION_3_0 ++# define VERSION_3_0 1 ++# endif + #endif +- default: +- break; +- } +- return zmq_strerror(err); +-} + +-]], ++/* make sure ZMQ_DONTWAIT & ZMQ_NOBLOCK are both defined. */ ++#ifndef ZMQ_DONTWAIT ++# define ZMQ_DONTWAIT ZMQ_NOBLOCK ++#endif ++#ifndef ZMQ_NOBLOCK ++# define ZMQ_NOBLOCK ZMQ_DONTWAIT ++#endif + +--- export helper function 'get_zmq_strerror' to FFI code. +-ffi_export_function "const char *" "get_zmq_strerror" "()", +-ffi_source[[ +-local C_get_zmq_strerror = get_zmq_strerror +--- make nicer wrapper for exported error function. +-local function get_zmq_strerror() +- return ffi.string(C_get_zmq_strerror()) +-end ++/* make sure DEALER/ROUTER & XREQ/XREP are all defined. */ ++#ifndef ZMQ_DEALER ++# define ZMQ_DEALER ZMQ_XREQ ++#endif ++#ifndef ZMQ_ROUTER ++# define ZMQ_ROUTER ZMQ_XREP ++#endif ++#ifndef ZMQ_XREQ ++# define ZMQ_XREQ ZMQ_DEALER ++#endif ++#ifndef ZMQ_XREP ++# define ZMQ_XREP ZMQ_ROUTER ++#endif ++ ++#if VERSION_2_0 ++# define ZMQ_POLL_MSEC 1000 // zmq_poll is usec ++#elif VERSION_3_0 ++# define ZMQ_POLL_MSEC 1 // zmq_poll is msec ++# ifndef ZMQ_HWM ++# define ZMQ_HWM 1 // backwards compatibility ++# endif ++#endif + ]], + + -- + -- Module constants + -- +-constants { +-MAX_VSM_SIZE = 30, ++export_definitions { ++MAX_VSM_SIZE = "ZMQ_MAX_VSM_SIZE", ++ ++-- context settings ++MAX_SOCKETS = "ZMQ_MAX_SOCKETS", ++IO_THREADS = "ZMQ_IO_THREADS", + + -- message types +-DELIMITER = 31, +-VSM = 32, ++DELIMITER = "ZMQ_DELIMITER", ++VSM = "ZMQ_VSM", + + -- message flags +-MSG_MORE = 1, +-MSG_SHARED = 128, ++MSG_MORE = "ZMQ_MSG_MORE", ++MSG_SHARED = "ZMQ_MSG_SHARED", + + -- socket types +-PAIR = 0, +-PUB = 1, +-SUB = 2, +-REQ = 3, +-REP = 4, +-XREQ = 5, +-XREP = 6, +-PULL = 7, +-PUSH = 8, ++PAIR = "ZMQ_PAIR", ++PUB = "ZMQ_PUB", ++SUB = "ZMQ_SUB", ++REQ = "ZMQ_REQ", ++REP = "ZMQ_REP", ++PULL = "ZMQ_PULL", ++PUSH = "ZMQ_PUSH", ++ ++DEALER = "ZMQ_DEALER", ++ROUTER = "ZMQ_ROUTER", ++XREQ = "ZMQ_XREQ", ++XREP = "ZMQ_XREP", ++ ++-- new 3.1 socket types ++XPUB = "ZMQ_XPUB", ++XSUB = "ZMQ_XSUB", + + -- socket options +-HWM = 1, +-SWAP = 3, +-AFFINITY = 4, +-IDENTITY = 5, +-SUBSCRIBE = 6, +-UNSUBSCRIBE = 7, +-RATE = 8, +-RECOVERY_IVL = 9, +-MCAST_LOOP = 10, +-SNDBUF = 11, +-RCVBUF = 12, +-RCVMORE = 13, +-FD = 14, +-EVENTS = 15, +-TYPE = 16, +-LINGER = 17, +-RECONNECT_IVL = 18, +-BACKLOG = 19, ++HWM = "ZMQ_HWM", ++SWAP = "ZMQ_SWAP", ++AFFINITY = "ZMQ_AFFINITY", ++IDENTITY = "ZMQ_IDENTITY", ++SUBSCRIBE = "ZMQ_SUBSCRIBE", ++UNSUBSCRIBE = "ZMQ_UNSUBSCRIBE", ++RATE = "ZMQ_RATE", ++RECOVERY_IVL = "ZMQ_RECOVERY_IVL", ++MCAST_LOOP = "ZMQ_MCAST_LOOP", ++SNDBUF = "ZMQ_SNDBUF", ++RCVBUF = "ZMQ_RCVBUF", ++RCVMORE = "ZMQ_RCVMORE", ++FD = "ZMQ_FD", ++EVENTS = "ZMQ_EVENTS", ++TYPE = "ZMQ_TYPE", ++LINGER = "ZMQ_LINGER", ++RECONNECT_IVL = "ZMQ_RECONNECT_IVL", ++RECONNECT_IVL_MSEC= "ZMQ_RECONNECT_IVL_MSEC", ++BACKLOG = "ZMQ_BACKLOG", ++RECONNECT_IVL_MAX = "ZMQ_RECONNECT_IVL_MAX", ++MAXMSGSIZE = "ZMQ_MAXMSGSIZE", ++SNDHWM = "ZMQ_SNDHWM", ++RCVHWM = "ZMQ_RCVHWM", ++MULTICAST_HOPS = "ZMQ_MULTICAST_HOPS", ++RCVTIMEO = "ZMQ_RCVTIMEO", ++SNDTIMEO = "ZMQ_SNDTIMEO", ++RCVLABEL = "ZMQ_RCVLABEL", + + -- send/recv flags +-NOBLOCK = 1, +-SNDMORE = 2, ++NOBLOCK = "ZMQ_NOBLOCK", ++DONTWAIT = "ZMQ_DONTWAIT", ++SNDMORE = "ZMQ_SNDMORE", ++SNDLABEL = "ZMQ_SNDLABEL", + + -- poll events +-POLLIN = 1, +-POLLOUT = 2, +-POLLERR = 4, ++POLLIN = "ZMQ_POLLIN", ++POLLOUT = "ZMQ_POLLOUT", ++POLLERR = "ZMQ_POLLERR", ++ ++-- poll milliseconds. ++POLL_MSEC = "ZMQ_POLL_MSEC", + + -- devices +-STREAMER = 1, +-FORWARDER = 2, +-QUEUE = 3, ++STREAMER = "ZMQ_STREAMER", ++FORWARDER = "ZMQ_FORWARDER", ++QUEUE = "ZMQ_QUEUE", + }, + + +@@ -159,6 +227,7 @@ c_function "version" { + ]], + }, + c_function "init" { ++ var_in{ "int", "io_threads?", default = "1" }, + c_call "!ZMQ_Ctx *" "zmq_init" { "int", "io_threads" }, + }, + c_function "init_ctx" { +@@ -174,18 +243,22 @@ c_function "init_ctx" { + ffi_source[[ + local p_type = type(${ptr}) + if p_type == 'userdata' then +- ${ctx} = ffi.cast('void *', ${ptr}); +- elseif p_type == 'cdata' then +- ${ctx} = ${ptr}; ++ ${ctx} = ffi.cast('ZMQ_Ctx *', ${ptr}); ++ elseif p_type == 'cdata' and ffi.istype('void *', ${ptr}) then ++ ${ctx} = ffi.cast('ZMQ_Ctx *', ${ptr}); + else + return error("expected lightuserdata/cdata"); + end + ]], + }, +-c_function "device" { ++c_function "device" { if_defs = { "VERSION_2_0", "VERSION_3_2" }, + c_call "ZMQ_Error" "zmq_device" + { "int", "device", "ZMQ_Socket *", "insock", "ZMQ_Socket *", "outsock" }, + }, ++c_function "proxy" { if_defs = "VERSION_3_2", ++ c_call "ZMQ_Error" "zmq_proxy" ++ { "ZMQ_Socket *", "frontend", "ZMQ_Socket *", "backend", "ZMQ_Socket *", "capture?" }, ++}, + + -- + -- zmq_utils.h +@@ -197,16 +270,5 @@ c_function "stopwatch_start" { + c_function "sleep" { + c_call "void" "zmq_sleep" { "int", "seconds_" }, + }, +--- +--- This dump function is for getting a copy of the FFI-based bindings code and is +--- only for debugging. +--- +-c_function "dump_ffi" { +- var_out{ "const char *", "ffi_code", has_length = true, }, +- c_source[[ +- ${ffi_code} = ${module_c_name}_ffi_lua_code; +- ${ffi_code_len} = sizeof(${module_c_name}_ffi_lua_code) - 1; +-]], +-}, + } + -- cgit v1.2.3