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; -]], -}, }