nanomsg 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY ADDED
File without changes
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+
2
+ Copyright (c) 2013 Kaspar Schiess
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,47 @@
1
+
2
+ TLDR
3
+
4
+ An idiomatic nanomsg wrapper for Ruby. (http://nanomsg.org/)
5
+
6
+ NANOMSG
7
+
8
+ nanomsg library is a high-performance implementation of several "scalability
9
+ protocols". Scalability protocol's job is to define how multiple applications
10
+ communicate to form a single distributed application. Implementation of
11
+ following scalability protocols is available at the moment:
12
+
13
+ * PAIR - simple one-to-one communication
14
+ * BUS - simple many-to-many communication
15
+ * REQREP - allows to build clusters of stateless services to process user requests
16
+ * PUBSUB - distributes messages to large sets of interested subscribers
17
+ * FANIN - aggregates messages from multiple sources
18
+ * FANOUT - load balances messages among many destinations
19
+ * SURVEY - allows to query state of multiple applications in a single go
20
+
21
+ Scalability protocols are layered on top of transport layer in the network
22
+ stack. At the moment, nanomsg library supports following transports:
23
+
24
+ * INPROC - transport within a process (between threads, modules etc.)
25
+ * IPC - transport between processes on a single machine
26
+ * TCP - network transport via TCP
27
+
28
+ SYNOPSIS
29
+
30
+ require 'nanomsg'
31
+
32
+ socket1 = NanoMsg::PairSocket.new
33
+ socket1.bind('inproc://test')
34
+
35
+ socket1.send('test')
36
+ socket1.recv
37
+
38
+ STATUS
39
+
40
+ Very early alpha, not much testing has been done. Only the PAIR communication
41
+ type works. Nonblocking mode doesn't even begin to work. This will break your
42
+ application.
43
+
44
+ LICENSE
45
+
46
+ MIT, 2013, Kaspar Schiess
47
+
data/examples/pair.rb ADDED
@@ -0,0 +1,16 @@
1
+
2
+ $:.unshift File.dirname(__FILE__) + "/../lib"
3
+ require 'nanomsg'
4
+
5
+ sock1 = NanoMsg::PairSocket.new(NanoMsg::AF_SP)
6
+ sock1.bind("ipc:///tmp/test.ipc")
7
+
8
+ sock2 = NanoMsg::PairSocket.new(NanoMsg::AF_SP)
9
+ sock2.connect("ipc:///tmp/test.ipc")
10
+
11
+ sock1.send 'test'
12
+ sock1.send 'nanomsg'
13
+
14
+ puts sock2.recv
15
+ puts sock2.recv
16
+
@@ -0,0 +1,140 @@
1
+
2
+ # Example adapted from nn-cores roundtrip_latency.
3
+ # (https://raw.github.com/chuckremes/nn-core/master/examples/roundtrip_latency.rb)
4
+
5
+ $:.unshift File.dirname(__FILE__) + "/../lib"
6
+ require 'nanomsg'
7
+
8
+ # Within a single process, we start up two threads. One thread has a REQ (request)
9
+ # socket and the second thread has a REP (reply) socket. We measure the
10
+ # *round-trip* latency between these sockets. Only *one* message is in flight at
11
+ # any given moment.
12
+ #
13
+ # % ruby roundtrip_latency.rb tcp://127.0.0.1:5555 1024 1_000_000
14
+ #
15
+ # % ruby roundtrip_latency.rb inproc://lm_sock 1024 1_000_000
16
+ #
17
+
18
+ if ARGV.length < 3
19
+ puts "usage: ruby roundtrip_latency.rb <connect-to> <message-size> <roundtrip-count>"
20
+ exit
21
+ end
22
+
23
+ link = ARGV[0]
24
+ message_size = ARGV[1].to_i
25
+ roundtrip_count = ARGV[2].to_i
26
+
27
+ def set_signal_handler(receiver, transmitter)
28
+ trap(:INT) do
29
+ puts "got ctrl-c"
30
+ receiver.terminate
31
+ transmitter.terminate
32
+ end
33
+ end
34
+
35
+ class Node
36
+ def initialize(endpoint, size, count)
37
+ @endpoint = endpoint
38
+ @size = size
39
+ @count = count
40
+ @msg = 'a' * @size
41
+
42
+ setup_socket
43
+ set_endpoint
44
+ end
45
+
46
+ def setup_socket
47
+ @socket = NanoMsg::PairSocket.new
48
+ end
49
+
50
+ def send_msg
51
+ nbytes = @socket.send(@msg)
52
+ assert(nbytes)
53
+ nbytes
54
+ end
55
+
56
+ def recv_msg
57
+ msg = @socket.recv
58
+ nbytes = msg.bytesize
59
+ assert(nbytes)
60
+ nbytes
61
+ end
62
+
63
+ def terminate
64
+ # TODO
65
+ # assert(NNCore::LibNanomsg.nn_close(@socket))
66
+ end
67
+
68
+ def assert(rc)
69
+ raise "Last API call failed at #{caller(1)}" unless rc >= 0
70
+ end
71
+ end
72
+
73
+ class Receiver < Node
74
+ def set_endpoint
75
+ @socket.bind(@endpoint)
76
+ end
77
+
78
+ def run
79
+ @count.times do
80
+ nbytes = recv_msg
81
+
82
+ raise "Message size doesn't match, expected [#{@size}] but received [#{string.size}]" if @size != nbytes
83
+
84
+ send_msg
85
+ end
86
+
87
+ terminate
88
+ end
89
+ end
90
+
91
+ class Transmitter < Node
92
+ def set_endpoint
93
+ @socket.connect(@endpoint)
94
+ end
95
+
96
+ def run
97
+ elapsed = elapsed_microseconds do
98
+ @count.times do
99
+ send_msg
100
+
101
+ nbytes = recv_msg
102
+
103
+ raise "Message size doesn't match, expected [#{@size}] but received [#{nbytes}]" if @size != nbytes
104
+ end
105
+ end
106
+
107
+ latency = elapsed / @count / 2
108
+
109
+ puts "message size: %i [B]" % @size
110
+ puts "roundtrip count: %i" % @count
111
+ puts "throughput (msgs/s): %i" % (@count / (elapsed / 1_000_000))
112
+ puts "mean latency: %.3f [us]" % latency
113
+ terminate
114
+ end
115
+
116
+ def elapsed_microseconds(&blk)
117
+ start = Time.now
118
+ yield
119
+ value = ((Time.now - start) * 1_000_000)
120
+ end
121
+ end
122
+
123
+ threads = []
124
+ receiver = transmitter = nil
125
+
126
+ threads << Thread.new do
127
+ receiver = Receiver.new(link, message_size, roundtrip_count)
128
+ receiver.run
129
+ end
130
+
131
+ sleep 1
132
+
133
+ threads << Thread.new do
134
+ transmitter = Transmitter.new(link, message_size, roundtrip_count)
135
+ transmitter.run
136
+ end
137
+
138
+ set_signal_handler(receiver, transmitter)
139
+
140
+ threads.each {|t| t.join}
data/ext/Makefile ADDED
@@ -0,0 +1,218 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ n=$(NULLCMD)
9
+ ECHO1 = $(V:1=@$n)
10
+ ECHO = $(ECHO1:0=@echo)
11
+
12
+ #### Start of system configuration section. ####
13
+
14
+ srcdir = .
15
+ topdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1
16
+ hdrdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1
17
+ arch_hdrdir = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/$(arch)
18
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
19
+ prefix = $(DESTDIR)/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo
20
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
21
+ exec_prefix = $(prefix)
22
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
23
+ sitehdrdir = $(rubyhdrdir)/site_ruby
24
+ rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
25
+ vendordir = $(rubylibprefix)/vendor_ruby
26
+ sitedir = $(rubylibprefix)/site_ruby
27
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
28
+ mandir = $(datarootdir)/man
29
+ localedir = $(datarootdir)/locale
30
+ libdir = $(exec_prefix)/lib
31
+ psdir = $(docdir)
32
+ pdfdir = $(docdir)
33
+ dvidir = $(docdir)
34
+ htmldir = $(docdir)
35
+ infodir = $(datarootdir)/info
36
+ docdir = $(datarootdir)/doc/$(PACKAGE)
37
+ oldincludedir = $(DESTDIR)/usr/include
38
+ includedir = $(prefix)/include
39
+ localstatedir = $(prefix)/var
40
+ sharedstatedir = $(prefix)/com
41
+ sysconfdir = $(prefix)/etc
42
+ datadir = $(datarootdir)
43
+ datarootdir = $(prefix)/share
44
+ libexecdir = $(exec_prefix)/libexec
45
+ sbindir = $(exec_prefix)/sbin
46
+ bindir = $(exec_prefix)/bin
47
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
48
+ archdir = $(rubylibdir)/$(arch)
49
+ sitelibdir = $(sitedir)/$(ruby_version)
50
+ sitearchdir = $(sitelibdir)/$(sitearch)
51
+ vendorlibdir = $(vendordir)/$(ruby_version)
52
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
53
+
54
+ NULLCMD = :
55
+
56
+ CC = /usr/local/bin/gcc-4.2
57
+ CXX = g++
58
+ LIBRUBY = $(LIBRUBY_SO)
59
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
60
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
61
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
62
+ empty =
63
+ OUTFLAG = -o $(empty)
64
+ COUTFLAG = -o $(empty)
65
+
66
+ RUBY_EXTCONF_H =
67
+ cflags = $(optflags) $(debugflags) $(warnflags)
68
+ optflags = -O3
69
+ debugflags = -ggdb
70
+ warnflags = -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration
71
+ CFLAGS = -fno-common $(cflags) -fno-common -pipe $(ARCH_FLAG)
72
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
73
+ DEFS =
74
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags) -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include
75
+ CXXFLAGS = $(CFLAGS) $(cxxflags)
76
+ ldflags = -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
77
+ dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
78
+ ARCH_FLAG =
79
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
80
+ LDSHARED = $(CC) -dynamic -bundle
81
+ LDSHAREDXX = $(CXX) -dynamic -bundle
82
+ AR = ar
83
+ EXEEXT =
84
+
85
+ RUBY_BASE_NAME = ruby
86
+ RUBY_INSTALL_NAME = ruby
87
+ RUBY_SO_NAME = ruby.1.9.1
88
+ arch = x86_64-darwin12.3.0
89
+ sitearch = $(arch)
90
+ ruby_version = 1.9.1
91
+ ruby = /Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/bin/ruby
92
+ RUBY = $(ruby)
93
+ RM = rm -f
94
+ RM_RF = $(RUBY) -run -e rm -- -rf
95
+ RMDIRS = rmdir -p
96
+ MAKEDIRS = mkdir -p
97
+ INSTALL = /usr/bin/install -c
98
+ INSTALL_PROG = $(INSTALL) -m 0755
99
+ INSTALL_DATA = $(INSTALL) -m 644
100
+ COPY = cp
101
+ TOUCH = exit >
102
+
103
+ #### End of system configuration section. ####
104
+
105
+ preload =
106
+
107
+ libpath = . $(libdir) /usr/local/opt/libyaml/lib /usr/local/opt/readline/lib /usr/local/opt/libxml2/lib /usr/local/opt/libxslt/lib /usr/local/opt/libksba/lib /usr/local/opt/openssl/lib /usr/local/opt/sqlite/lib
108
+ LIBPATH = -L. -L$(libdir) -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib
109
+ DEFFILE =
110
+
111
+ CLEANFILES = mkmf.log
112
+ DISTCLEANFILES =
113
+ DISTCLEANDIRS =
114
+
115
+ extout =
116
+ extout_prefix =
117
+ target_prefix =
118
+ LOCAL_LIBS =
119
+ LIBS = $(LIBRUBYARG_SHARED) -lnanomsg -lpthread -ldl -lobjc
120
+ SRCS = init.c
121
+ OBJS = init.o
122
+ TARGET = nanomsg
123
+ DLLIB = $(TARGET).bundle
124
+ EXTSTATIC =
125
+ STATIC_LIB =
126
+
127
+ BINDIR = $(bindir)
128
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
129
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
130
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
131
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
132
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
133
+
134
+ TARGET_SO = $(DLLIB)
135
+ CLEANLIBS = $(TARGET).bundle
136
+ CLEANOBJS = *.o *.bak
137
+
138
+ all: $(DLLIB)
139
+ static: $(STATIC_LIB)
140
+ .PHONY: all install static install-so install-rb
141
+ .PHONY: clean clean-so clean-rb
142
+
143
+ clean-static::
144
+ clean-rb-default::
145
+ clean-rb::
146
+ clean-so::
147
+ clean: clean-so clean-static clean-rb-default clean-rb
148
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
149
+
150
+ distclean-rb-default::
151
+ distclean-rb::
152
+ distclean-so::
153
+ distclean: clean distclean-so distclean-rb-default distclean-rb
154
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
155
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
156
+ @-$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
157
+
158
+ realclean: distclean
159
+ install: install-so install-rb
160
+
161
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
162
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
163
+ -$(Q)$(MAKEDIRS) $(@D)
164
+ $(INSTALL_PROG) $(DLLIB) $(@D)
165
+ clean-static::
166
+ -$(Q)$(RM) $(STATIC_LIB)
167
+ install-rb: pre-install-rb install-rb-default
168
+ install-rb-default: pre-install-rb-default
169
+ pre-install-rb: Makefile
170
+ pre-install-rb-default: Makefile
171
+ pre-install-rb-default:
172
+ $(ECHO) installing default nanomsg libraries
173
+ ./.RUBYARCHDIR.time:
174
+ $(Q) $(MAKEDIRS) $(RUBYARCHDIR)
175
+ $(Q) $(TOUCH) $@
176
+
177
+ site-install: site-install-so site-install-rb
178
+ site-install-so: install-so
179
+ site-install-rb: install-rb
180
+
181
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .C .o
182
+
183
+ .cc.o:
184
+ $(ECHO) compiling $(<)
185
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
186
+
187
+ .mm.o:
188
+ $(ECHO) compiling $(<)
189
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
190
+
191
+ .cxx.o:
192
+ $(ECHO) compiling $(<)
193
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
194
+
195
+ .cpp.o:
196
+ $(ECHO) compiling $(<)
197
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
198
+
199
+ .C.o:
200
+ $(ECHO) compiling $(<)
201
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
202
+
203
+ .c.o:
204
+ $(ECHO) compiling $(<)
205
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
206
+
207
+ .m.o:
208
+ $(ECHO) compiling $(<)
209
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
210
+
211
+ $(DLLIB): $(OBJS) Makefile
212
+ $(ECHO) linking shared-object $(DLLIB)
213
+ -$(Q)$(RM) $(@)
214
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
215
+
216
+
217
+
218
+ $(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
data/ext/extconf.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ have_library 'nanomsg'
4
+
5
+ create_makefile('nanomsg')
data/ext/init.c ADDED
@@ -0,0 +1,271 @@
1
+
2
+ #include "ruby/ruby.h"
3
+
4
+ #include <nanomsg/nn.h>
5
+ #include <nanomsg/pair.h>
6
+
7
+ static VALUE cNanoMsg;
8
+ static VALUE cSocket;
9
+ static VALUE cPairSocket;
10
+ static VALUE ceSocketError;
11
+
12
+ struct nmsg_socket {
13
+ int socket;
14
+ };
15
+
16
+
17
+ static void
18
+ sock_mark(void *ptr)
19
+ {
20
+ // struct nmsg_socket *sock = ptr;
21
+ }
22
+
23
+ static void
24
+ sock_free(void *ptr)
25
+ {
26
+ struct nmsg_socket *sock = ptr;
27
+ xfree(sock);
28
+ }
29
+
30
+ static size_t
31
+ sock_memsize(const void *ptr)
32
+ {
33
+ return ptr ? sizeof(struct nmsg_socket) : 0;
34
+ }
35
+
36
+ static const rb_data_type_t socket_data_type = {
37
+ "nanomsg_socket",
38
+ {sock_mark, sock_free, sock_memsize,},
39
+ };
40
+
41
+ static struct nmsg_socket*
42
+ sock_get_ptr(VALUE socket)
43
+ {
44
+ struct nmsg_socket *psock;
45
+ TypedData_Get_Struct(socket, struct nmsg_socket, &socket_data_type, psock);
46
+
47
+ return psock;
48
+ }
49
+
50
+ static int
51
+ sock_get(VALUE socket)
52
+ {
53
+ struct nmsg_socket *psock = sock_get_ptr(socket);
54
+ return psock->socket;
55
+ }
56
+
57
+ static VALUE
58
+ sock_alloc(VALUE klass)
59
+ {
60
+ VALUE obj;
61
+ struct nmsg_socket *psock;
62
+
63
+ obj = TypedData_Make_Struct(klass, struct nmsg_socket, &socket_data_type, psock);
64
+ return obj;
65
+ }
66
+
67
+ static void
68
+ sock_raise_error(int code)
69
+ {
70
+ printf("socket error %d errno %d\n", code, errno);
71
+
72
+ // TODO allow querying of the errno at the very least.
73
+ switch (errno) {
74
+ case EBADF:
75
+ rb_raise(ceSocketError, "The provided socket is invalid.");
76
+ break;
77
+ case ENOTSUP:
78
+ rb_raise(ceSocketError, "The operation is not supported by this socket type.");
79
+ break;
80
+ case EFSM:
81
+ rb_raise(ceSocketError, "The operation cannot be performed on this socket at the moment because the socket is not in the appropriate state.");
82
+ break;
83
+ case EAGAIN:
84
+ rb_raise(ceSocketError, "Non-blocking mode was requested and the message cannot be sent at the moment.");
85
+ break;
86
+ case EINTR:
87
+ rb_raise(ceSocketError, "The operation was interrupted by delivery of a signal before the message was sent.");
88
+ break;
89
+ case ETIMEDOUT:
90
+ rb_raise(ceSocketError, "Individual socket types may define their own specific timeouts. If such timeout is hit, this error will be returned.");
91
+ break;
92
+ case EAFNOSUPPORT:
93
+ rb_raise(ceSocketError, "Specified address family is not supported.");
94
+ break;
95
+ case EINVAL:
96
+ rb_raise(ceSocketError, "Unknown protocol.");
97
+ break;
98
+ case EMFILE:
99
+ rb_raise(ceSocketError, "The limit on the total number of open SP sockets or OS limit for file descriptors has been reached.");
100
+ break;
101
+ case ETERM:
102
+ rb_raise(ceSocketError, "The library is terminating.");
103
+ break;
104
+ default:
105
+ rb_raise(ceSocketError, "Unknown error code %d", errno);
106
+ }
107
+ }
108
+
109
+ static VALUE
110
+ sock_bind(VALUE socket, VALUE bind)
111
+ {
112
+ int sock = sock_get(socket);
113
+ int endpoint;
114
+
115
+ endpoint = nn_bind(sock, StringValueCStr(bind));
116
+ if (endpoint < 0)
117
+ sock_raise_error(endpoint);
118
+
119
+ // TODO do something with the endpoint, returning it in a class for example.
120
+ return Qnil;
121
+ }
122
+
123
+ static VALUE
124
+ sock_connect(VALUE socket, VALUE connect)
125
+ {
126
+ int sock = sock_get(socket);
127
+ int endpoint;
128
+
129
+ endpoint = nn_connect(sock, StringValueCStr(connect));
130
+ if (endpoint < 0)
131
+ sock_raise_error(endpoint);
132
+
133
+ // TODO do something with the endpoint, returning it in a class for example.
134
+ return Qnil;
135
+ }
136
+
137
+ struct ioop {
138
+ int last_code;
139
+ int sock;
140
+ char* buffer;
141
+ long len;
142
+ int abort;
143
+ };
144
+
145
+ static VALUE
146
+ sock_send_no_gvl(void* data)
147
+ {
148
+ struct ioop *pio = data;
149
+
150
+ while (pio->last_code == EAGAIN && !pio->abort) {
151
+ pio->last_code = nn_send(pio->sock, pio->buffer, pio->len, NN_DONTWAIT /* flags */);
152
+
153
+ if (pio->last_code < 0)
154
+ pio->last_code = errno;
155
+ }
156
+
157
+ return Qnil;
158
+ }
159
+
160
+ static void
161
+ sock_send_abort(void* data)
162
+ {
163
+ struct ioop *pio = data;
164
+ pio->abort = Qtrue;
165
+ }
166
+
167
+ static VALUE
168
+ sock_send(VALUE socket, VALUE buffer)
169
+ {
170
+ struct ioop io;
171
+
172
+ io.sock = sock_get(socket);
173
+ io.last_code = EAGAIN;
174
+ io.buffer = StringValuePtr(buffer);
175
+ io.len = RSTRING_LEN(buffer);
176
+ io.abort = Qfalse;
177
+
178
+ rb_thread_blocking_region(sock_send_no_gvl, &io, sock_send_abort, &io);
179
+
180
+ // Unclear what to do in this situation, but we'll simply return nil,
181
+ // leaving Ruby to handle the abort.
182
+ if (io.abort)
183
+ return Qnil;
184
+
185
+ if (io.last_code < 0)
186
+ sock_raise_error(io.last_code);
187
+
188
+ return INT2NUM(io.last_code);
189
+ }
190
+
191
+ static VALUE
192
+ sock_recv_no_gvl(void* data)
193
+ {
194
+ struct ioop *pio = data;
195
+
196
+ while (pio->last_code == EAGAIN && !pio->abort) {
197
+ pio->last_code = nn_recv(pio->sock, &pio->buffer, NN_MSG, NN_DONTWAIT /* flags */);
198
+
199
+ if (pio->last_code < 0)
200
+ pio->last_code = errno;
201
+ }
202
+
203
+ return Qnil;
204
+ }
205
+
206
+ static void
207
+ sock_recv_abort(void* data)
208
+ {
209
+ struct ioop *pio = data;
210
+
211
+ pio->abort = Qtrue;
212
+ }
213
+
214
+ static VALUE
215
+ sock_recv(VALUE socket)
216
+ {
217
+ VALUE result;
218
+ struct ioop io;
219
+
220
+ io.sock = sock_get(socket);
221
+ io.buffer = (char*) 0;
222
+ io.abort = Qfalse;
223
+ io.last_code = EAGAIN;
224
+
225
+ rb_thread_blocking_region(sock_recv_no_gvl, &io, sock_recv_abort, &io);
226
+
227
+ if (io.abort)
228
+ return Qnil;
229
+
230
+ if (io.last_code < 0)
231
+ sock_raise_error(io.last_code);
232
+
233
+ result = rb_str_new(io.buffer, io.last_code);
234
+ nn_freemsg(io.buffer); io.buffer = (char*) 0;
235
+
236
+ return result;
237
+ }
238
+
239
+ static VALUE
240
+ pair_sock_init(VALUE socket)
241
+ {
242
+ struct nmsg_socket *psock = sock_get_ptr(socket);
243
+
244
+ psock->socket = nn_socket(AF_SP, NN_PAIR);
245
+ if (psock->socket < 0) {
246
+ sock_raise_error(psock->socket);
247
+ }
248
+
249
+ return socket;
250
+ }
251
+
252
+ void
253
+ Init_nanomsg(void)
254
+ {
255
+ printf("loading nanomsg extension\n");
256
+
257
+ cNanoMsg = rb_define_module("NanoMsg");
258
+ cSocket = rb_define_class_under(cNanoMsg, "Socket", rb_cObject);
259
+ cPairSocket = rb_define_class_under(cNanoMsg, "PairSocket", cSocket);
260
+
261
+ ceSocketError = rb_define_class_under(cNanoMsg, "SocketError", rb_eIOError);
262
+
263
+ rb_define_method(cSocket, "bind", sock_bind, 1);
264
+ rb_define_method(cSocket, "connect", sock_connect, 1);
265
+ rb_define_method(cSocket, "send", sock_send, 1);
266
+ rb_define_method(cSocket, "recv", sock_recv, 0);
267
+
268
+ rb_define_alloc_func(cPairSocket, sock_alloc);
269
+ rb_define_method(cPairSocket, "initialize", pair_sock_init, 0);
270
+ }
271
+
data/ext/init.o ADDED
Binary file
data/ext/mkmf.log ADDED
@@ -0,0 +1,22 @@
1
+ have_library: checking for main() in -lnanomsg... -------------------- yes
2
+
3
+ "/usr/local/bin/gcc-4.2 -o conftest -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/x86_64-darwin12.3.0 -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/ruby/backward -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -O3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -fno-common -pipe conftest.c -L. -L/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -lruby.1.9.1 -lpthread -ldl -lobjc "
4
+ checked program was:
5
+ /* begin */
6
+ 1: #include "ruby.h"
7
+ 2:
8
+ 3: int main() {return 0;}
9
+ /* end */
10
+
11
+ "/usr/local/bin/gcc-4.2 -o conftest -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/x86_64-darwin12.3.0 -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1/ruby/backward -I/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -I/usr/local/opt/libyaml/include -I/usr/local/opt/readline/include -I/usr/local/opt/libxml2/include -I/usr/local/opt/libxslt/include -I/usr/local/opt/libksba/include -I/usr/local/opt/openssl/include -I/usr/local/opt/sqlite/include -O3 -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -fno-common -pipe conftest.c -L. -L/Users/kschiess/.rvm/rubies/ruby-1.9.3-p392-turbo/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -L. -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/libxml2/lib -L/usr/local/opt/libxslt/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib -lruby.1.9.1 -lnanomsg -lpthread -ldl -lobjc "
12
+ checked program was:
13
+ /* begin */
14
+ 1: #include "ruby.h"
15
+ 2:
16
+ 3: /*top*/
17
+ 4: int main() {return 0;}
18
+ 5: int t() { void ((*volatile p)()); p = (void ((*)()))main; return 0; }
19
+ /* end */
20
+
21
+ --------------------
22
+
Binary file
data/ext/nanomsg.o ADDED
Binary file
data/lib/nanomsg.rb ADDED
@@ -0,0 +1,10 @@
1
+
2
+ $:.unshift File.dirname(__FILE__) + "/../ext"
3
+ require 'nanomsg.bundle'
4
+
5
+ module NanoMsg
6
+ class Socket
7
+ end
8
+ end
9
+
10
+ require 'nanomsg/pair_socket'
@@ -0,0 +1,6 @@
1
+
2
+
3
+ module NanoMsg
4
+ class PairSocket < Socket
5
+ end
6
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe NanoMsg::PairSocket do
4
+ let(:sock1) { NanoMsg::PairSocket.new }
5
+ let(:sock2) { NanoMsg::PairSocket.new }
6
+
7
+ def self.examples_for_transport tbind
8
+ name = tbind.split('://').first
9
+
10
+ describe "transport #{name}" do
11
+ it 'allows simple send/recv' do
12
+ sock1.bind(tbind)
13
+ sock2.connect(tbind)
14
+
15
+ sock1.send('1234').should == 4
16
+ sock2.recv.should == '1234'
17
+
18
+ sock2.send('5678').should == 4
19
+ sock1.recv.should == '5678'
20
+ end
21
+ end
22
+ end
23
+
24
+ examples_for_transport "ipc:///tmp/test.ipc"
25
+ examples_for_transport "tcp://127.0.0.1:5555"
26
+ examples_for_transport "inproc://test"
27
+ end
@@ -0,0 +1,4 @@
1
+
2
+
3
+ $:.unshift File.dirname(__FILE__) + "/../ext"
4
+ require 'nanomsg'
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nanomsg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kaspar Schiess
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-08-22 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! " nanomsg provides idiomatic Ruby bindings to the C library nanomsg
15
+ (nanomsg.org)\n\n nanomsg library is a high-performance implementation of several
16
+ \"scalability \n protocols\". Scalability protocol's job is to define how multiple
17
+ applications \n communicate to form a single distributed application. Implementation
18
+ of \n following scalability protocols is available at the moment:\n\n PAIR
19
+ - simple one-to-one communication\n BUS - simple many-to-many communication\n
20
+ \ REQREP - allows to build clusters of stateless services to process user requests\n
21
+ \ PUBSUB - distributes messages to large sets of interested subscribers\n FANIN
22
+ - aggregates messages from multiple sources\n FANOUT - load balances messages
23
+ among many destinations\n SURVEY - allows to query state of multiple applications
24
+ in a single go\n\n WARNING: nanomsg is still in alpha stage!\n"
25
+ email: kaspar.schiess@absurd.li
26
+ executables: []
27
+ extensions:
28
+ - ext/extconf.rb
29
+ extra_rdoc_files:
30
+ - README
31
+ files:
32
+ - HISTORY
33
+ - LICENSE
34
+ - README
35
+ - lib/nanomsg/pair_socket.rb
36
+ - lib/nanomsg.rb
37
+ - ext/extconf.rb
38
+ - ext/init.c
39
+ - ext/init.o
40
+ - ext/Makefile
41
+ - ext/mkmf.log
42
+ - ext/nanomsg.bundle
43
+ - ext/nanomsg.o
44
+ - examples/pair.rb
45
+ - examples/roundtrip_latency.rb
46
+ - spec/lib/nanomsg/pair_socket_spec.rb
47
+ - spec/spec_helper.rb
48
+ homepage: https://bitbucket.org/kschiess/nanomsg
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --main
53
+ - README
54
+ require_paths:
55
+ - lib
56
+ - ext
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.25
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Ruby binding for nanomsg. nanomsg library is a high-performance implementation
75
+ of several "scalability protocols".
76
+ test_files: []
77
+ has_rdoc: