diff options
Diffstat (limited to 'lib/wrappers/zmq.nim')
-rw-r--r-- | lib/wrappers/zmq.nim | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/lib/wrappers/zmq.nim b/lib/wrappers/zmq.nim new file mode 100644 index 000000000..8ebda26f9 --- /dev/null +++ b/lib/wrappers/zmq.nim @@ -0,0 +1,298 @@ +# Nimrod wrapper of 0mq +# Generated by c2nim with modifications and enhancement from Andreas Rumpf +# Original licence follows: + +# +# Copyright (c) 2007-2011 iMatix Corporation +# Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file +# +# This file is part of 0MQ. +# +# 0MQ is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# 0MQ 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# Generated from zmq version 2.1.5 + +## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as +## some higher level constructs. The higher level constructs are easily +## recognizable because they are the only ones that have documentation. + + +{.deadCodeElim: on.} +when defined(windows): + const + zmqdll* = "zmq.dll" +elif defined(macosx): + const + zmqdll* = "libzmq.dylib" +else: + const + zmqdll* = "libzmq.so" + +# A number random enough not to collide with different errno ranges on +# different OSes. The assumption is that error_t is at least 32-bit type. +const + HAUSNUMERO* = 156384712 + # On Windows platform some of the standard POSIX errnos are not defined. + ENOTSUP* = (HAUSNUMERO + 1) + EPROTONOSUPPORT* = (HAUSNUMERO + 2) + ENOBUFS* = (HAUSNUMERO + 3) + ENETDOWN* = (HAUSNUMERO + 4) + EADDRINUSE* = (HAUSNUMERO + 5) + EADDRNOTAVAIL* = (HAUSNUMERO + 6) + ECONNREFUSED* = (HAUSNUMERO + 7) + EINPROGRESS* = (HAUSNUMERO + 8) + # Native 0MQ error codes. + EFSM* = (HAUSNUMERO + 51) + ENOCOMPATPROTO* = (HAUSNUMERO + 52) + ETERM* = (HAUSNUMERO + 53) + EMTHREAD* = (HAUSNUMERO + 54) + # Maximal size of "Very Small Message". VSMs are passed by value + # to avoid excessive memory allocation/deallocation. + # If VMSs larger than 255 bytes are required, type of 'vsm_size' + # field in msg_t structure should be modified accordingly. + MAX_VSM_SIZE* = 30 + + POLLIN* = 1 + POLLOUT* = 2 + POLLERR* = 4 + + STREAMER* = 1 + FORWARDER* = 2 + QUEUE* = 3 + + PAIR* = 0 + PUB* = 1 + SUB* = 2 + REQ* = 3 + REP* = 4 + DEALER* = 5 + ROUTER* = 6 + PULL* = 7 + PUSH* = 8 + XPUB* = 9 + XSUB* = 10 + XREQ* = DEALER # Old alias, remove in 3.x + XREP* = ROUTER # Old alias, remove in 3.x + UPSTREAM* = PULL # Old alias, remove in 3.x + DOWNSTREAM* = PUSH # Old alias, remove in 3.x + +type + # Message types. These integers may be stored in 'content' member of the + # message instead of regular pointer to the data. + TMsgTypes* = enum + DELIMITER = 31, + VSM = 32 + # Message flags. MSG_SHARED is strictly speaking not a message flag + # (it has no equivalent in the wire format), however, making it a flag + # allows us to pack the stucture tighter and thus improve performance. + TMsgFlags* = enum + MSG_MORE = 1, + MSG_SHARED = 128, + MSG_MASK = 129 # Merges all the flags + # A message. Note that 'content' is not a pointer to the raw data. + # Rather it is pointer to zmq::msg_content_t structure + # (see src/msg_content.hpp for its definition). + TMsg*{.pure, final.} = object + content*: pointer + flags*: char + vsm_size*: char + vsm_data*: array[0..MAX_VSM_SIZE - 1, char] + + TFreeFn = proc (data, hint: pointer) {.noconv.} + + TContext {.final, pure.} = object + PContext* = ptr TContext + + # Socket Types + TSocket {.final, pure.} = object + PSocket* = ptr TSocket + + # Socket options. + TSockOptions* = enum + 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, + theTYPE = 16, + LINGER = 17, + RECONNECT_IVL = 18, + BACKLOG = 19, + RECOVERY_IVL_MSEC = 20, # opt. recovery time, reconcile in 3.x + RECONNECT_IVL_MAX = 21 + + # Send/recv options. + TSendRecvOptions* = enum + NOBLOCK, SNDMORE + + TPollItem*{.pure, final.} = object + socket*: PSocket + fd*: cint + events*: cshort + revents*: cshort + +# Run-time API version detection + +proc version*(major: var cint, minor: var cint, patch: var cint){.cdecl, + importc: "zmq_version", dynlib: zmqdll.} +#**************************************************************************** +# 0MQ errors. +#**************************************************************************** + +# This function retrieves the errno as it is known to 0MQ library. The goal +# of this function is to make the code 100% portable, including where 0MQ +# compiled with certain CRT library (on Windows) is linked to an +# application that uses different CRT library. + +proc errno*(): cint{.cdecl, importc: "zmq_errno", dynlib: zmqdll.} +# Resolves system errors and 0MQ errors to human-readable string. + +proc strerror*(errnum: cint): cstring {.cdecl, importc: "zmq_strerror", + dynlib: zmqdll.} +#**************************************************************************** +# 0MQ message definition. +#**************************************************************************** + +proc msg_init*(msg: var TMsg): cint{.cdecl, importc: "zmq_msg_init", + dynlib: zmqdll.} +proc msg_init*(msg: var TMsg, size: int): cint{.cdecl, + importc: "zmq_msg_init_size", dynlib: zmqdll.} +proc msg_init*(msg: var TMsg, data: cstring, size: int, + ffn: TFreeFn, hint: pointer): cint{.cdecl, + importc: "zmq_msg_init_data", dynlib: zmqdll.} +proc msg_close*(msg: var TMsg): cint {.cdecl, importc: "zmq_msg_close", + dynlib: zmqdll.} +proc msg_move*(dest, src: var TMsg): cint{.cdecl, + importc: "zmq_msg_move", dynlib: zmqdll.} +proc msg_copy*(dest, src: var TMsg): cint{.cdecl, + importc: "zmq_msg_copy", dynlib: zmqdll.} +proc msg_data*(msg: var TMsg): cstring {.cdecl, importc: "zmq_msg_data", + dynlib: zmqdll.} +proc msg_size*(msg: var TMsg): int {.cdecl, importc: "zmq_msg_size", + dynlib: zmqdll.} + +#**************************************************************************** +# 0MQ infrastructure (a.k.a. context) initialisation & termination. +#**************************************************************************** + +proc init*(io_threads: cint): PContext {.cdecl, importc: "zmq_init", + dynlib: zmqdll.} +proc term*(context: PContext): cint {.cdecl, importc: "zmq_term", + dynlib: zmqdll.} +#**************************************************************************** +# 0MQ socket definition. +#**************************************************************************** + +proc socket*(context: PContext, theType: cint): PSocket {.cdecl, + importc: "zmq_socket", dynlib: zmqdll.} +proc close*(s: PSocket): cint{.cdecl, importc: "zmq_close", dynlib: zmqdll.} +proc setsockopt*(s: PSocket, option: cint, optval: pointer, + optvallen: int): cint {.cdecl, importc: "zmq_setsockopt", + dynlib: zmqdll.} +proc getsockopt*(s: PSocket, option: cint, optval: pointer, + optvallen: ptr int): cint{.cdecl, + importc: "zmq_getsockopt", dynlib: zmqdll.} +proc bindAddr*(s: PSocket, address: cstring): cint{.cdecl, importc: "zmq_bind", + dynlib: zmqdll.} +proc connect*(s: PSocket, address: cstring): cint{.cdecl, + importc: "zmq_connect", dynlib: zmqdll.} +proc send*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, + importc: "zmq_send", dynlib: zmqdll.} +proc recv*(s: PSocket, msg: var TMsg, flags: cint): cint{.cdecl, + importc: "zmq_recv", dynlib: zmqdll.} +#**************************************************************************** +# I/O multiplexing. +#**************************************************************************** + +proc poll*(items: ptr TPollItem, nitems: cint, timeout: int): cint{. + cdecl, importc: "zmq_poll", dynlib: zmqdll.} + +#**************************************************************************** +# Built-in devices +#**************************************************************************** + +proc device*(device: cint, insocket, outsocket: PSocket): cint{. + cdecl, importc: "zmq_device", dynlib: zmqdll.} + +type + EZmq* = object of ESynch ## exception that is raised if something fails + TConnection* {.pure, final.} = object ## a connection + c*: PContext ## the embedded context + s*: PSocket ## the embedded socket + + TConnectionMode* = enum ## connection mode + conPAIR = 0, + conPUB = 1, + conSUB = 2, + conREQ = 3, + conREP = 4, + conDEALER = 5, + conROUTER = 6, + conPULL = 7, + conPUSH = 8, + conXPUB = 9, + conXSUB = 10 + +proc zmqError*() {.noinline, noreturn.} = + ## raises EZmq with error message from `zmq.strerror`. + var e: ref EZmq + new(e) + e.msg = $strerror(errno()) + raise e + +proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER, + numthreads = 4): TConnection = + ## opens a new connection. If `server` is true, it uses `bindAddr` for the + ## underlying socket, otherwise it opens the socket with `connect`. + result.c = init(cint(numthreads)) + if result.c == nil: zmqError() + result.s = socket(result.c, cint(ord(mode))) + if result.s == nil: zmqError() + if server: + if bindAddr(result.s, address) != 0'i32: zmqError() + else: + if connect(result.s, address) != 0'i32: zmqError() + +proc close*(c: var TConnection) = + ## closes the connection. + if close(c.s) != 0'i32: zmqError() + if term(c.c) != 0'i32: zmqError() + +proc send*(c: var TConnection, msg: string) = + ## sends a message over the connection. + var m: TMsg + if msg_init(m, msg.len) != 0'i32: zmqError() + copyMem(msg_data(m), cstring(msg), msg.len) + if send(c.s, m, 0'i32) != 0'i32: zmqError() + discard msg_close(m) + +proc receive*(c: var TConnection): string = + ## receives a message from a connection. + var m: TMsg + if msg_init(m) != 0'i32: zmqError() + if recv(c.s, m, 0'i32) != 0'i32: zmqError() + result = newString(msg_size(m)) + copyMem(addr(result[0]), msg_data(m), result.len) + discard msg_close(m) + |