nanomsg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: