zeromq 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,156 @@
1
+ //-----------------------------------------------------------------------------
2
+
3
+
4
+ #include "context.h"
5
+ #include "socket.h"
6
+
7
+ //-----------------------------------------------------------------------------
8
+
9
+ static VALUE context_allocate( VALUE klass );
10
+ static void context_free( void* instance );
11
+
12
+ static VALUE context_initialize( int argc_, VALUE* argv_, VALUE self );
13
+ static VALUE context_close( VALUE self );
14
+
15
+ //-----------------------------------------------------------------------------
16
+
17
+ struct zeromq_context* zeromq_context_create()
18
+ //--------------------------------------------
19
+ {
20
+ struct zeromq_context* context = NULL;
21
+
22
+ context = ALLOC( struct zeromq_context );
23
+ context->context = NULL;
24
+ context->reference_count = 1;
25
+
26
+ return context;
27
+ }
28
+
29
+ void zeromq_context_destroy( struct zeromq_context* context )
30
+ //-----------------------------------------------------------
31
+ {
32
+ assert( context );
33
+
34
+ if ( context->context != NULL )
35
+ {
36
+ int rc = zmq_ctx_destroy( context->context );
37
+ assert( rc == 0 );
38
+ }
39
+
40
+ xfree( context );
41
+ }
42
+
43
+ void zeromq_context_retain( struct zeromq_context* context )
44
+ //----------------------------------------------------------
45
+ {
46
+ assert( context );
47
+ assert( context->context );
48
+ assert( context->reference_count != 0 );
49
+
50
+ context->reference_count++;
51
+ }
52
+
53
+ void zeromq_context_release( struct zeromq_context* context )
54
+ //-----------------------------------------------------------
55
+ {
56
+ assert( context );
57
+ assert( context->context );
58
+ assert( context->reference_count != 0 );
59
+
60
+ context->reference_count--;
61
+
62
+ if ( context->reference_count == 0 )
63
+ {
64
+ zeromq_context_destroy( context );
65
+ }
66
+ }
67
+
68
+ //-----------------------------------------------------------------------------
69
+
70
+ VALUE context_declare( VALUE zeromq_module )
71
+ //------------------------------------------
72
+ {
73
+ VALUE klass = rb_define_class_under(
74
+ zeromq_module,
75
+ "Context",
76
+ rb_cObject
77
+ );
78
+
79
+ rb_define_singleton_method(
80
+ klass,
81
+ "default",
82
+ context_default,
83
+ 0
84
+ );
85
+
86
+ rb_define_alloc_func( klass, context_allocate );
87
+ rb_define_method( klass, "initialize", context_initialize, -1 );
88
+ rb_define_method( klass, "close", context_close, 0 );
89
+
90
+ return klass;
91
+ }
92
+
93
+ VALUE context_default( VALUE self )
94
+ //---------------------------------
95
+ {
96
+ static VALUE default_context = Qnil;
97
+
98
+ if ( default_context == Qnil )
99
+ {
100
+ default_context = rb_class_new_instance( 0, NULL, self );
101
+ }
102
+
103
+ return default_context;
104
+ }
105
+
106
+ static VALUE context_allocate( VALUE class )
107
+ //------------------------------------------
108
+ {
109
+ return rb_data_object_alloc(
110
+ class,
111
+ zeromq_context_create(),
112
+ 0,
113
+ context_free
114
+ );
115
+ }
116
+
117
+ static void context_free( void* instance )
118
+ //----------------------------------------
119
+ {
120
+ zeromq_context_destroy( ( struct zeromq_context* )instance );
121
+ }
122
+
123
+ static VALUE context_initialize( int arg_count, VALUE* args, VALUE self )
124
+ //------------------------------------------------------------------------
125
+ {
126
+ VALUE context_options = Qnil;
127
+ rb_scan_args( arg_count, args, "01", &context_options );
128
+
129
+ struct zeromq_context* context = NULL;
130
+ Data_Get_Struct( self, void, context );
131
+
132
+ assert( context->context == NULL );
133
+
134
+ context->context = zmq_ctx_new();
135
+ if ( !context->context )
136
+ {
137
+ rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
138
+ return Qnil;
139
+ }
140
+
141
+ return self;
142
+ }
143
+
144
+ static VALUE context_close( VALUE self )
145
+ //--------------------------------------
146
+ {
147
+ struct zeromq_context* context = NULL;
148
+ Data_Get_Struct( self, void, context );
149
+
150
+ if ( context->context != NULL )
151
+ {
152
+ zeromq_context_destroy( context );
153
+ }
154
+
155
+ return Qnil;
156
+ }
@@ -0,0 +1,24 @@
1
+ #include "extension.h"
2
+
3
+ //-----------------------------------------------------------------------------
4
+
5
+ struct zeromq_context
6
+ {
7
+ void* context;
8
+ unsigned reference_count;
9
+ };
10
+
11
+ //-----------------------------------------------------------------------------
12
+
13
+ struct zeromq_context* zeromq_context_default();
14
+
15
+ struct zeromq_context* zeromq_context_create();
16
+ void zeromq_context_destroy( struct zeromq_context* context );
17
+
18
+ void zeromq_context_retain( struct zeromq_context* context );
19
+ void zeromq_context_release( struct zeromq_context* context );
20
+
21
+ //-----------------------------------------------------------------------------
22
+
23
+ VALUE context_declare( VALUE zeromq_module );
24
+ VALUE context_default( VALUE self );
data/extension/error.c ADDED
@@ -0,0 +1,14 @@
1
+ //-----------------------------------------------------------------------------
2
+
3
+ #include "error.h"
4
+
5
+ //-----------------------------------------------------------------------------
6
+
7
+ VALUE error_declare( VALUE zeromq_module )
8
+ {
9
+ return rb_define_class_under(
10
+ zeromq_module,
11
+ "Error",
12
+ rb_eRuntimeError
13
+ );
14
+ }
data/extension/error.h ADDED
@@ -0,0 +1,7 @@
1
+ //-----------------------------------------------------------------------------
2
+
3
+ #include "extension.h"
4
+
5
+ //-----------------------------------------------------------------------------
6
+
7
+ VALUE error_declare( VALUE zeromq_module );
@@ -0,0 +1,41 @@
1
+ require 'mkmf'
2
+ dir_config( 'zeromq' )
3
+
4
+ def header?
5
+
6
+ have_header( 'zmq.h' ) ||
7
+ find_header(
8
+ 'zmq.h',
9
+ '/opt/local/include',
10
+ '/usr/local/include',
11
+ '/usr/include'
12
+ )
13
+
14
+ end
15
+
16
+ def library?
17
+
18
+ have_library( 'zmq', 'zmq_init' ) ||
19
+ find_library(
20
+ 'zmq',
21
+ 'zmq_init',
22
+ '/opt/local/lib',
23
+ '/usr/local/lib',
24
+ '/usr/lib'
25
+ )
26
+
27
+ end
28
+
29
+ if header? && library?
30
+
31
+ puts "Cool, I found your zmq install..."
32
+
33
+ create_makefile( 'zeromq' )
34
+
35
+ else
36
+
37
+ raise "Couldn't find zmq library. try setting --with-zmq-dir=<path> to tell me where it is."
38
+
39
+ end
40
+
41
+
@@ -0,0 +1,21 @@
1
+ #include "extension.h"
2
+
3
+ #include "zeromq.h"
4
+ #include "error.h"
5
+ #include "context.h"
6
+ #include "socket.h"
7
+
8
+ VALUE module;
9
+ VALUE exception_type;
10
+ VALUE context_class;
11
+ VALUE socket_class;
12
+
13
+ void Init_zeromq()
14
+ //----------------
15
+ {
16
+ module = module_declare();
17
+
18
+ exception_type = error_declare( module );
19
+ context_class = context_declare( module );
20
+ socket_class = socket_declare( module );
21
+ }
@@ -0,0 +1,63 @@
1
+ /*
2
+ Copyright (c) 2007-2010 iMatix Corporation
3
+
4
+ This file is part of 0MQ.
5
+
6
+ 0MQ is free software; you can redistribute it and/or modify it under
7
+ the terms of the Lesser GNU General Public License as published by
8
+ the Free Software Foundation; either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ 0MQ is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ Lesser GNU General Public License for more details.
15
+
16
+ You should have received a copy of the Lesser GNU General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+ #include <assert.h>
21
+ #include <string.h>
22
+ #include <ruby.h>
23
+ #ifdef HAVE_RUBY_IO_H
24
+ #include <ruby/io.h>
25
+ #else
26
+ #include <rubyio.h>
27
+ #endif
28
+ #include <zmq.h>
29
+
30
+ #if defined _MSC_VER
31
+ #ifndef int8_t
32
+ typedef __int8 int8_t;
33
+ #endif
34
+ #ifndef int16_t
35
+ typedef __int16 int16_t;
36
+ #endif
37
+ #ifndef int32_t
38
+ typedef __int32 int32_t;
39
+ #endif
40
+ #ifndef int64_t
41
+ typedef __int64 int64_t;
42
+ #endif
43
+ #ifndef uint8_t
44
+ typedef unsigned __int8 uint8_t;
45
+ #endif
46
+ #ifndef uint16_t
47
+ typedef unsigned __int16 uint16_t;
48
+ #endif
49
+ #ifndef uint32_t
50
+ typedef unsigned __int32 uint32_t;
51
+ #endif
52
+ #ifndef uint64_t
53
+ typedef unsigned __int64 uint64_t;
54
+ #endif
55
+ #else
56
+ #include <stdint.h>
57
+ #endif
58
+
59
+ //-----------------------------------------------------------------------------
60
+
61
+ extern VALUE context_class;
62
+ extern VALUE socket_class;
63
+ extern VALUE exception_type;
@@ -0,0 +1,591 @@
1
+ //-----------------------------------------------------------------------------
2
+
3
+ #include "socket.h"
4
+ #include "context.h"
5
+
6
+ //-----------------------------------------------------------------------------
7
+
8
+ #define Check_Socket(__socket) \
9
+ do {\
10
+ if ((__socket->socket) == NULL)\
11
+ rb_raise (rb_eIOError, "closed socket");\
12
+ } while(0)
13
+
14
+ //-----------------------------------------------------------------------------
15
+ // ZeroMQ::Socket method declarations
16
+
17
+ static VALUE socket_allocate( VALUE socket_class );
18
+ void socket_free( void* instance );
19
+
20
+ static VALUE socket_initialize( int count, VALUE* arguments, VALUE self );
21
+ static VALUE socket_close( VALUE self );
22
+
23
+ static VALUE socket_getsockopt( VALUE self, VALUE option );
24
+ static VALUE socket_setsockopt( VALUE self, VALUE option, VALUE value );
25
+ static VALUE socket_bind( VALUE self, VALUE addr_ );
26
+ static VALUE socket_connect( VALUE self, VALUE addr_ );
27
+
28
+ static VALUE socket_recv( int argc_, VALUE* argv_, VALUE self_ );
29
+ static VALUE socket_send( int argc_, VALUE* argv_, VALUE self_ );
30
+
31
+ //-----------------------------------------------------------------------------
32
+ // zeromq socket helper functions
33
+
34
+ struct zeromq_socket* zeromq_socket_create()
35
+ //------------------------------------------
36
+ {
37
+ struct zeromq_socket* socket;
38
+
39
+ socket = ALLOC( struct zeromq_socket );
40
+ socket->context = NULL;
41
+ socket->socket = NULL;
42
+
43
+ return socket;
44
+ }
45
+
46
+ void zeromq_socket_destroy( struct zeromq_socket* zeromq_socket )
47
+ //---------------------------------------------------------------
48
+ {
49
+ if ( zeromq_socket->socket != NULL )
50
+ {
51
+ int rc = zmq_close( zeromq_socket->socket );
52
+ assert( rc == 0 );
53
+ }
54
+
55
+ if ( zeromq_socket->context != NULL )
56
+ {
57
+ zeromq_context_release( zeromq_socket->context );
58
+ }
59
+
60
+ xfree( zeromq_socket );
61
+ }
62
+
63
+ int zeromq_apply_socket_option( VALUE option, VALUE value, VALUE socket )
64
+ //-----------------------------------------------------------------------
65
+ {
66
+ socket_setsockopt( socket, option, value );
67
+ return ST_CONTINUE;
68
+ }
69
+
70
+ //-----------------------------------------------------------------------------
71
+ // ZeroMQ::Socket class initialization
72
+
73
+ VALUE socket_declare( VALUE zeromq_module )
74
+ //-----------------------------------------
75
+ {
76
+ VALUE klass = Qnil;
77
+
78
+ klass = rb_define_class_under( zeromq_module, "Socket", rb_cObject );
79
+ rb_define_alloc_func( klass, socket_allocate );
80
+
81
+ rb_define_method( klass, "initialize", socket_initialize, -1 );
82
+ rb_define_method( klass, "getsockopt", socket_getsockopt, 1 );
83
+ rb_define_method( klass, "setsockopt", socket_setsockopt, 2 );
84
+ rb_define_method( klass, "bind", socket_bind, 1 );
85
+ rb_define_method( klass, "connect", socket_connect, 1 );
86
+ rb_define_method( klass, "send", socket_send, -1 );
87
+ rb_define_method( klass, "recv", socket_recv, -1 );
88
+ rb_define_method( klass, "close", socket_close, 0 );
89
+
90
+ return klass;
91
+ }
92
+
93
+ //-----------------------------------------------------------------------------
94
+ // ZeroMQ::Socket method implmentation
95
+
96
+ static VALUE socket_allocate( VALUE socket_class )
97
+ //------------------------------------------------
98
+ {
99
+ return rb_data_object_alloc(
100
+ socket_class,
101
+ zeromq_socket_create(),
102
+ 0,
103
+ socket_free
104
+ );
105
+ }
106
+
107
+ void socket_free( void* instance )
108
+ //--------------------------------
109
+ {
110
+ zeromq_socket_destroy( ( struct zeromq_socket* )instance );
111
+ }
112
+
113
+ static VALUE socket_initialize( int arg_count, VALUE* arguments, VALUE self )
114
+ //---------------------------------------------------------------------------
115
+ {
116
+ struct zeromq_socket* socket = NULL;
117
+ Data_Get_Struct( self, void, socket );
118
+
119
+ VALUE context = Qnil;
120
+ VALUE socket_type = Qnil;
121
+ VALUE socket_options = Qnil;
122
+
123
+ rb_scan_args(
124
+ arg_count,
125
+ arguments,
126
+ "12",
127
+ &context,
128
+ &socket_type,
129
+ &socket_options
130
+ );
131
+
132
+ if ( CLASS_OF( context ) != context_class )
133
+ {
134
+ socket_options = socket_type;
135
+ socket_type = context;
136
+ context = Qnil;
137
+ }
138
+
139
+ if ( context == Qnil )
140
+ {
141
+ context = context_default( context_class );
142
+ }
143
+
144
+ if ( socket_type == Qnil )
145
+ {
146
+ rb_raise( exception_type, "The socket type is required." );
147
+ return Qnil;
148
+ }
149
+
150
+ struct zeromq_context* context_struct = NULL;
151
+ Data_Get_Struct( context, void, context_struct );
152
+
153
+ socket->socket = zmq_socket(
154
+ context_struct->context,
155
+ NUM2INT( socket_type )
156
+ );
157
+
158
+ if ( !socket->socket )
159
+ {
160
+ rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
161
+ return Qnil;
162
+ }
163
+
164
+ socket->context = context_struct;
165
+ zeromq_context_retain( socket->context );
166
+
167
+ if ( CLASS_OF( socket_options ) == rb_cHash )
168
+ {
169
+ rb_hash_foreach( socket_options, zeromq_apply_socket_option, self );
170
+ }
171
+
172
+ return self;
173
+ }
174
+
175
+ static VALUE socket_close( VALUE self_ )
176
+ //--------------------------------------
177
+ {
178
+ struct zeromq_socket * s;
179
+ Data_Get_Struct (self_, struct zeromq_socket, s);
180
+ if (s->socket != NULL) {
181
+ int rc = zmq_close(s->socket);
182
+ if (rc != 0) {
183
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
184
+ return Qnil;
185
+ }
186
+
187
+ s->socket = NULL;
188
+
189
+ /* Decrement the refcounter for the context (and possibly free it). */
190
+ zeromq_context_release( s->context );
191
+ s->context = NULL;
192
+ }
193
+ return Qnil;
194
+ }
195
+
196
+ static VALUE socket_getsockopt( VALUE self_, VALUE option_ )
197
+ {
198
+ int rc = 0;
199
+ VALUE retval;
200
+ struct zeromq_socket * s;
201
+
202
+ Data_Get_Struct (self_, struct zeromq_socket, s);
203
+ Check_Socket (s);
204
+
205
+ switch ( NUM2INT( option_ ) )
206
+ {
207
+ case ZMQ_FD:
208
+ {
209
+ #ifdef _WIN32
210
+ SOCKET optval;
211
+ #else
212
+ int optval;
213
+ #endif
214
+ size_t optvalsize = sizeof( optval );
215
+
216
+ rc = zmq_getsockopt(
217
+ s->socket,
218
+ NUM2INT( option_ ),
219
+ ( void* )&optval,
220
+ &optvalsize
221
+ );
222
+
223
+ if ( rc != 0 )
224
+ {
225
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
226
+ return Qnil;
227
+ }
228
+
229
+ if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
230
+ retval = optval ? Qtrue : Qfalse;
231
+ else
232
+ retval = INT2NUM (optval);
233
+ }
234
+ break;
235
+
236
+ case ZMQ_EVENTS:
237
+ {
238
+ uint32_t optval;
239
+ size_t optvalsize = sizeof(optval);
240
+
241
+ rc = zmq_getsockopt(
242
+ s->socket,
243
+ NUM2INT( option_ ),
244
+ ( void* )&optval,
245
+ &optvalsize
246
+ );
247
+
248
+ if ( rc != 0 )
249
+ {
250
+ rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
251
+ return Qnil;
252
+ }
253
+
254
+ if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
255
+ retval = optval ? Qtrue : Qfalse;
256
+ else
257
+ retval = INT2NUM( optval );
258
+ }
259
+ break;
260
+
261
+ case ZMQ_TYPE:
262
+ case ZMQ_LINGER:
263
+ case ZMQ_RECONNECT_IVL:
264
+ case ZMQ_BACKLOG:
265
+ case ZMQ_RECONNECT_IVL_MAX:
266
+ case ZMQ_SNDTIMEO:
267
+ case ZMQ_RCVTIMEO:
268
+ case ZMQ_RCVHWM:
269
+ case ZMQ_SNDHWM:
270
+ {
271
+ int optval;
272
+ size_t optvalsize = sizeof( optval );
273
+
274
+ rc = zmq_getsockopt(
275
+ s->socket,
276
+ NUM2INT( option_ ),
277
+ ( void* )&optval,
278
+ &optvalsize
279
+ );
280
+
281
+ if ( rc != 0 )
282
+ {
283
+ rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
284
+ return Qnil;
285
+ }
286
+
287
+ if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
288
+ retval = optval ? Qtrue : Qfalse;
289
+ else
290
+ retval = INT2NUM (optval);
291
+ }
292
+ break;
293
+
294
+ case ZMQ_RCVMORE:
295
+ case ZMQ_AFFINITY:
296
+ case ZMQ_RATE:
297
+ case ZMQ_RECOVERY_IVL:
298
+ case ZMQ_SNDBUF:
299
+ case ZMQ_RCVBUF:
300
+ {
301
+ int64_t optval;
302
+ size_t optvalsize = sizeof(optval);
303
+
304
+ rc = zmq_getsockopt (s->socket, NUM2INT (option_), (void *)&optval,
305
+ &optvalsize);
306
+
307
+ if (rc != 0) {
308
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
309
+ return Qnil;
310
+ }
311
+
312
+ if (NUM2INT (option_) == ZMQ_RCVMORE)
313
+ retval = optval ? Qtrue : Qfalse;
314
+ else
315
+ retval = INT2NUM (optval);
316
+ }
317
+ break;
318
+
319
+ case ZMQ_IDENTITY:
320
+ {
321
+ char identity[255];
322
+ size_t optvalsize = sizeof (identity);
323
+
324
+ rc = zmq_getsockopt (s->socket, NUM2INT (option_),
325
+ (void *)identity, &optvalsize);
326
+
327
+ if (rc != 0) {
328
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
329
+ return Qnil;
330
+ }
331
+
332
+ if (optvalsize > sizeof (identity))
333
+ optvalsize = sizeof (identity);
334
+
335
+ retval = rb_str_new (identity, optvalsize);
336
+ }
337
+ break;
338
+
339
+ default:
340
+ rb_raise (exception_type, "%s", zmq_strerror (EINVAL));
341
+ return Qnil;
342
+ }
343
+
344
+ return retval;
345
+ }
346
+
347
+ static VALUE socket_setsockopt (VALUE self_, VALUE option_, VALUE optval_)
348
+ {
349
+ int rc = 0;
350
+ struct zeromq_socket * s;
351
+
352
+ Data_Get_Struct (self_, struct zeromq_socket, s);
353
+ Check_Socket (s);
354
+
355
+ switch ( NUM2INT( option_ ) )
356
+ {
357
+ case ZMQ_AFFINITY:
358
+ case ZMQ_RATE:
359
+ case ZMQ_RECOVERY_IVL:
360
+ case ZMQ_SNDBUF:
361
+ case ZMQ_RCVBUF:
362
+ {
363
+ uint64_t optval = FIX2LONG (optval_);
364
+
365
+ // Forward the code to native 0MQ library.
366
+ rc = zmq_setsockopt(
367
+ s->socket,
368
+ NUM2INT( option_ ),
369
+ ( void* ) &optval,
370
+ sizeof( optval )
371
+ );
372
+ }
373
+ break;
374
+
375
+ case ZMQ_RCVHWM:
376
+ case ZMQ_SNDHWM:
377
+ case ZMQ_LINGER:
378
+ case ZMQ_RECONNECT_IVL:
379
+ case ZMQ_BACKLOG:
380
+ case ZMQ_RECONNECT_IVL_MAX:
381
+ case ZMQ_SNDTIMEO:
382
+ case ZMQ_RCVTIMEO:
383
+ {
384
+ int optval = FIX2INT (optval_);
385
+
386
+ // Forward the code to native 0MQ library.
387
+ rc = zmq_setsockopt(
388
+ s->socket,
389
+ NUM2INT( option_ ),
390
+ ( void* )&optval,
391
+ sizeof( optval )
392
+ );
393
+ }
394
+ break;
395
+
396
+ case ZMQ_IDENTITY:
397
+ case ZMQ_SUBSCRIBE:
398
+ case ZMQ_UNSUBSCRIBE:
399
+ {
400
+ // Forward the code to native 0MQ library.
401
+ rc = zmq_setsockopt(
402
+ s->socket,
403
+ NUM2INT( option_ ),
404
+ ( void* )StringValueCStr( optval_ ),
405
+ RSTRING_LEN( optval_ )
406
+ );
407
+ }
408
+ break;
409
+
410
+ default:
411
+ {
412
+ rb_raise( exception_type, "%s", zmq_strerror( EINVAL ) );
413
+ return Qnil;
414
+ }
415
+ }
416
+
417
+ if ( rc != 0 )
418
+ {
419
+ rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
420
+ return Qnil;
421
+ }
422
+
423
+ return self_;
424
+ }
425
+
426
+ static VALUE socket_bind( VALUE self_, VALUE addr_ )
427
+ {
428
+ struct zeromq_socket * s;
429
+ Data_Get_Struct (self_, struct zeromq_socket, s);
430
+ Check_Socket (s);
431
+
432
+ int rc = zmq_bind (s->socket, rb_string_value_cstr (&addr_));
433
+ if (rc != 0) {
434
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
435
+ return Qnil;
436
+ }
437
+
438
+ return Qnil;
439
+ }
440
+
441
+ static VALUE socket_connect( VALUE self_, VALUE addr_ )
442
+ {
443
+ struct zeromq_socket * s;
444
+ Data_Get_Struct (self_, struct zeromq_socket, s);
445
+ Check_Socket (s);
446
+
447
+ int rc = zmq_connect (s->socket, rb_string_value_cstr (&addr_));
448
+ if (rc != 0) {
449
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
450
+ return Qnil;
451
+ }
452
+
453
+ return Qnil;
454
+ }
455
+
456
+ #ifdef HAVE_RUBY_INTERN_H
457
+ struct zmq_send_recv_args {
458
+ void *socket;
459
+ zmq_msg_t *msg;
460
+ int flags;
461
+ int rc;
462
+ };
463
+
464
+ static VALUE zmq_send_blocking( void* args_ )
465
+ {
466
+ struct zmq_send_recv_args *send_args = (struct zmq_send_recv_args *)args_;
467
+
468
+ send_args->rc = zmq_sendmsg(
469
+ send_args->socket,
470
+ send_args->msg,
471
+ send_args->flags
472
+ );
473
+
474
+ return Qnil;
475
+ }
476
+ #endif
477
+
478
+ static VALUE socket_send (int argc_, VALUE* argv_, VALUE self_)
479
+ {
480
+ VALUE msg_, flags_;
481
+
482
+ rb_scan_args (argc_, argv_, "11", &msg_, &flags_);
483
+
484
+ struct zeromq_socket * s;
485
+ Data_Get_Struct (self_, struct zeromq_socket, s);
486
+ Check_Socket (s);
487
+
488
+ Check_Type (msg_, T_STRING);
489
+
490
+ int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
491
+
492
+ zmq_msg_t msg;
493
+ int msg_len = (int)RSTRING_LEN (msg_);
494
+ int rc = zmq_msg_init_size (&msg, msg_len);
495
+ if (rc != 0) {
496
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
497
+ return Qnil;
498
+ }
499
+ memcpy (zmq_msg_data (&msg), RSTRING_PTR (msg_), msg_len);
500
+
501
+ #ifdef HAVE_RUBY_INTERN_H
502
+ if (!(flags & ZMQ_NOBLOCK)) {
503
+ struct zmq_send_recv_args send_args;
504
+ send_args.socket = s->socket;
505
+ send_args.msg = &msg;
506
+ send_args.flags = flags;
507
+ rb_thread_blocking_region (zmq_send_blocking, (void*) &send_args, NULL, NULL);
508
+ rc = send_args.rc;
509
+ }
510
+ else
511
+ #endif
512
+ rc = zmq_sendmsg( s->socket, &msg, flags );
513
+ if (rc != 0 && zmq_errno () == EAGAIN) {
514
+ rc = zmq_msg_close (&msg);
515
+ assert (rc == 0);
516
+ return Qfalse;
517
+ }
518
+
519
+ if (rc != 0) {
520
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
521
+ rc = zmq_msg_close (&msg);
522
+ assert (rc == 0);
523
+ return Qnil;
524
+ }
525
+
526
+ rc = zmq_msg_close (&msg);
527
+ assert (rc == 0);
528
+ return Qtrue;
529
+ }
530
+
531
+ #ifdef HAVE_RUBY_INTERN_H
532
+ static VALUE zmq_recv_blocking (void* args_)
533
+ {
534
+ struct zmq_send_recv_args *recv_args = (struct zmq_send_recv_args *)args_;
535
+
536
+ recv_args->rc = zmq_recvmsg(recv_args->socket, recv_args->msg, recv_args->flags);
537
+
538
+ return Qnil;
539
+ }
540
+ #endif
541
+
542
+ static VALUE socket_recv (int argc_, VALUE* argv_, VALUE self_)
543
+ {
544
+ VALUE flags_;
545
+
546
+ rb_scan_args (argc_, argv_, "01", &flags_);
547
+
548
+ struct zeromq_socket * s;
549
+ Data_Get_Struct (self_, struct zeromq_socket, s);
550
+ Check_Socket (s);
551
+
552
+ int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
553
+
554
+ zmq_msg_t msg;
555
+ int rc = zmq_msg_init (&msg);
556
+ assert (rc == 0);
557
+
558
+ #ifdef HAVE_RUBY_INTERN_H
559
+ if (!(flags & ZMQ_NOBLOCK)) {
560
+ struct zmq_send_recv_args recv_args;
561
+ recv_args.socket = s->socket;
562
+ recv_args.msg = &msg;
563
+ recv_args.flags = flags;
564
+ rb_thread_blocking_region (zmq_recv_blocking, (void*) &recv_args,
565
+ NULL, NULL);
566
+ rc = recv_args.rc;
567
+ }
568
+ else
569
+ #endif
570
+ rc = zmq_recvmsg(s->socket, &msg, flags);
571
+ if (rc == -1 && zmq_errno () == EAGAIN) {
572
+ rc = zmq_msg_close (&msg);
573
+ assert (rc == 0);
574
+ return Qnil;
575
+ }
576
+
577
+ if (rc == -1) {
578
+ rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
579
+ rc = zmq_msg_close (&msg);
580
+ assert (rc == 0);
581
+ return Qnil;
582
+ }
583
+
584
+ VALUE message = rb_str_new ((char*) zmq_msg_data (&msg),
585
+ zmq_msg_size (&msg));
586
+ rc = zmq_msg_close (&msg);
587
+ assert (rc == 0);
588
+ return message;
589
+ }
590
+
591
+
@@ -0,0 +1,18 @@
1
+ #include "extension.h"
2
+
3
+ //-----------------------------------------------------------------------------
4
+
5
+ struct zeromq_socket
6
+ {
7
+ void* socket;
8
+ struct zeromq_context* context;
9
+ };
10
+
11
+ //-----------------------------------------------------------------------------
12
+
13
+ struct zeromq_socket* zeromq_socket_create();
14
+ void zeromq_socket_destroy( struct zeromq_socket* );
15
+
16
+ //-----------------------------------------------------------------------------
17
+
18
+ VALUE socket_declare( VALUE zeromq_module );
@@ -0,0 +1,284 @@
1
+ //-----------------------------------------------------------------------------
2
+
3
+ #include "zeromq.h"
4
+ #include "socket.h"
5
+
6
+ //-----------------------------------------------------------------------------
7
+
8
+ static VALUE module_version( VALUE self );
9
+ static VALUE module_select( int argument_count, VALUE* arguments, VALUE self );
10
+
11
+ //-----------------------------------------------------------------------------
12
+
13
+ VALUE module_declare()
14
+ //--------------------
15
+ {
16
+ VALUE zmq_module = rb_define_module( "ZeroMQ" );
17
+
18
+ rb_define_singleton_method( zmq_module, "version", module_version, 0 );
19
+ rb_define_singleton_method( zmq_module, "select", module_select, -1 );
20
+
21
+ rb_define_const (zmq_module, "SNDHWM", INT2NUM (ZMQ_SNDHWM));
22
+ rb_define_const (zmq_module, "RCVHWM", INT2NUM (ZMQ_RCVHWM));
23
+ rb_define_const (zmq_module, "AFFINITY", INT2NUM (ZMQ_AFFINITY));
24
+ rb_define_const (zmq_module, "IDENTITY", INT2NUM (ZMQ_IDENTITY));
25
+ rb_define_const (zmq_module, "SUBSCRIBE", INT2NUM (ZMQ_SUBSCRIBE));
26
+ rb_define_const (zmq_module, "UNSUBSCRIBE", INT2NUM (ZMQ_UNSUBSCRIBE));
27
+ rb_define_const (zmq_module, "RATE", INT2NUM (ZMQ_RATE));
28
+ rb_define_const (zmq_module, "RECOVERY_IVL", INT2NUM (ZMQ_RECOVERY_IVL));
29
+ rb_define_const (zmq_module, "SNDBUF", INT2NUM (ZMQ_SNDBUF));
30
+ rb_define_const (zmq_module, "RCVBUF", INT2NUM (ZMQ_RCVBUF));
31
+ rb_define_const (zmq_module, "SNDMORE", INT2NUM (ZMQ_SNDMORE));
32
+ rb_define_const (zmq_module, "RCVMORE", INT2NUM (ZMQ_RCVMORE));
33
+ rb_define_const (zmq_module, "FD", INT2NUM (ZMQ_FD));
34
+ rb_define_const (zmq_module, "EVENTS", INT2NUM (ZMQ_EVENTS));
35
+ rb_define_const (zmq_module, "TYPE", INT2NUM (ZMQ_TYPE));
36
+ rb_define_const (zmq_module, "LINGER", INT2NUM (ZMQ_LINGER));
37
+ rb_define_const (zmq_module, "RECONNECT_IVL", INT2NUM (ZMQ_RECONNECT_IVL));
38
+ rb_define_const (zmq_module, "BACKLOG", INT2NUM (ZMQ_BACKLOG));
39
+ rb_define_const (zmq_module, "RECONNECT_IVL_MAX", INT2NUM (ZMQ_RECONNECT_IVL_MAX));
40
+ rb_define_const (zmq_module, "RECOVERY_IVL_MSEC", INT2NUM (ZMQ_RECOVERY_IVL));
41
+ rb_define_const (zmq_module, "SNDTIMEO", INT2NUM (ZMQ_SNDTIMEO));
42
+ rb_define_const (zmq_module, "RCVTIMEO", INT2NUM (ZMQ_RCVTIMEO));
43
+ rb_define_const (zmq_module, "NOBLOCK", INT2NUM (ZMQ_NOBLOCK));
44
+ rb_define_const (zmq_module, "PAIR", INT2NUM (ZMQ_PAIR));
45
+ rb_define_const (zmq_module, "SUB", INT2NUM (ZMQ_SUB));
46
+ rb_define_const (zmq_module, "PUB", INT2NUM (ZMQ_PUB));
47
+ rb_define_const (zmq_module, "REQ", INT2NUM (ZMQ_REQ));
48
+ rb_define_const (zmq_module, "REP", INT2NUM (ZMQ_REP));
49
+
50
+ return zmq_module;
51
+ }
52
+
53
+ static VALUE module_version( VALUE self_ )
54
+ {
55
+ int major, minor, patch;
56
+
57
+ zmq_version(&major, &minor, &patch);
58
+
59
+ return rb_ary_new3 (3, INT2NUM (major), INT2NUM (minor), INT2NUM (patch));
60
+ }
61
+
62
+ struct poll_state {
63
+ int event;
64
+ int nitems;
65
+ zmq_pollitem_t *items;
66
+ VALUE io_objects;
67
+ };
68
+
69
+ typedef VALUE(*iterfunc)(ANYARGS);
70
+
71
+ static VALUE poll_add_item(VALUE io_, void *ps_) {
72
+ struct poll_state *state = (struct poll_state *)ps_;
73
+
74
+ long i;
75
+
76
+ for (i = 0; i < RARRAY_LEN (state->io_objects); i++) {
77
+ if (RARRAY_PTR (state->io_objects)[i] == io_) {
78
+ #ifdef HAVE_RUBY_IO_H
79
+ state->items[i].events |= state->event;
80
+ return Qnil;
81
+ #else
82
+ if (CLASS_OF (io_) == socket_class) {
83
+ state->items[i].events |= state->event;
84
+ return Qnil;
85
+ }
86
+
87
+ OpenFile *fptr;
88
+ GetOpenFile (io_, fptr);
89
+
90
+ if (state->event == ZMQ_POLLOUT &&
91
+ GetWriteFile (fptr) != NULL &&
92
+ fileno (GetWriteFile (fptr)) != state->items[i].fd) {
93
+ break;
94
+ }
95
+ else {
96
+ state->items[i].events |= state->event;
97
+ return Qnil;
98
+ }
99
+ #endif
100
+ }
101
+ }
102
+
103
+ /* Not found in array. Add a new poll item. */
104
+ rb_ary_push (state->io_objects, io_);
105
+
106
+ zmq_pollitem_t *item = &state->items[state->nitems];
107
+ state->nitems++;
108
+
109
+ item->events = state->event;
110
+
111
+ if (CLASS_OF (io_) == socket_class) {
112
+ struct zeromq_socket* socket;
113
+ Data_Get_Struct( io_, struct zeromq_socket, socket );
114
+
115
+ item->socket = socket->socket;
116
+ item->fd = -1;
117
+ }
118
+ else {
119
+ item->socket = NULL;
120
+
121
+ #ifdef HAVE_RUBY_IO_H
122
+ rb_io_t *fptr;
123
+
124
+ GetOpenFile (io_, fptr);
125
+ item->fd = fileno (rb_io_stdio_file (fptr));
126
+ #else
127
+ OpenFile *fptr;
128
+
129
+ GetOpenFile (io_, fptr);
130
+
131
+ if (state->event == ZMQ_POLLIN && GetReadFile (fptr) != NULL) {
132
+ item->fd = fileno (GetReadFile (fptr));
133
+ }
134
+ else if (state->event == ZMQ_POLLOUT && GetWriteFile (fptr) != NULL) {
135
+ item->fd = fileno (GetWriteFile (fptr));
136
+ }
137
+ else if (state->event == ZMQ_POLLERR) {
138
+ if (GetReadFile(fptr) != NULL)
139
+ item->fd = fileno (GetReadFile (fptr));
140
+ else
141
+ item->fd = fileno (GetWriteFile (fptr));
142
+ }
143
+ #endif
144
+ }
145
+
146
+ return Qnil;
147
+ }
148
+
149
+ #ifdef HAVE_RUBY_INTERN_H
150
+
151
+ struct zmq_poll_args {
152
+ zmq_pollitem_t *items;
153
+ int nitems;
154
+ long timeout_usec;
155
+ int rc;
156
+ };
157
+
158
+ static VALUE zmq_poll_blocking (void* args_)
159
+ {
160
+ struct zmq_poll_args *poll_args = (struct zmq_poll_args *)args_;
161
+
162
+ poll_args->rc = zmq_poll (poll_args->items, poll_args->nitems, poll_args->timeout_usec);
163
+
164
+ return Qnil;
165
+ }
166
+
167
+ #endif
168
+
169
+ struct select_arg {
170
+ VALUE readset;
171
+ VALUE writeset;
172
+ VALUE errset;
173
+ long timeout_usec;
174
+ zmq_pollitem_t *items;
175
+ };
176
+
177
+ static VALUE internal_select(VALUE argval)
178
+ {
179
+ struct select_arg *arg = (struct select_arg *)argval;
180
+
181
+ int rc, nitems, i;
182
+ zmq_pollitem_t *item;
183
+
184
+ struct poll_state ps;
185
+ ps.nitems = 0;
186
+ ps.items = arg->items;
187
+ ps.io_objects = rb_ary_new ();
188
+
189
+ if (!NIL_P (arg->readset)) {
190
+ ps.event = ZMQ_POLLIN;
191
+ rb_iterate(rb_each, arg->readset, (iterfunc)poll_add_item, (VALUE)&ps);
192
+ }
193
+
194
+ if (!NIL_P (arg->writeset)) {
195
+ ps.event = ZMQ_POLLOUT;
196
+ rb_iterate(rb_each, arg->writeset, (iterfunc)poll_add_item, (VALUE)&ps);
197
+ }
198
+
199
+ if (!NIL_P (arg->errset)) {
200
+ ps.event = ZMQ_POLLERR;
201
+ rb_iterate(rb_each, arg->errset, (iterfunc)poll_add_item, (VALUE)&ps);
202
+ }
203
+
204
+ /* Reset nitems to the actual number of zmq_pollitem_t records we're sending. */
205
+ nitems = ps.nitems;
206
+
207
+ #ifdef HAVE_RUBY_INTERN_H
208
+ if (arg->timeout_usec != 0) {
209
+ struct zmq_poll_args poll_args;
210
+ poll_args.items = ps.items;
211
+ poll_args.nitems = ps.nitems;
212
+ poll_args.timeout_usec = arg->timeout_usec;
213
+
214
+ rb_thread_blocking_region (zmq_poll_blocking, (void*)&poll_args, NULL, NULL);
215
+ rc = poll_args.rc;
216
+ }
217
+ else
218
+ #endif
219
+ rc = zmq_poll (ps.items, ps.nitems, arg->timeout_usec);
220
+
221
+ if (rc == -1) {
222
+ rb_raise(exception_type, "%s", zmq_strerror (zmq_errno ()));
223
+ return Qnil;
224
+ }
225
+ else if (rc == 0)
226
+ return Qnil;
227
+
228
+ VALUE read_active = rb_ary_new ();
229
+ VALUE write_active = rb_ary_new ();
230
+ VALUE err_active = rb_ary_new ();
231
+
232
+ for (i = 0, item = &ps.items[0]; i < nitems; i++, item++) {
233
+ if (item->revents != 0) {
234
+ VALUE io = RARRAY_PTR (ps.io_objects)[i];
235
+
236
+ if (item->revents & ZMQ_POLLIN)
237
+ rb_ary_push (read_active, io);
238
+ if (item->revents & ZMQ_POLLOUT)
239
+ rb_ary_push (write_active, io);
240
+ if (item->revents & ZMQ_POLLERR)
241
+ rb_ary_push (err_active, io);
242
+ }
243
+ }
244
+
245
+ return rb_ary_new3 (3, read_active, write_active, err_active);
246
+ }
247
+
248
+ static VALUE module_select_internal(VALUE readset, VALUE writeset, VALUE errset, long timeout_usec)
249
+ {
250
+ size_t nitems;
251
+ struct select_arg arg;
252
+
253
+ /* Conservative estimate for nitems before we traverse the lists. */
254
+ nitems = (NIL_P (readset) ? 0 : RARRAY_LEN (readset)) +
255
+ (NIL_P (writeset) ? 0 : RARRAY_LEN (writeset)) +
256
+ (NIL_P (errset) ? 0 : RARRAY_LEN (errset));
257
+ arg.items = ALLOC_N(zmq_pollitem_t, nitems);
258
+
259
+ arg.readset = readset;
260
+ arg.writeset = writeset;
261
+ arg.errset = errset;
262
+ arg.timeout_usec = timeout_usec;
263
+
264
+ return rb_ensure(internal_select, (VALUE)&arg, (VALUE (*)())xfree, (VALUE)arg.items);
265
+ }
266
+
267
+ static VALUE module_select (int argc_, VALUE* argv_, VALUE self_)
268
+ {
269
+ VALUE readset, writeset, errset, timeout;
270
+ rb_scan_args (argc_, argv_, "13", &readset, &writeset, &errset, &timeout);
271
+
272
+ long timeout_usec;
273
+
274
+ if (!NIL_P (readset)) Check_Type (readset, T_ARRAY);
275
+ if (!NIL_P (writeset)) Check_Type (writeset, T_ARRAY);
276
+ if (!NIL_P (errset)) Check_Type (errset, T_ARRAY);
277
+
278
+ if (NIL_P (timeout))
279
+ timeout_usec = -1;
280
+ else
281
+ timeout_usec = (long)(NUM2DBL (timeout) * 1000000);
282
+
283
+ return module_select_internal(readset, writeset, errset, timeout_usec);
284
+ }
@@ -0,0 +1,3 @@
1
+ #include "extension.h"
2
+
3
+ VALUE module_declare();
@@ -0,0 +1,3 @@
1
+ module ZeroMQ
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zeromq
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kristoph Cichocki-Romanov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-24 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: This gem provides a Ruby API for the ZeroMQ messaging library.
15
+ email:
16
+ - open-source@kristoph.net
17
+ executables: []
18
+ extensions:
19
+ - extension/extconf.rb
20
+ extra_rdoc_files: []
21
+ files:
22
+ - extension/context.c
23
+ - extension/error.c
24
+ - extension/extension.c
25
+ - extension/socket.c
26
+ - extension/zeromq.c
27
+ - extension/context.h
28
+ - extension/error.h
29
+ - extension/extension.h
30
+ - extension/socket.h
31
+ - extension/zeromq.h
32
+ - lib/zeromq/version.rb
33
+ - extension/extconf.rb
34
+ homepage:
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.24
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Ruby API for ZeroMQ
58
+ test_files: []