nanomsg 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +16 -0
- data/README +9 -5
- data/examples/bus.rb +32 -0
- data/examples/bus_device.rb +39 -0
- data/examples/pair.rb +2 -2
- data/ext/Makefile +2 -2
- data/ext/constants.c +89 -0
- data/ext/constants.h +9 -0
- data/ext/constants.o +0 -0
- data/ext/init.c +272 -73
- data/ext/init.o +0 -0
- data/ext/nanomsg.bundle +0 -0
- data/spec/lib/nanomsg/bus_spec.rb +34 -0
- data/spec/lib/nanomsg/device_spec.rb +41 -0
- data/spec/lib/nanomsg/pair_socket_spec.rb +5 -0
- data/spec/lib/nanomsg/pub_sub_spec.rb +58 -0
- data/spec/lib/nanomsg/push_pull_spec.rb +70 -0
- data/spec/lib/nanomsg/req_rep_spec.rb +33 -0
- data/spec/lib/nanomsg/survey_spec.rb +47 -0
- data/spec/lib/nanomsg_spec.rb +11 -0
- data/spec/spec_helper.rb +7 -1
- metadata +17 -14
- data/ext/mkmf.log +0 -22
- data/ext/nanomsg.o +0 -0
data/HISTORY
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
= 0.2 /
|
3
|
+
|
4
|
+
* Adds REQ/REP socket type (ReqSocket, RepSocket).
|
5
|
+
* Adds PUB/SUB socket type.
|
6
|
+
* Adds SURVEYOR/RESPONDENT socket types. (SurveySocket, RespondSocket)
|
7
|
+
* Adds PUSH/PULL socket types. (PushSocket, PullSocket)
|
8
|
+
* Adds BUS socket type. (BusSocket)
|
9
|
+
* There's an experimental API for devices (.run_loopback, .run_device).
|
10
|
+
Devices block a Ruby thread until .terminate is called.
|
11
|
+
* Exceptions raised are now subclasses of NanoMsg::Errno
|
12
|
+
* Added NanoMsg.terminate, calls nn_term.
|
13
|
+
|
14
|
+
= 0.1 / 22Aug2013
|
15
|
+
|
16
|
+
* Initial release, only PAIR sockets supported.
|
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
TLDR
|
3
3
|
|
4
|
-
An idiomatic nanomsg wrapper for Ruby.
|
4
|
+
An idiomatic nanomsg wrapper for Ruby.
|
5
5
|
|
6
6
|
NANOMSG
|
7
7
|
|
@@ -25,6 +25,11 @@ stack. At the moment, nanomsg library supports following transports:
|
|
25
25
|
* IPC - transport between processes on a single machine
|
26
26
|
* TCP - network transport via TCP
|
27
27
|
|
28
|
+
DOCUMENTATION
|
29
|
+
|
30
|
+
Check out the examples folder of the project. See http://nanomsg.org/ for more
|
31
|
+
documentation.
|
32
|
+
|
28
33
|
SYNOPSIS
|
29
34
|
|
30
35
|
require 'nanomsg'
|
@@ -37,11 +42,10 @@ SYNOPSIS
|
|
37
42
|
|
38
43
|
STATUS
|
39
44
|
|
40
|
-
Very early alpha, not much testing has been done.
|
41
|
-
|
42
|
-
application.
|
45
|
+
Very early alpha, not much testing has been done. All socket types and devices
|
46
|
+
should work.
|
43
47
|
|
44
48
|
LICENSE
|
45
49
|
|
46
|
-
|
50
|
+
See file LICENSE, Copyright (c) 2013 Kaspar Schiess
|
47
51
|
|
data/examples/bus.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'nanomsg'
|
3
|
+
include NanoMsg
|
4
|
+
|
5
|
+
buses = 3.times.map { BusSocket.new }
|
6
|
+
|
7
|
+
a = 'tcp://127.0.0.1:5432'
|
8
|
+
b = 'tcp://127.0.0.1:5433'
|
9
|
+
|
10
|
+
one, two, three = *buses
|
11
|
+
|
12
|
+
one.bind a
|
13
|
+
|
14
|
+
two.bind b
|
15
|
+
two.connect a
|
16
|
+
|
17
|
+
three.connect a
|
18
|
+
three.connect b
|
19
|
+
|
20
|
+
sleep 0.1
|
21
|
+
|
22
|
+
one.send 'A'
|
23
|
+
p two.recv
|
24
|
+
p three.recv
|
25
|
+
|
26
|
+
two.send 'B'
|
27
|
+
p one.recv
|
28
|
+
p three.recv
|
29
|
+
|
30
|
+
three.send 'C'
|
31
|
+
p one.recv
|
32
|
+
p two.recv
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'nanomsg'
|
3
|
+
include NanoMsg
|
4
|
+
|
5
|
+
a = 'tcp://127.0.0.1:5432'
|
6
|
+
b = 'tcp://127.0.0.1:5433'
|
7
|
+
c = 'tcp://127.0.0.1:5434'
|
8
|
+
|
9
|
+
one, two, three = 3.times.map { BusSocket.new }
|
10
|
+
four, five, six = 3.times.map { BusSocket.new(AF_SP_RAW) }
|
11
|
+
|
12
|
+
one.bind a
|
13
|
+
two.bind b
|
14
|
+
three.bind c
|
15
|
+
|
16
|
+
# one -> four -> four -> two
|
17
|
+
four.connect a
|
18
|
+
four.connect b
|
19
|
+
Thread.start do
|
20
|
+
NanoMsg.run_loopback(four)
|
21
|
+
end.abort_on_exception = true
|
22
|
+
|
23
|
+
# one -> five -> six -> three
|
24
|
+
five.connect a
|
25
|
+
six.connect c
|
26
|
+
Thread.start do
|
27
|
+
NanoMsg.run_device(five, six)
|
28
|
+
end.abort_on_exception = true
|
29
|
+
|
30
|
+
sleep 0.2
|
31
|
+
one.send 'A'
|
32
|
+
|
33
|
+
# Gets sent to three, which forwards it to two.
|
34
|
+
puts two.recv
|
35
|
+
|
36
|
+
# Gets sent to five, which forwards it through six to three.
|
37
|
+
puts three.recv
|
38
|
+
|
39
|
+
NanoMsg.terminate
|
data/examples/pair.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
$:.unshift File.dirname(__FILE__) + "/../lib"
|
3
3
|
require 'nanomsg'
|
4
4
|
|
5
|
-
sock1 = NanoMsg::PairSocket.new
|
5
|
+
sock1 = NanoMsg::PairSocket.new
|
6
6
|
sock1.bind("ipc:///tmp/test.ipc")
|
7
7
|
|
8
|
-
sock2 = NanoMsg::PairSocket.new
|
8
|
+
sock2 = NanoMsg::PairSocket.new
|
9
9
|
sock2.connect("ipc:///tmp/test.ipc")
|
10
10
|
|
11
11
|
sock1.send 'test'
|
data/ext/Makefile
CHANGED
@@ -117,8 +117,8 @@ extout_prefix =
|
|
117
117
|
target_prefix =
|
118
118
|
LOCAL_LIBS =
|
119
119
|
LIBS = $(LIBRUBYARG_SHARED) -lnanomsg -lpthread -ldl -lobjc
|
120
|
-
SRCS = init.c
|
121
|
-
OBJS = init.o
|
120
|
+
SRCS = constants.c init.c
|
121
|
+
OBJS = constants.o init.o
|
122
122
|
TARGET = nanomsg
|
123
123
|
DLLIB = $(TARGET).bundle
|
124
124
|
EXTSTATIC =
|
data/ext/constants.c
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
#include "ruby/ruby.h"
|
3
|
+
#include "ruby/st.h"
|
4
|
+
|
5
|
+
#include <nanomsg/nn.h>
|
6
|
+
|
7
|
+
static st_table *syserr_tbl;
|
8
|
+
|
9
|
+
static VALUE
|
10
|
+
errno_initialize(VALUE self)
|
11
|
+
{
|
12
|
+
VALUE error;
|
13
|
+
VALUE klass = rb_obj_class(self);
|
14
|
+
|
15
|
+
const char *explanation;
|
16
|
+
VALUE message;
|
17
|
+
|
18
|
+
error = rb_const_get(klass, rb_intern("Errno"));
|
19
|
+
explanation = nn_strerror(FIX2INT(error));
|
20
|
+
|
21
|
+
message = rb_str_new(explanation, strlen(explanation));
|
22
|
+
rb_call_super(1, &message);
|
23
|
+
|
24
|
+
rb_iv_set(self, "errno", error);
|
25
|
+
|
26
|
+
return self;
|
27
|
+
}
|
28
|
+
|
29
|
+
static VALUE
|
30
|
+
errno_errno(VALUE self)
|
31
|
+
{
|
32
|
+
return rb_attr_get(self, rb_intern("errno"));
|
33
|
+
}
|
34
|
+
|
35
|
+
static VALUE
|
36
|
+
err_add(VALUE module, int n, const char *name)
|
37
|
+
{
|
38
|
+
st_data_t error;
|
39
|
+
|
40
|
+
if (!st_lookup(syserr_tbl, n, &error)) {
|
41
|
+
error = rb_define_class_under(module, name, rb_eStandardError);
|
42
|
+
|
43
|
+
rb_define_const(error, "Errno", INT2NUM(n));
|
44
|
+
rb_define_method(error, "initialize", errno_initialize, 0);
|
45
|
+
rb_define_method(error, "errno", errno_errno, 0);
|
46
|
+
|
47
|
+
st_add_direct(syserr_tbl, n, error);
|
48
|
+
}
|
49
|
+
|
50
|
+
return error;
|
51
|
+
}
|
52
|
+
|
53
|
+
VALUE
|
54
|
+
errno_lookup(int n)
|
55
|
+
{
|
56
|
+
st_data_t error;
|
57
|
+
|
58
|
+
if (!st_lookup(syserr_tbl, n, &error))
|
59
|
+
return Qnil;
|
60
|
+
|
61
|
+
return error;
|
62
|
+
}
|
63
|
+
|
64
|
+
void
|
65
|
+
Init_constants(VALUE module)
|
66
|
+
{
|
67
|
+
VALUE mErrno;
|
68
|
+
int i, value;
|
69
|
+
|
70
|
+
syserr_tbl = st_init_numtable();
|
71
|
+
|
72
|
+
mErrno = rb_define_module_under(module, "Errno");
|
73
|
+
|
74
|
+
// Define all constants that nanomsg knows about:
|
75
|
+
for (i = 0; ; ++i) {
|
76
|
+
const char* name = nn_symbol (i, &value);
|
77
|
+
if (name == NULL) break;
|
78
|
+
|
79
|
+
// I see no point in declaring values other than those starting with NN_:
|
80
|
+
if (strncmp(name, "NN_", 3) == 0)
|
81
|
+
rb_const_set(module, rb_intern(name), INT2NUM(value));
|
82
|
+
|
83
|
+
if (strncmp(name, "AF_", 3) == 0)
|
84
|
+
rb_const_set(module, rb_intern(name), INT2NUM(value));
|
85
|
+
|
86
|
+
if (strncmp(name, "E", 1) == 0)
|
87
|
+
err_add(mErrno, value, name);
|
88
|
+
}
|
89
|
+
}
|
data/ext/constants.h
ADDED
data/ext/constants.o
ADDED
Binary file
|
data/ext/init.c
CHANGED
@@ -2,11 +2,34 @@
|
|
2
2
|
#include "ruby/ruby.h"
|
3
3
|
|
4
4
|
#include <nanomsg/nn.h>
|
5
|
+
#include <nanomsg/reqrep.h>
|
5
6
|
#include <nanomsg/pair.h>
|
7
|
+
#include <nanomsg/pubsub.h>
|
8
|
+
#include <nanomsg/survey.h>
|
9
|
+
#include <nanomsg/pipeline.h>
|
10
|
+
#include <nanomsg/bus.h>
|
6
11
|
|
7
|
-
|
12
|
+
#include "constants.h"
|
13
|
+
|
14
|
+
static VALUE mNanoMsg;
|
8
15
|
static VALUE cSocket;
|
16
|
+
|
9
17
|
static VALUE cPairSocket;
|
18
|
+
|
19
|
+
static VALUE cReqSocket;
|
20
|
+
static VALUE cRepSocket;
|
21
|
+
|
22
|
+
static VALUE cPubSocket;
|
23
|
+
static VALUE cSubSocket;
|
24
|
+
|
25
|
+
static VALUE cSurveySocket;
|
26
|
+
static VALUE cRespondSocket;
|
27
|
+
|
28
|
+
static VALUE cPushSocket;
|
29
|
+
static VALUE cPullSocket;
|
30
|
+
|
31
|
+
static VALUE cBusSocket;
|
32
|
+
|
10
33
|
static VALUE ceSocketError;
|
11
34
|
|
12
35
|
struct nmsg_socket {
|
@@ -65,46 +88,18 @@ sock_alloc(VALUE klass)
|
|
65
88
|
}
|
66
89
|
|
67
90
|
static void
|
68
|
-
sock_raise_error(int
|
91
|
+
sock_raise_error(int nn_errno)
|
69
92
|
{
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
}
|
93
|
+
VALUE error = errno_lookup(nn_errno);
|
94
|
+
|
95
|
+
if (error != Qnil) {
|
96
|
+
VALUE exc = rb_class_new_instance(0, NULL, error);
|
97
|
+
rb_exc_raise(exc);
|
98
|
+
}
|
99
|
+
|
100
|
+
rb_raise(ceSocketError, "General failure, no such error code %d found.", nn_errno);
|
107
101
|
}
|
102
|
+
#define RAISE_SOCK_ERROR { sock_raise_error(nn_errno()); }
|
108
103
|
|
109
104
|
static VALUE
|
110
105
|
sock_bind(VALUE socket, VALUE bind)
|
@@ -114,7 +109,7 @@ sock_bind(VALUE socket, VALUE bind)
|
|
114
109
|
|
115
110
|
endpoint = nn_bind(sock, StringValueCStr(bind));
|
116
111
|
if (endpoint < 0)
|
117
|
-
|
112
|
+
RAISE_SOCK_ERROR;
|
118
113
|
|
119
114
|
// TODO do something with the endpoint, returning it in a class for example.
|
120
115
|
return Qnil;
|
@@ -128,14 +123,25 @@ sock_connect(VALUE socket, VALUE connect)
|
|
128
123
|
|
129
124
|
endpoint = nn_connect(sock, StringValueCStr(connect));
|
130
125
|
if (endpoint < 0)
|
131
|
-
|
126
|
+
RAISE_SOCK_ERROR;
|
132
127
|
|
133
128
|
// TODO do something with the endpoint, returning it in a class for example.
|
134
129
|
return Qnil;
|
135
130
|
}
|
136
131
|
|
132
|
+
static void
|
133
|
+
sock_init(VALUE socket, int domain, int protocol)
|
134
|
+
{
|
135
|
+
struct nmsg_socket *psock = sock_get_ptr(socket);
|
136
|
+
|
137
|
+
psock->socket = nn_socket(domain, protocol);
|
138
|
+
if (psock->socket < 0)
|
139
|
+
RAISE_SOCK_ERROR;
|
140
|
+
}
|
141
|
+
|
137
142
|
struct ioop {
|
138
|
-
int
|
143
|
+
int nn_errno;
|
144
|
+
int return_code;
|
139
145
|
int sock;
|
140
146
|
char* buffer;
|
141
147
|
long len;
|
@@ -147,11 +153,18 @@ sock_send_no_gvl(void* data)
|
|
147
153
|
{
|
148
154
|
struct ioop *pio = data;
|
149
155
|
|
150
|
-
|
151
|
-
|
156
|
+
// TODO This is buggy. I cannot make the difference between
|
157
|
+
// 'socket gone away' (=EAGAIN) and 'socket busy' (=EAGAIN). So I err on the
|
158
|
+
// side of 'socket busy' and do not raise the error. As a consequence, we'll
|
159
|
+
// get stuck in an endless loop when the socket is just not answering.
|
160
|
+
|
161
|
+
while (pio->nn_errno == EAGAIN && !pio->abort) {
|
162
|
+
pio->return_code = nn_send(pio->sock, pio->buffer, pio->len, NN_DONTWAIT /* flags */);
|
152
163
|
|
153
|
-
if (pio->
|
154
|
-
pio->
|
164
|
+
if (pio->return_code < 0)
|
165
|
+
pio->nn_errno = nn_errno();
|
166
|
+
else
|
167
|
+
break;
|
155
168
|
}
|
156
169
|
|
157
170
|
return Qnil;
|
@@ -170,7 +183,7 @@ sock_send(VALUE socket, VALUE buffer)
|
|
170
183
|
struct ioop io;
|
171
184
|
|
172
185
|
io.sock = sock_get(socket);
|
173
|
-
io.
|
186
|
+
io.nn_errno = EAGAIN;
|
174
187
|
io.buffer = StringValuePtr(buffer);
|
175
188
|
io.len = RSTRING_LEN(buffer);
|
176
189
|
io.abort = Qfalse;
|
@@ -182,10 +195,10 @@ sock_send(VALUE socket, VALUE buffer)
|
|
182
195
|
if (io.abort)
|
183
196
|
return Qnil;
|
184
197
|
|
185
|
-
if (io.
|
186
|
-
sock_raise_error(io.
|
198
|
+
if (io.return_code < 0)
|
199
|
+
sock_raise_error(io.nn_errno);
|
187
200
|
|
188
|
-
return INT2NUM(io.
|
201
|
+
return INT2NUM(io.return_code);
|
189
202
|
}
|
190
203
|
|
191
204
|
static VALUE
|
@@ -193,11 +206,18 @@ sock_recv_no_gvl(void* data)
|
|
193
206
|
{
|
194
207
|
struct ioop *pio = data;
|
195
208
|
|
196
|
-
|
197
|
-
|
209
|
+
// TODO This is buggy. I cannot make the difference between
|
210
|
+
// 'socket gone away' (=EAGAIN) and 'socket busy' (=EAGAIN). So I err on the
|
211
|
+
// side of 'socket busy' and do not raise the error. As a consequence, we'll
|
212
|
+
// get stuck in an endless loop when the socket is just not answering.
|
213
|
+
|
214
|
+
while (pio->nn_errno == EAGAIN && !pio->abort) {
|
215
|
+
pio->return_code = nn_recv(pio->sock, &pio->buffer, NN_MSG, NN_DONTWAIT /* flags */);
|
198
216
|
|
199
|
-
if (pio->
|
200
|
-
pio->
|
217
|
+
if (pio->return_code < 0)
|
218
|
+
pio->nn_errno = nn_errno();
|
219
|
+
else
|
220
|
+
break;
|
201
221
|
}
|
202
222
|
|
203
223
|
return Qnil;
|
@@ -220,52 +240,231 @@ sock_recv(VALUE socket)
|
|
220
240
|
io.sock = sock_get(socket);
|
221
241
|
io.buffer = (char*) 0;
|
222
242
|
io.abort = Qfalse;
|
223
|
-
io.
|
243
|
+
io.nn_errno = EAGAIN;
|
224
244
|
|
225
245
|
rb_thread_blocking_region(sock_recv_no_gvl, &io, sock_recv_abort, &io);
|
226
246
|
|
227
247
|
if (io.abort)
|
228
248
|
return Qnil;
|
229
249
|
|
230
|
-
if (io.
|
231
|
-
sock_raise_error(io.
|
250
|
+
if (io.return_code < 0)
|
251
|
+
sock_raise_error(io.nn_errno);
|
232
252
|
|
233
|
-
result = rb_str_new(io.buffer, io.
|
253
|
+
result = rb_str_new(io.buffer, io.return_code);
|
234
254
|
nn_freemsg(io.buffer); io.buffer = (char*) 0;
|
235
255
|
|
236
256
|
return result;
|
237
257
|
}
|
238
258
|
|
239
|
-
static VALUE
|
240
|
-
|
259
|
+
static VALUE
|
260
|
+
sock_close_no_gvl(void* data)
|
241
261
|
{
|
242
|
-
struct
|
262
|
+
struct ioop *pio = (struct ioop*) data;
|
243
263
|
|
244
|
-
|
245
|
-
if (
|
246
|
-
|
247
|
-
}
|
264
|
+
pio->return_code = nn_close(pio->sock);
|
265
|
+
if (pio->return_code < 0)
|
266
|
+
pio->nn_errno = nn_errno();
|
248
267
|
|
249
|
-
return
|
268
|
+
return Qnil;
|
269
|
+
}
|
270
|
+
|
271
|
+
static VALUE
|
272
|
+
sock_close(VALUE socket)
|
273
|
+
{
|
274
|
+
struct ioop io;
|
275
|
+
|
276
|
+
io.sock = sock_get(socket);
|
277
|
+
|
278
|
+
// I've no idea on how to abort a close (which may block for NN_LINGER
|
279
|
+
// seconds), so we'll be uninterruptible.
|
280
|
+
rb_thread_blocking_region(sock_close_no_gvl, &io, NULL, NULL);
|
281
|
+
|
282
|
+
if (io.return_code < 0)
|
283
|
+
sock_raise_error(io.nn_errno);
|
284
|
+
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
|
288
|
+
#define SOCK_INIT_FUNC(name, type) \
|
289
|
+
static VALUE \
|
290
|
+
name(int argc, VALUE *argv, VALUE self) \
|
291
|
+
{ \
|
292
|
+
VALUE domain; \
|
293
|
+
\
|
294
|
+
rb_scan_args(argc, argv, "01", &domain); \
|
295
|
+
if (NIL_P(domain)) \
|
296
|
+
sock_init(self, AF_SP, (type)); \
|
297
|
+
else \
|
298
|
+
sock_init(self, FIX2INT(domain), (type)); \
|
299
|
+
\
|
300
|
+
return self; \
|
301
|
+
}
|
302
|
+
|
303
|
+
SOCK_INIT_FUNC(pair_sock_init, NN_PAIR);
|
304
|
+
SOCK_INIT_FUNC(req_sock_init, NN_REQ);
|
305
|
+
SOCK_INIT_FUNC(rep_sock_init, NN_REP);
|
306
|
+
SOCK_INIT_FUNC(pub_sock_init, NN_PUB);
|
307
|
+
SOCK_INIT_FUNC(sub_sock_init, NN_SUB);
|
308
|
+
SOCK_INIT_FUNC(srvy_sock_init, NN_SURVEYOR);
|
309
|
+
SOCK_INIT_FUNC(resp_sock_init, NN_RESPONDENT);
|
310
|
+
SOCK_INIT_FUNC(push_sock_init, NN_PUSH);
|
311
|
+
SOCK_INIT_FUNC(pull_sock_init, NN_PULL);
|
312
|
+
SOCK_INIT_FUNC(bus_sock_init, NN_BUS);
|
313
|
+
|
314
|
+
static VALUE
|
315
|
+
sub_sock_subscribe(VALUE socket, VALUE channel)
|
316
|
+
{
|
317
|
+
int sock = sock_get(socket);
|
318
|
+
int err;
|
319
|
+
|
320
|
+
err = nn_setsockopt(
|
321
|
+
sock, NN_SUB, NN_SUB_SUBSCRIBE,
|
322
|
+
StringValuePtr(channel),
|
323
|
+
RSTRING_LEN(channel)
|
324
|
+
);
|
325
|
+
if (err < 0)
|
326
|
+
RAISE_SOCK_ERROR;
|
327
|
+
|
328
|
+
return socket;
|
329
|
+
}
|
330
|
+
|
331
|
+
static VALUE
|
332
|
+
srvy_set_deadline(VALUE self, VALUE deadline)
|
333
|
+
{
|
334
|
+
int sock = sock_get(self);
|
335
|
+
VALUE miliseconds = rb_funcall(deadline, rb_intern("*"), 1, INT2NUM(1000));
|
336
|
+
int timeout = FIX2INT(miliseconds);
|
337
|
+
int err;
|
338
|
+
|
339
|
+
err = nn_setsockopt(sock, NN_SURVEYOR, NN_SURVEYOR_DEADLINE, &timeout, sizeof(int));
|
340
|
+
if (err < 0)
|
341
|
+
RAISE_SOCK_ERROR;
|
342
|
+
|
343
|
+
return deadline;
|
344
|
+
}
|
345
|
+
|
346
|
+
static VALUE
|
347
|
+
srvy_get_deadline(VALUE self)
|
348
|
+
{
|
349
|
+
int sock = sock_get(self);
|
350
|
+
int deadline;
|
351
|
+
size_t size = sizeof(int);
|
352
|
+
|
353
|
+
int err;
|
354
|
+
|
355
|
+
err = nn_getsockopt(sock, NN_SURVEYOR, NN_SURVEYOR_DEADLINE, &deadline, &size);
|
356
|
+
if (err < 0)
|
357
|
+
RAISE_SOCK_ERROR;
|
358
|
+
|
359
|
+
return rb_funcall(INT2NUM(deadline), rb_intern("/"), 1, rb_float_new(1000));
|
360
|
+
}
|
361
|
+
|
362
|
+
static VALUE
|
363
|
+
nanomsg_terminate(VALUE self)
|
364
|
+
{
|
365
|
+
nn_term();
|
366
|
+
|
367
|
+
return Qnil;
|
368
|
+
}
|
369
|
+
|
370
|
+
struct device_op {
|
371
|
+
int sa, sb;
|
372
|
+
int err;
|
373
|
+
};
|
374
|
+
|
375
|
+
static VALUE
|
376
|
+
nanomsg_run_device_no_gvl(void* data)
|
377
|
+
{
|
378
|
+
struct device_op *pop = (struct device_op*) data;
|
379
|
+
|
380
|
+
pop->err = nn_device(pop->sa, pop->sb);
|
381
|
+
|
382
|
+
return Qnil;
|
383
|
+
}
|
384
|
+
|
385
|
+
static VALUE
|
386
|
+
nanomsg_run_device(VALUE self, VALUE a, VALUE b)
|
387
|
+
{
|
388
|
+
struct device_op dop;
|
389
|
+
|
390
|
+
dop.sa = sock_get(a);
|
391
|
+
dop.sb = sock_get(b);
|
392
|
+
|
393
|
+
rb_thread_blocking_region(nanomsg_run_device_no_gvl, &dop, NULL, NULL);
|
394
|
+
if (dop.err < 0)
|
395
|
+
RAISE_SOCK_ERROR;
|
396
|
+
|
397
|
+
return Qnil;
|
398
|
+
}
|
399
|
+
|
400
|
+
static VALUE
|
401
|
+
nanomsg_run_loopback(VALUE self, VALUE a)
|
402
|
+
{
|
403
|
+
struct device_op dop;
|
404
|
+
|
405
|
+
dop.sa = sock_get(a);
|
406
|
+
dop.sb = -1; // invalid socket, see documentation
|
407
|
+
|
408
|
+
rb_thread_blocking_region(nanomsg_run_device_no_gvl, &dop, NULL, NULL);
|
409
|
+
if (dop.err < 0)
|
410
|
+
RAISE_SOCK_ERROR;
|
411
|
+
|
412
|
+
return Qnil;
|
250
413
|
}
|
251
414
|
|
252
415
|
void
|
253
416
|
Init_nanomsg(void)
|
254
417
|
{
|
255
|
-
|
418
|
+
mNanoMsg = rb_define_module("NanoMsg");
|
419
|
+
cSocket = rb_define_class_under(mNanoMsg, "Socket", rb_cObject);
|
420
|
+
cPairSocket = rb_define_class_under(mNanoMsg, "PairSocket", cSocket);
|
421
|
+
|
422
|
+
cReqSocket = rb_define_class_under(mNanoMsg, "ReqSocket", cSocket);
|
423
|
+
cRepSocket = rb_define_class_under(mNanoMsg, "RepSocket", cSocket);
|
424
|
+
|
425
|
+
cPubSocket = rb_define_class_under(mNanoMsg, "PubSocket", cSocket);
|
426
|
+
cSubSocket = rb_define_class_under(mNanoMsg, "SubSocket", cSocket);
|
427
|
+
|
428
|
+
cSurveySocket = rb_define_class_under(mNanoMsg, "SurveySocket", cSocket);
|
429
|
+
cRespondSocket = rb_define_class_under(mNanoMsg, "RespondSocket", cSocket);
|
430
|
+
|
431
|
+
cPushSocket = rb_define_class_under(mNanoMsg, "PushSocket", cSocket);
|
432
|
+
cPullSocket = rb_define_class_under(mNanoMsg, "PullSocket", cSocket);
|
433
|
+
|
434
|
+
cBusSocket = rb_define_class_under(mNanoMsg, "BusSocket", cSocket);
|
256
435
|
|
257
|
-
|
258
|
-
cSocket = rb_define_class_under(cNanoMsg, "Socket", rb_cObject);
|
259
|
-
cPairSocket = rb_define_class_under(cNanoMsg, "PairSocket", cSocket);
|
436
|
+
ceSocketError = rb_define_class_under(mNanoMsg, "SocketError", rb_eIOError);
|
260
437
|
|
261
|
-
|
438
|
+
rb_define_singleton_method(mNanoMsg, "terminate", nanomsg_terminate, 0);
|
439
|
+
rb_define_singleton_method(mNanoMsg, "run_device", nanomsg_run_device, 2);
|
440
|
+
rb_define_singleton_method(mNanoMsg, "run_loopback", nanomsg_run_loopback, 1);
|
262
441
|
|
442
|
+
rb_define_alloc_func(cSocket, sock_alloc);
|
263
443
|
rb_define_method(cSocket, "bind", sock_bind, 1);
|
264
444
|
rb_define_method(cSocket, "connect", sock_connect, 1);
|
265
445
|
rb_define_method(cSocket, "send", sock_send, 1);
|
266
446
|
rb_define_method(cSocket, "recv", sock_recv, 0);
|
447
|
+
rb_define_method(cSocket, "close", sock_close, 0);
|
448
|
+
|
449
|
+
rb_define_method(cPairSocket, "initialize", pair_sock_init, -1);
|
450
|
+
|
451
|
+
rb_define_method(cReqSocket, "initialize", req_sock_init, -1);
|
452
|
+
rb_define_method(cRepSocket, "initialize", rep_sock_init, -1);
|
453
|
+
|
454
|
+
rb_define_method(cPubSocket, "initialize", pub_sock_init, -1);
|
455
|
+
rb_define_method(cSubSocket, "initialize", sub_sock_init, -1);
|
456
|
+
rb_define_method(cSubSocket, "subscribe", sub_sock_subscribe, 1);
|
457
|
+
|
458
|
+
rb_define_method(cSurveySocket, "initialize", srvy_sock_init, -1);
|
459
|
+
rb_define_method(cSurveySocket, "deadline=", srvy_set_deadline, 1);
|
460
|
+
rb_define_method(cSurveySocket, "deadline", srvy_get_deadline, 0);
|
461
|
+
rb_define_method(cRespondSocket, "initialize", resp_sock_init, -1);
|
462
|
+
|
463
|
+
rb_define_method(cPushSocket, "initialize", push_sock_init, -1);
|
464
|
+
rb_define_method(cPullSocket, "initialize", pull_sock_init, -1);
|
465
|
+
|
466
|
+
rb_define_method(cBusSocket, "initialize", bus_sock_init, -1);
|
267
467
|
|
268
|
-
|
269
|
-
rb_define_method(cPairSocket, "initialize", pair_sock_init, 0);
|
468
|
+
Init_constants(mNanoMsg);
|
270
469
|
}
|
271
470
|
|
data/ext/init.o
CHANGED
Binary file
|
data/ext/nanomsg.bundle
CHANGED
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'BUS sockets' do
|
4
|
+
def self.examples_for_transport tbind
|
5
|
+
name = tbind.split('://').first
|
6
|
+
|
7
|
+
describe "transport #{name}" do
|
8
|
+
describe "using a broker topology" do
|
9
|
+
let!(:a) { NanoMsg::BusSocket.new }
|
10
|
+
let!(:b) { NanoMsg::BusSocket.new }
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
[a, b].each(&:close)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'forwards messages to everyone (except the producer)' do
|
17
|
+
a.bind(tbind)
|
18
|
+
b.connect(tbind)
|
19
|
+
sleep 0.01
|
20
|
+
|
21
|
+
a.send 'test'
|
22
|
+
b.recv.should == 'test'
|
23
|
+
|
24
|
+
b.send 'ing'
|
25
|
+
a.recv.should == 'ing'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
examples_for_transport "ipc:///tmp/bus1.ipc"
|
32
|
+
examples_for_transport "tcp://127.0.0.1:5558"
|
33
|
+
examples_for_transport "inproc://bus1"
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
describe 'Devices' do
|
6
|
+
describe "connecting two BUSes" do
|
7
|
+
let(:a) { NanoMsg::BusSocket.new(NanoMsg::AF_SP_RAW) }
|
8
|
+
let(:b) { NanoMsg::BusSocket.new(NanoMsg::AF_SP_RAW) }
|
9
|
+
let(:c) { NanoMsg::BusSocket.new }
|
10
|
+
let(:d) { NanoMsg::BusSocket.new }
|
11
|
+
|
12
|
+
let(:adr1) { 'inproc://a' }
|
13
|
+
let(:adr2) { 'inproc://b' }
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
a.bind(adr1)
|
17
|
+
b.bind(adr2)
|
18
|
+
|
19
|
+
c.connect adr1
|
20
|
+
d.connect adr2
|
21
|
+
end
|
22
|
+
|
23
|
+
let!(:thread) {
|
24
|
+
Thread.start do
|
25
|
+
begin
|
26
|
+
NanoMsg.run_device(a, b)
|
27
|
+
rescue NanoMsg::Errno::ETERM
|
28
|
+
# Ignore, spec shutdown
|
29
|
+
end
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
it "forwards messages" do
|
34
|
+
sleep 0.01
|
35
|
+
c.send 'test'
|
36
|
+
timeout(1) do
|
37
|
+
d.recv.should == 'test'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
describe 'PUB/SUB sockets' do
|
6
|
+
describe 'PUB socket' do
|
7
|
+
it 'has no #recv method'
|
8
|
+
end
|
9
|
+
describe 'SUB socket' do
|
10
|
+
it 'has no #send method'
|
11
|
+
it 'allows subscribing to channels'
|
12
|
+
it 'allows unsubscribing to channels'
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.examples_for_transport tbind
|
16
|
+
name = tbind.split('://').first
|
17
|
+
|
18
|
+
describe "transport #{name}" do
|
19
|
+
let(:pub) { NanoMsg::PubSocket.new }
|
20
|
+
let(:sub1) { NanoMsg::SubSocket.new }
|
21
|
+
let(:sub2) { NanoMsg::SubSocket.new }
|
22
|
+
|
23
|
+
after(:each) {
|
24
|
+
pub.close
|
25
|
+
sub1.close
|
26
|
+
sub2.close
|
27
|
+
}
|
28
|
+
|
29
|
+
around(:each) { |example|
|
30
|
+
timeout(1) { example.run }}
|
31
|
+
|
32
|
+
it 'allows simple pub/sub' do
|
33
|
+
pub.bind(tbind)
|
34
|
+
sub1.connect(tbind)
|
35
|
+
sub2.connect(tbind)
|
36
|
+
|
37
|
+
sub1.subscribe 'foo'
|
38
|
+
sub2.subscribe 'foo'
|
39
|
+
|
40
|
+
sub1.subscribe 'bar'
|
41
|
+
sleep 0.1
|
42
|
+
|
43
|
+
pub.send 'foo1234'
|
44
|
+
sub1.recv.should == 'foo1234'
|
45
|
+
sub2.recv.should == 'foo1234'
|
46
|
+
|
47
|
+
pub.send 'bar4567'
|
48
|
+
pub.send 'foo9999'
|
49
|
+
sub1.recv.should == 'bar4567'
|
50
|
+
sub2.recv.should == 'foo9999'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
examples_for_transport "ipc:///tmp/pubsub.ipc"
|
56
|
+
examples_for_transport "tcp://127.0.0.1:5557"
|
57
|
+
examples_for_transport "inproc://pubsub"
|
58
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'PUSH/PULL pipeline sockets' do
|
4
|
+
def self.examples_for_transport tbind
|
5
|
+
name = tbind.split('://').first
|
6
|
+
|
7
|
+
describe "transport #{name}" do
|
8
|
+
describe 'fanout' do
|
9
|
+
let(:producer) { NanoMsg::PushSocket.new }
|
10
|
+
let(:consumer1) { NanoMsg::PullSocket.new }
|
11
|
+
let(:consumer2) { NanoMsg::PullSocket.new }
|
12
|
+
|
13
|
+
after(:each) do
|
14
|
+
[producer, consumer2, consumer1].each(&:close)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'distributes load evenly' do
|
18
|
+
producer.bind(tbind)
|
19
|
+
consumer1.connect(tbind)
|
20
|
+
consumer2.connect(tbind)
|
21
|
+
sleep 0.1
|
22
|
+
|
23
|
+
100.times do |i|
|
24
|
+
producer.send i.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
n = [0, 0]
|
28
|
+
50.times do
|
29
|
+
[consumer1, consumer2].each_with_index do |consumer, idx|
|
30
|
+
v = consumer.recv.to_i
|
31
|
+
n[idx] += 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This is about a 5% level of the binominal distribution
|
36
|
+
(n.first - n.last).abs.should < 10
|
37
|
+
end
|
38
|
+
end
|
39
|
+
describe 'fanin' do
|
40
|
+
let(:producer1) { NanoMsg::PushSocket.new }
|
41
|
+
let(:producer2) { NanoMsg::PushSocket.new }
|
42
|
+
let(:consumer) { NanoMsg::PullSocket.new }
|
43
|
+
|
44
|
+
after(:each) do
|
45
|
+
[producer1, producer2, consumer].each(&:close)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'consumes results fairly' do
|
49
|
+
consumer.bind(tbind)
|
50
|
+
producer1.connect(tbind)
|
51
|
+
producer2.connect(tbind)
|
52
|
+
|
53
|
+
100.times do |i|
|
54
|
+
producer = [producer1, producer2][i%2]
|
55
|
+
|
56
|
+
producer.send i.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
100.times do |i|
|
60
|
+
consumer.recv.to_i.should == i
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
examples_for_transport "ipc:///tmp/reqrep.ipc"
|
68
|
+
examples_for_transport "tcp://127.0.0.1:5555"
|
69
|
+
examples_for_transport "inproc://reqrep"
|
70
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'REQ/REP sockets' do
|
4
|
+
let(:req) { NanoMsg::ReqSocket.new }
|
5
|
+
let(:rep) { NanoMsg::RepSocket.new }
|
6
|
+
|
7
|
+
after(:each) do
|
8
|
+
req.close
|
9
|
+
rep.close
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.examples_for_transport tbind
|
13
|
+
name = tbind.split('://').first
|
14
|
+
|
15
|
+
describe "transport #{name}" do
|
16
|
+
it 'allows simple req/rep' do
|
17
|
+
req.bind(tbind)
|
18
|
+
rep.connect(tbind)
|
19
|
+
|
20
|
+
req.send 'req1'
|
21
|
+
|
22
|
+
rep.recv.should == 'req1'
|
23
|
+
rep.send 'rep1'
|
24
|
+
|
25
|
+
req.recv.should == 'rep1'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
examples_for_transport "ipc:///tmp/reqrep.ipc"
|
31
|
+
examples_for_transport "tcp://127.0.0.1:5555"
|
32
|
+
examples_for_transport "inproc://reqrep"
|
33
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'SURVEY sockets' do
|
4
|
+
let(:surveyor) { NanoMsg::SurveySocket.new }
|
5
|
+
let(:resp1) { NanoMsg::RespondSocket.new }
|
6
|
+
let(:resp2) { NanoMsg::RespondSocket.new }
|
7
|
+
|
8
|
+
after(:each) do
|
9
|
+
[surveyor, resp2, resp1].each(&:close)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.examples_for_transport tbind
|
13
|
+
name = tbind.split('://').first
|
14
|
+
|
15
|
+
describe "transport #{name}" do
|
16
|
+
it 'allows simple surveys' do
|
17
|
+
surveyor.deadline.should == 1 # default: 1 second
|
18
|
+
surveyor.deadline = 0.1 # 100ms
|
19
|
+
surveyor.deadline.should == 0.1
|
20
|
+
|
21
|
+
surveyor.bind(tbind)
|
22
|
+
|
23
|
+
resp1.connect(tbind)
|
24
|
+
resp2.connect(tbind)
|
25
|
+
|
26
|
+
sleep 0.1
|
27
|
+
surveyor.send 'u there?'
|
28
|
+
resp1.recv.should == 'u there?'
|
29
|
+
resp2.recv.should == 'u there?'
|
30
|
+
|
31
|
+
resp1.send 'KTHNXBYE'
|
32
|
+
surveyor.recv.should == 'KTHNXBYE'
|
33
|
+
|
34
|
+
# nanomsg/tests/survey.c says this should be EFSM, the documentation
|
35
|
+
# says it should be ETIMEDOUT. Reality wins.
|
36
|
+
begin
|
37
|
+
surveyor.recv
|
38
|
+
rescue NanoMsg::Errno::EFSM
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
examples_for_transport "ipc:///tmp/reqrep.ipc"
|
45
|
+
examples_for_transport "tcp://127.0.0.1:5555"
|
46
|
+
examples_for_transport "inproc://reqrep"
|
47
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nanomsg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,19 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-26 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: ! " nanomsg
|
15
|
-
(nanomsg.org)\n\n nanomsg library is a high-performance implementation of several
|
14
|
+
description: ! " nanomsg library is a high-performance implementation of several
|
16
15
|
\"scalability \n protocols\". Scalability protocol's job is to define how multiple
|
17
|
-
applications \n communicate to form a single distributed application.
|
18
|
-
|
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"
|
16
|
+
applications \n communicate to form a single distributed application. WARNING:
|
17
|
+
nanomsg is still in alpha stage!\n"
|
25
18
|
email: kaspar.schiess@absurd.li
|
26
19
|
executables: []
|
27
20
|
extensions:
|
@@ -34,16 +27,26 @@ files:
|
|
34
27
|
- README
|
35
28
|
- lib/nanomsg/pair_socket.rb
|
36
29
|
- lib/nanomsg.rb
|
30
|
+
- ext/constants.c
|
31
|
+
- ext/constants.h
|
32
|
+
- ext/constants.o
|
37
33
|
- ext/extconf.rb
|
38
34
|
- ext/init.c
|
39
35
|
- ext/init.o
|
40
36
|
- ext/Makefile
|
41
|
-
- ext/mkmf.log
|
42
37
|
- ext/nanomsg.bundle
|
43
|
-
-
|
38
|
+
- examples/bus.rb
|
39
|
+
- examples/bus_device.rb
|
44
40
|
- examples/pair.rb
|
45
41
|
- examples/roundtrip_latency.rb
|
42
|
+
- spec/lib/nanomsg/bus_spec.rb
|
43
|
+
- spec/lib/nanomsg/device_spec.rb
|
46
44
|
- spec/lib/nanomsg/pair_socket_spec.rb
|
45
|
+
- spec/lib/nanomsg/pub_sub_spec.rb
|
46
|
+
- spec/lib/nanomsg/push_pull_spec.rb
|
47
|
+
- spec/lib/nanomsg/req_rep_spec.rb
|
48
|
+
- spec/lib/nanomsg/survey_spec.rb
|
49
|
+
- spec/lib/nanomsg_spec.rb
|
47
50
|
- spec/spec_helper.rb
|
48
51
|
homepage: https://bitbucket.org/kschiess/nanomsg
|
49
52
|
licenses: []
|
data/ext/mkmf.log
DELETED
@@ -1,22 +0,0 @@
|
|
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
|
-
|
data/ext/nanomsg.o
DELETED
Binary file
|