zmq 1.0 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/rbzmq.c ADDED
@@ -0,0 +1,1365 @@
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
+ #define Check_Socket(__socket) \
60
+ do {\
61
+ if ((__socket) == NULL)\
62
+ rb_raise (rb_eIOError, "closed socket");\
63
+ } while(0)
64
+
65
+ VALUE socket_type;
66
+
67
+ /*
68
+ * Document-class: ZMQ
69
+ *
70
+ * Ruby interface to the zeromq messaging library.
71
+ */
72
+
73
+ /*
74
+ * call-seq:
75
+ * ZMQ.version() -> [major, minor, patch]
76
+ *
77
+ * Returns the version of the zeromq library.
78
+ */
79
+ static VALUE module_version (VALUE self_)
80
+ {
81
+ int major, minor, patch;
82
+
83
+ zmq_version(&major, &minor, &patch);
84
+
85
+ return rb_ary_new3 (3, INT2NUM (major), INT2NUM (minor), INT2NUM (patch));
86
+ }
87
+
88
+ /*
89
+ * Document-class: ZMQ::Context
90
+ *
91
+ * ZeroMQ library context.
92
+ */
93
+
94
+ static void context_free (void *ctx)
95
+ {
96
+ if (ctx) {
97
+ int rc = zmq_term (ctx);
98
+ assert (rc == 0);
99
+ }
100
+ }
101
+
102
+ static VALUE context_alloc (VALUE class_)
103
+ {
104
+ return rb_data_object_alloc (class_, NULL, 0, context_free);
105
+ }
106
+
107
+ /*
108
+ * Document-method: new
109
+ *
110
+ * call-seq:
111
+ * new(io_threads=1)
112
+ *
113
+ * Initializes a new 0MQ context. The io_threads argument specifies the size
114
+ * of the 0MQ thread pool to handle I/O operations. If your application is
115
+ * using only the _inproc_ transport for you may set this to zero; otherwise,
116
+ * set it to at least one.
117
+ */
118
+
119
+ static VALUE context_initialize (int argc_, VALUE* argv_, VALUE self_)
120
+ {
121
+ VALUE io_threads;
122
+ rb_scan_args (argc_, argv_, "01", &io_threads);
123
+
124
+ assert (!DATA_PTR (self_));
125
+ void *ctx = zmq_init (NIL_P (io_threads) ? 1 : NUM2INT (io_threads));
126
+ if (!ctx) {
127
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
128
+ return Qnil;
129
+ }
130
+
131
+ DATA_PTR (self_) = (void*) ctx;
132
+ return self_;
133
+ }
134
+
135
+ /*
136
+ * call-seq:
137
+ * zmq.close() -> nil
138
+ *
139
+ * Terminates the 0MQ context. If there are no longer any sockets open within
140
+ * context at the time zmq_term() is called then context shall be shut down and
141
+ * all associated resources shall be released immediately.
142
+ *
143
+ * Otherwise, the following applies:
144
+ * - The close() function shall return immediately.
145
+ * - Any blocking operations currently in progress on sockets open within
146
+ * context shall return immediately with an error code of ETERM.
147
+ * - With the exception of ZMQ::Socket#close(), any further operations on
148
+ * sockets open within context shall fail with an error code of ETERM.
149
+ * - The actual shutdown of context, and release of any associated resources, shall
150
+ * be delayed until the last socket within it is closed with ZMQ::Socket#close().
151
+ */
152
+ static VALUE context_close (VALUE self_)
153
+ {
154
+ void * ctx = NULL;
155
+ Data_Get_Struct (self_, void, ctx);
156
+
157
+ if (ctx != NULL) {
158
+ int rc = zmq_term (ctx);
159
+ assert (rc == 0);
160
+
161
+ DATA_PTR (self_) = NULL;
162
+ }
163
+
164
+ return Qnil;
165
+ }
166
+
167
+ struct poll_state {
168
+ int event;
169
+ int nitems;
170
+ zmq_pollitem_t *items;
171
+ VALUE io_objects;
172
+ };
173
+
174
+ typedef VALUE(*iterfunc)(ANYARGS);
175
+
176
+ static VALUE poll_add_item(VALUE io_, void *ps_) {
177
+ struct poll_state *state = (struct poll_state *)ps_;
178
+
179
+ long i;
180
+
181
+ for (i = 0; i < RARRAY_LEN (state->io_objects); i++) {
182
+ if (RARRAY_PTR (state->io_objects)[i] == io_) {
183
+ #ifdef HAVE_RUBY_IO_H
184
+ state->items[i].events |= state->event;
185
+ return Qnil;
186
+ #else
187
+ if (CLASS_OF (io_) == socket_type) {
188
+ state->items[i].events |= state->event;
189
+ return Qnil;
190
+ }
191
+
192
+ OpenFile *fptr;
193
+ GetOpenFile (io_, fptr);
194
+
195
+ if (state->event == ZMQ_POLLOUT &&
196
+ GetWriteFile (fptr) != NULL &&
197
+ fileno (GetWriteFile (fptr)) != state->items[i].fd) {
198
+ break;
199
+ }
200
+ else {
201
+ state->items[i].events |= state->event;
202
+ return Qnil;
203
+ }
204
+ #endif
205
+ }
206
+ }
207
+
208
+ /* Not found in array. Add a new poll item. */
209
+ rb_ary_push (state->io_objects, io_);
210
+
211
+ zmq_pollitem_t *item = &state->items[state->nitems];
212
+ state->nitems++;
213
+
214
+ item->events = state->event;
215
+
216
+ if (CLASS_OF (io_) == socket_type) {
217
+ item->socket = DATA_PTR (io_);
218
+ item->fd = -1;
219
+ }
220
+ else {
221
+ item->socket = NULL;
222
+
223
+ #ifdef HAVE_RUBY_IO_H
224
+ rb_io_t *fptr;
225
+
226
+ GetOpenFile (io_, fptr);
227
+ item->fd = fileno (rb_io_stdio_file (fptr));
228
+ #else
229
+ OpenFile *fptr;
230
+
231
+ GetOpenFile (io_, fptr);
232
+
233
+ if (state->event == ZMQ_POLLIN && GetReadFile (fptr) != NULL) {
234
+ item->fd = fileno (GetReadFile (fptr));
235
+ }
236
+ else if (state->event == ZMQ_POLLOUT && GetWriteFile (fptr) != NULL) {
237
+ item->fd = fileno (GetWriteFile (fptr));
238
+ }
239
+ else if (state->event == ZMQ_POLLERR) {
240
+ if (GetReadFile(fptr) != NULL)
241
+ item->fd = fileno (GetReadFile (fptr));
242
+ else
243
+ item->fd = fileno (GetWriteFile (fptr));
244
+ }
245
+ #endif
246
+ }
247
+
248
+ return Qnil;
249
+ }
250
+
251
+ #ifdef HAVE_RUBY_INTERN_H
252
+
253
+ struct zmq_poll_args {
254
+ zmq_pollitem_t *items;
255
+ int nitems;
256
+ long timeout_usec;
257
+ int rc;
258
+ };
259
+
260
+ static VALUE zmq_poll_blocking (void* args_)
261
+ {
262
+ struct zmq_poll_args *poll_args = (struct zmq_poll_args *)args_;
263
+
264
+ poll_args->rc = zmq_poll (poll_args->items, poll_args->nitems, poll_args->timeout_usec);
265
+
266
+ return Qnil;
267
+ }
268
+
269
+ #endif
270
+
271
+ /*
272
+ * call-seq:
273
+ * ZMQ.select(in, out=[], err=[], timeout=nil) -> [in, out, err] | nil
274
+ *
275
+ * Like IO.select, but also works with 0MQ sockets.
276
+ */
277
+ static VALUE module_select (int argc_, VALUE* argv_, VALUE self_)
278
+ {
279
+ VALUE readset, writeset, errset, timeout;
280
+ rb_scan_args (argc_, argv_, "13", &readset, &writeset, &errset, &timeout);
281
+
282
+ long timeout_usec;
283
+ int rc, nitems, i;
284
+ zmq_pollitem_t *items, *item;
285
+
286
+ if (!NIL_P (readset)) Check_Type (readset, T_ARRAY);
287
+ if (!NIL_P (writeset)) Check_Type (writeset, T_ARRAY);
288
+ if (!NIL_P (errset)) Check_Type (errset, T_ARRAY);
289
+
290
+ if (NIL_P (timeout))
291
+ timeout_usec = -1;
292
+ else
293
+ timeout_usec = (long)(NUM2DBL (timeout) * 1000000);
294
+
295
+ /* Conservative estimate for nitems before we traverse the lists. */
296
+ nitems = (NIL_P (readset) ? 0 : RARRAY_LEN (readset)) +
297
+ (NIL_P (writeset) ? 0 : RARRAY_LEN (writeset)) +
298
+ (NIL_P (errset) ? 0 : RARRAY_LEN (errset));
299
+ items = (zmq_pollitem_t*)ruby_xmalloc(sizeof(zmq_pollitem_t) * nitems);
300
+
301
+ struct poll_state ps;
302
+ ps.nitems = 0;
303
+ ps.items = items;
304
+ ps.io_objects = rb_ary_new ();
305
+
306
+ if (!NIL_P (readset)) {
307
+ ps.event = ZMQ_POLLIN;
308
+ rb_iterate(rb_each, readset, (iterfunc)poll_add_item, (VALUE)&ps);
309
+ }
310
+
311
+ if (!NIL_P (writeset)) {
312
+ ps.event = ZMQ_POLLOUT;
313
+ rb_iterate(rb_each, writeset, (iterfunc)poll_add_item, (VALUE)&ps);
314
+ }
315
+
316
+ if (!NIL_P (errset)) {
317
+ ps.event = ZMQ_POLLERR;
318
+ rb_iterate(rb_each, errset, (iterfunc)poll_add_item, (VALUE)&ps);
319
+ }
320
+
321
+ /* Reset nitems to the actual number of zmq_pollitem_t records we're sending. */
322
+ nitems = ps.nitems;
323
+
324
+ #ifdef HAVE_RUBY_INTERN_H
325
+ if (timeout_usec != 0) {
326
+ struct zmq_poll_args poll_args;
327
+ poll_args.items = items;
328
+ poll_args.nitems = nitems;
329
+ poll_args.timeout_usec = timeout_usec;
330
+
331
+ rb_thread_blocking_region (zmq_poll_blocking, (void*)&poll_args, NULL, NULL);
332
+ rc = poll_args.rc;
333
+ }
334
+ else
335
+ #endif
336
+ rc = zmq_poll (items, nitems, timeout_usec);
337
+
338
+ if (rc == -1) {
339
+ rb_raise(rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
340
+ return Qnil;
341
+ }
342
+ else if (rc == 0)
343
+ return Qnil;
344
+
345
+ VALUE read_active = rb_ary_new ();
346
+ VALUE write_active = rb_ary_new ();
347
+ VALUE err_active = rb_ary_new ();
348
+
349
+ for (i = 0, item = &items[0]; i < nitems; i++, item++) {
350
+ if (item->revents != 0) {
351
+ VALUE io = RARRAY_PTR (ps.io_objects)[i];
352
+
353
+ if (item->revents & ZMQ_POLLIN)
354
+ rb_ary_push (read_active, io);
355
+ if (item->revents & ZMQ_POLLOUT)
356
+ rb_ary_push (write_active, io);
357
+ if (item->revents & ZMQ_POLLERR)
358
+ rb_ary_push (err_active, io);
359
+ }
360
+ }
361
+
362
+ ruby_xfree (items);
363
+
364
+ return rb_ary_new3 (3, read_active, write_active, err_active);
365
+ }
366
+
367
+
368
+ static void socket_free (void *s)
369
+ {
370
+ if (s) {
371
+ int rc = zmq_close (s);
372
+ assert (rc == 0);
373
+ }
374
+ }
375
+
376
+ /*
377
+ * Document-method: socket
378
+ *
379
+ * call-seq:
380
+ * zmq.socket(socket_type)
381
+ *
382
+ * Creates a new 0MQ socket. The socket_type argument specifies the socket
383
+ * type, which determines the semantics of communication over the socket.
384
+ *
385
+ * The newly created socket is initially unbound, and not associated with any
386
+ * endpoints. In order to establish a message flow a socket must first be
387
+ * connected to at least one endpoint with connect(), or at least one
388
+ * endpoint must be created for accepting incoming connections with
389
+ * bind().
390
+ *
391
+ * For a description of the various socket types, see ZMQ::Socket.
392
+ */
393
+ static VALUE context_socket (VALUE self_, VALUE type_)
394
+ {
395
+ void * c = NULL;
396
+ Data_Get_Struct (self_, void, c);
397
+ void * s = zmq_socket (c, NUM2INT (type_));
398
+ if (!s) {
399
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
400
+ return Qnil;
401
+ }
402
+
403
+ return Data_Wrap_Struct(socket_type, 0, socket_free, s);
404
+ }
405
+
406
+ /*
407
+ * Document-class: ZMQ::Socket
408
+ *
409
+ * ZeroMQ message socket.
410
+ *
411
+ * = Description
412
+ * == Key differences to conventional sockets
413
+ * Generally speaking, conventional sockets present a _synchronous_ interface
414
+ * to either connection-oriented reliable byte streams (SOCK_STREAM), or
415
+ * connection-less unreliable datagrams (SOCK_DGRAM). In comparison, 0MQ
416
+ * sockets present an abstraction of an asynchronous <em>message queue</em>, with the
417
+ * exact queueing semantics depending on the socket type in use. Where
418
+ * conventional sockets transfer streams of bytes or discrete datagrams, 0MQ
419
+ * sockets transfer discrete _messages_.
420
+ *
421
+ * 0MQ sockets being _asynchronous_ means that the timings of the physical
422
+ * connection setup and teardown, reconnect and effective delivery are
423
+ * transparent to the user and organized by 0MQ itself. Further, messages
424
+ * may be _queued_ in the event that a peer is unavailable to receive them.
425
+ *
426
+ * Conventional sockets allow only strict one-to-one (two peers),
427
+ * many-to-one (many clients, one server), or in some cases one-to-many
428
+ * (multicast) relationships. With the exception of ZMQ::PAIR, 0MQ sockets
429
+ * may be connected <b>to multiple endpoints</b> using connect(), while
430
+ * simultaneously accepting incoming connections <b>from multiple endpoints</b>
431
+ * bound to the socket using bind(), thus allowing many-to-many relationships.
432
+ *
433
+ * == Socket Types
434
+ *
435
+ * The following sections present the socket types defined by 0MQ, grouped by
436
+ * the general <em>messaging pattern</em> which is built from related
437
+ * socket types.
438
+ *
439
+ * = Request-reply pattern
440
+ * The request-reply pattern is used for sending requests from a _client_ to one
441
+ * or more instances of a _service_, and receiving subsequent replies to each
442
+ * request sent.
443
+ *
444
+ * == ZMQ::REQ
445
+ * A socket of type ZMQ::REQ is used by a _client_ to send requests to and receive
446
+ * replies from a _service_. This socket type allows only an alternating sequence
447
+ * of send(request) and subsequent recv(reply) calls. Each request sent
448
+ * is load-balanced among all _services_, and each reply received is matched with
449
+ * the last issued request.
450
+ *
451
+ * When a ZMQ::REQ socket enters an exceptional state due to having reached the
452
+ * high water mark for all _services_, or if there are no _services_ at all, then
453
+ * any send() operations on the socket shall block until the exceptional
454
+ * state ends or at least one _service_ becomes available for sending; messages
455
+ * are not discarded.
456
+ *
457
+ * === Summary of ZMQ::REQ characteristics
458
+ * [Compatible peer sockets] ZMQ::REP
459
+ * [Direction] Bidirectional
460
+ * [Send/receive pattern] Send, Receive, Send, Receive, ...
461
+ * [Outgoing routing strategy] Load-balanced
462
+ * [Incoming routing strategy] Last peer
463
+ * [ZMQ::HWM option action] Block
464
+ *
465
+ * == ZMQ::REP
466
+ * A socket of type ZMQ::REP is used by a _service_ to receive requests from and
467
+ * send replies to a _client_. This socket type allows only an alternating
468
+ * sequence of recv(request) and subsequent send(reply) calls. Each
469
+ * request received is fair-queued from among all _clients_, and each reply sent
470
+ * is routed to the _client_ that issued the last request.
471
+ *
472
+ * When a ZMQ::REP socket enters an exceptional state due to having reached the
473
+ * high water mark for a _client_, then any replies sent to the _client_ in
474
+ * question shall be dropped until the exceptional state ends.
475
+ *
476
+ * === Summary of ZMQ::REP characteristics
477
+ * [Compatible peer sockets] ZMQ::REQ
478
+ * [Direction] Bidirectional
479
+ * [Send/receive pattern] Receive, Send, Receive, Send, ...
480
+ * [Incoming routing strategy] Fair-queued
481
+ * [Outgoing routing stratagy] Last peer
482
+ * [ZMQ::HWM option action] Drop
483
+ *
484
+ *
485
+ * = Publish-subscribe pattern
486
+ * The publish-subscribe pattern is used for one-to-many distribution of data
487
+ * from a single _publisher_ to multiple _subscribers_ in a fanout fashion.
488
+ *
489
+ * == ZMQ::PUB
490
+ * A socket of type ZMQ::PUB is used by a publisher to distribute data. Messages
491
+ * sent are distributed in a fanout fashion to all connected peers. The
492
+ * recv() function is not implemented for this socket type.
493
+ *
494
+ * When a ZMQ::PUB socket enters an exceptional state due to having reached the
495
+ * high water mark for a _subscriber_, then any messages that would be sent to the
496
+ * subscriber in question shall instead be dropped until the exceptional state
497
+ * ends.
498
+ *
499
+ * === Summary of ZMQ::PUB characteristics
500
+ * [Compatible peer sockets] ZMQ::SUB
501
+ * [Direction] Unidirectional
502
+ * [Send/receive pattern] Send only
503
+ * [Incoming routing strategy] N/A
504
+ * [Outgoing routing strategy] Fanout
505
+ * [ZMQ::HWM option action] Drop
506
+ *
507
+ * == ZMQ::SUB
508
+ *
509
+ * A socket of type ZMQ::SUB is used by a _subscriber_ to subscribe to data
510
+ * distributed by a _publisher_. Initially a ZMQ::SUB socket is not subscribed to
511
+ * any messages, use the ZMQ::SUBSCRIBE option of setsockopt() to specify which
512
+ * messages to subscribe to. The send() function is not implemented for this
513
+ * socket type.
514
+ *
515
+ * === Summary of ZMQ::SUB characteristics
516
+ * [Compatible peer sockets] ZMQ::PUB
517
+ * [Direction] Unidirectional
518
+ * [Send/receive pattern] Receive only
519
+ * [Incoming routing strategy] Fair-queued
520
+ * [Outgoing routing strategy] N/A
521
+ * [ZMQ::HWM option action] N/A
522
+ *
523
+ * = Pipeline pattern
524
+ * The pipeline pattern is used for distributing data to _nodes_ arranged in a
525
+ * pipeline. Data always flows down the pipeline, and each stage of the pipeline
526
+ * is connected to at least one _node_. When a pipeline stage is connected to
527
+ * multiple _nodes_ data is load-balanced among all connected _nodes_.
528
+ *
529
+ * == ZMQ::DOWNSTREAM
530
+ *
531
+ * A socket of type ZMQ::DOWNSTREAM is used by a pipeline node to send messages to downstream pipeline nodes. Messages are load-balanced to all connected downstream nodes. The ZMQ::recv() function is not implemented for this socket type.
532
+ *
533
+ * When a ZMQ::DOWNSTREAM socket enters an exceptional state due to having
534
+ * reached the high water mark for all downstream _nodes_, or if there are no
535
+ * downstream _nodes_ at all, then any send() operations on the socket shall
536
+ * block until the exceptional state ends or at least one downstream _node_
537
+ * becomes available for sending; messages are not discarded.
538
+ *
539
+ * === Summary of ZMQ::DOWNSTREAM characteristics
540
+ * [Compatible peer sockets] ZMQ::UPSTREAM
541
+ * [Direction] Unidirectional
542
+ * [Send/receive pattern] Send only
543
+ * [Incoming routing strategy] N/A
544
+ * [Outgoing routing strategy] Load-balanced
545
+ * [ZMQ::HWM option action] Block
546
+ *
547
+ * == ZMQ::UPSTREAM
548
+ *
549
+ * A socket of type ZMQ::UPSTREAM is used by a pipeline _node_ to receive messages
550
+ * from upstream pipeline _nodes_. Messages are fair-queued from among all
551
+ * connected upstream nodes. The send() function is not implemented for
552
+ * this socket type.
553
+ *
554
+ * === Summary of ZMQ::UPSTREAM characteristics
555
+ * [Compatible peer sockets] ZMQ::DOWNSTREAM
556
+ * [Direction] Unidirectional
557
+ * [Send/receive pattern] Receive only
558
+ * [Incoming routing strategy] Fair-queued
559
+ * [Outgoing routing strategy] N/A
560
+ * [ZMQ::HWM option action] N/A
561
+ *
562
+ * = Exclusive pair pattern
563
+ *
564
+ * The exclusive pair is an advanced pattern used for communicating exclusively
565
+ * between two peers.
566
+ *
567
+ * == ZMQ::PAIR
568
+ *
569
+ * A socket of type ZMQ::PAIR can only be connected to a single peer at any one
570
+ * time. No message routing or filtering is performed on messages sent over a
571
+ * ZMQ::PAIR socket.
572
+ *
573
+ * When a ZMQ::PAIR socket enters an exceptional state due to having reached the
574
+ * high water mark for the connected peer, or if no peer is connected, then any
575
+ * send() operations on the socket shall block until the peer becomes
576
+ * available for sending; messages are not discarded.
577
+ *
578
+ * *NOTE* ZMQ_PAIR sockets are experimental, and are currently missing several features such as auto-reconnection.
579
+ *
580
+ * === Summary of ZMQ::PAIR characteristics
581
+ * [Compatible peer sockets] ZMQ::PAIR
582
+ * [Direction] Bidirectional
583
+ * [Send/receive pattern] Unrestricted
584
+ * [Incoming routing strategy] N/A
585
+ * [Outcoming routing strategy] N/A
586
+ * [ZMQ::HWM option action] Block
587
+ */
588
+
589
+ /*
590
+ * call-seq:
591
+ * socket.getsockopt(option)
592
+ *
593
+ * Retrieves the value of the specified 0MQ socket option.
594
+ *
595
+ * The following options can be retrievesd with the getsockopt() function:
596
+ *
597
+ * == ZMQ::RCVMORE: More message parts to follow
598
+ * The ZMQ::RCVMORE option shall return a boolean value indicating if the
599
+ * multi-part message currently being read from the specified socket has more
600
+ * message parts to follow. If there are no message parts to follow or if the
601
+ * message currently being read is not a multi-part message a value of false
602
+ * shall be returned. Otherwise, a value of true shall be returned.
603
+ *
604
+ * Refer to send() and recv() for a detailed description of sending/receiving
605
+ * multi-part messages.
606
+ *
607
+ * [Option value type] Boolean
608
+ * [Option value unit] N/A
609
+ * [Default value] N/A
610
+ * [Applicable socket types] all
611
+ *
612
+ * == ZMQ::HWM: Retrieve high water mark
613
+ * The ZMQ::HWM option shall retrieve the high water mark for the specified
614
+ * _socket_. The high water mark is a hard limit on the maximum number of
615
+ * outstanding messages 0MQ shall queue in memory for any single peer that the
616
+ * specified _socket_ is communicating with.
617
+ *
618
+ * If this limit has been reached the socket shall enter an exceptional state
619
+ * and depending on the socket type, 0MQ shall take appropriate action such as
620
+ * blocking or dropping sent messages. Refer to the individual socket
621
+ * descriptions in ZMQ::Socket for details on the exact action taken for each
622
+ * socket type.
623
+ *
624
+ * The default ZMQ::HWM value of zero means "no limit".
625
+ *
626
+ * [Option value type] Integer
627
+ * [Option value unit] messages
628
+ * [Default value] 0
629
+ * [Applicable socket types] all
630
+ *
631
+ * == ZMQ::SWAP: Retrieve disk offload size
632
+ * The ZMQ::SWAP option shall retrieve the disk offload (swap) size for the
633
+ * specified _socket_. A socket which has ZMQ::SWAP set to a non-zero value may
634
+ * exceed it’s high water mark; in this case outstanding messages shall be
635
+ * offloaded to storage on disk rather than held in memory.
636
+ *
637
+ * The value of ZMQ::SWAP defines the maximum size of the swap space in bytes.
638
+ *
639
+ * [Option value type] Integer
640
+ * [Option value unit] bytes
641
+ * [Default value] 0
642
+ * [Applicable socket types] all
643
+ *
644
+ * == ZMQ::AFFINITY: Retrieve I/O thread affinity
645
+ * The ZMQ::AFFINITY option shall retrieve the I/O thread affinity for newly
646
+ * created connections on the specified _socket_.
647
+ *
648
+ * Affinity determines which threads from the 0MQ I/O thread pool associated
649
+ * with the socket’s _context_ shall handle newly created connections. A value of
650
+ * zero specifies no affinity, meaning that work shall be distributed fairly
651
+ * among all 0MQ I/O threads in the thread pool. For non-zero values, the lowest
652
+ * bit corresponds to thread 1, second lowest bit to thread 2 and so on. For
653
+ * example, a value of 3 specifies that subsequent connections on _socket_ shall
654
+ * be handled exclusively by I/O threads 1 and 2.
655
+ *
656
+ * See also ZMQ::Context#new for details on allocating the number of
657
+ * I/O threads for a specific _context_.
658
+ *
659
+ * [Option value type] Integer
660
+ * [Option value unit] N/A (bitmap)
661
+ * [Default value] 0
662
+ * [Applicable socket types] all
663
+ *
664
+ * == ZMQ::IDENTITY: Retrieve socket identity
665
+ * The ZMQ::IDENTITY option shall retrieve the identity of the specified _socket_.
666
+ * Socket identity determines if existing 0MQ infastructure (<em>message queues</em>,
667
+ * <em>forwarding devices</em>) shall be identified with a specific application and
668
+ * persist across multiple runs of the application.
669
+ *
670
+ * If the socket has no identity, each run of an application is completely
671
+ * separate from other runs. However, with identity set the socket shall re-use
672
+ * any existing 0MQ infrastructure configured by the previous run(s). Thus the
673
+ * application may receive messages that were sent in the meantime, <em>message
674
+ * queue</em> limits shall be shared with previous run(s) and so on.
675
+ *
676
+ * Identity can be at least one byte and at most 255 bytes long. Identities
677
+ * starting with binary zero are reserved for use by 0MQ infrastructure.
678
+ *
679
+ * [Option value type] String
680
+ * [Option value unit] N/A
681
+ * [Default value] nil
682
+ * [Applicable socket types] all
683
+ *
684
+ * == ZMQ::RATE: Retrieve multicast data rate
685
+ *
686
+ * The ZMQ::Rate option shall retrieve the maximum send or receive data
687
+ * rate for multicast transports using the specified _socket_.
688
+ *
689
+ * [Option value type] Integer
690
+ * [Option value unit] kilobits per second
691
+ * [Default value] 100
692
+ * [Applicable socket types] all, when using multicast transports
693
+ *
694
+ * == ZMQ::RECOVERY_IVL: Get multicast recovery interval
695
+ *
696
+ * The ZMQ::RECOVERY_IVL option shall retrieve the recovery interval for
697
+ * multicast transports using the specified _socket_. The recovery interval
698
+ * determines the maximum time in seconds that a receiver can be absent from a
699
+ * multicast group before unrecoverable data loss will occur.
700
+ *
701
+ * [Option value type] Integer
702
+ * [Option value unit] seconds
703
+ * [Default value] 10
704
+ * [Applicable socket types] all, when using multicast transports
705
+ *
706
+ * == ZMQ::MCAST_LOOP: Control multicast loopback
707
+ * The ZMQ::MCAST_LOOP option controls whether data sent via multicast transports
708
+ * can also be received by the sending host via loopback. A value of zero
709
+ * indicates that the loopback functionality is disabled, while the default
710
+ * value of 1 indicates that the loopback functionality is enabled. Leaving
711
+ * multicast loopback enabled when it is not required can have a negative impact
712
+ * on performance. Where possible, disable ZMQ::MCAST_LOOP in production
713
+ * environments.
714
+ *
715
+ * [Option value type] Boolean
716
+ * [Option value unit] N/A
717
+ * [Default value] true
718
+ * [Applicable socket types] all, when using multicast transports
719
+ *
720
+ * == ZMQ::SNDBUF: Retrieve kernel transmit buffer size
721
+ * The ZMQ::SNDBUF option shall retrieve the underlying kernel transmit buffer
722
+ * size for the specified _socket_. A value of zero means that the OS default is
723
+ * in effect. For details refer to your operating system documentation for the
724
+ * SO_SNDBUF socket option.
725
+ *
726
+ * [Option value type] Integer
727
+ * [Option value unit] bytes
728
+ * [Default value] 0
729
+ * [Applicable socket types] all
730
+ *
731
+ * == ZMQ::RCVBUF: Retrieve kernel receive buffer size
732
+ * The ZMQ::RCVBUF option shall retrieve the underlying kernel receive buffer
733
+ * size for the specified _socket_. A value of zero means that the OS default is
734
+ * in effect. For details refer to your operating system documentation for the
735
+ * SO_RCVBUF socket option.
736
+ *
737
+ * [Option value type] Integer
738
+ * [Option value unit] bytes
739
+ * [Default value] 0
740
+ * [Applicable socket types] all
741
+ *
742
+ */
743
+ static VALUE socket_getsockopt (VALUE self_, VALUE option_)
744
+ {
745
+ int rc = 0;
746
+ VALUE retval;
747
+ void * s;
748
+
749
+ Data_Get_Struct (self_, void, s);
750
+ Check_Socket (s);
751
+
752
+ switch (NUM2INT (option_)) {
753
+ case ZMQ_RCVMORE:
754
+ case ZMQ_HWM:
755
+ case ZMQ_SWAP:
756
+ case ZMQ_AFFINITY:
757
+ case ZMQ_RATE:
758
+ case ZMQ_RECOVERY_IVL:
759
+ case ZMQ_MCAST_LOOP:
760
+ case ZMQ_SNDBUF:
761
+ case ZMQ_RCVBUF:
762
+ {
763
+ int64_t optval;
764
+ size_t optvalsize = sizeof(optval);
765
+
766
+ rc = zmq_getsockopt (s, NUM2INT (option_), (void *)&optval,
767
+ &optvalsize);
768
+
769
+ if (rc != 0) {
770
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
771
+ return Qnil;
772
+ }
773
+
774
+ if (NUM2INT (option_) == ZMQ_RCVMORE)
775
+ retval = optval ? Qtrue : Qfalse;
776
+ else
777
+ retval = INT2NUM (optval);
778
+ }
779
+ break;
780
+ case ZMQ_IDENTITY:
781
+ {
782
+ char identity[255];
783
+ size_t optvalsize = sizeof (identity);
784
+
785
+ rc = zmq_getsockopt (s, NUM2INT (option_), (void *)identity,
786
+ &optvalsize);
787
+
788
+ if (rc != 0) {
789
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
790
+ return Qnil;
791
+ }
792
+
793
+ if (optvalsize > sizeof (identity))
794
+ optvalsize = sizeof (identity);
795
+
796
+ retval = rb_str_new (identity, optvalsize);
797
+ }
798
+ break;
799
+ default:
800
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (EINVAL));
801
+ return Qnil;
802
+ }
803
+
804
+ return retval;
805
+ }
806
+
807
+ /*
808
+ * call-seq:
809
+ * socket.setsockopt(option, value) -> nil
810
+ *
811
+ * Sets the value of a 0MQ socket option.
812
+ *
813
+ * The following socket options can be set with the setsockopt() function:
814
+ *
815
+ * == ZMQ::HWM: Set high water mark
816
+ * The ZMQ::HWM option shall set the high water mark for the specified _socket_.
817
+ * The high water mark is a hard limit on the maximum number of outstanding
818
+ * messages 0MQ shall queue in memory for any single peer that the specified
819
+ * _socket_ is communicating with.
820
+ *
821
+ * If this limit has been reached the socket shall enter an exceptional state
822
+ * and depending on the socket type, 0MQ shall take appropriate action such as
823
+ * blocking or dropping sent messages. Refer to the individual socket
824
+ * descriptions in ZMQ::Socket for details on the exact action taken for each
825
+ * socket type.
826
+ *
827
+ * The default ZMQ::HWM value of zero means "no limit".
828
+ *
829
+ * [Option value type] Integer
830
+ * [Option value unit] messages
831
+ * [Default value] 0
832
+ * [Applicable socket types] all
833
+ *
834
+ * == ZMQ::SWAP: Set disk offload size
835
+ * The ZMQ::SWAP option shall set the disk offload (swap) size for the specified
836
+ * socket. A socket which has ZMQ::SWAP set to a non-zero value may exceed it’s
837
+ * high water mark; in this case outstanding messages shall be offloaded to
838
+ * storage on disk rather than held in memory.
839
+ *
840
+ * The value of ZMQ::SWAP defines the maximum size of the swap space in bytes.
841
+ *
842
+ * [Option value type] Integer
843
+ * [Option value unit] bytes
844
+ * [Default value] 0
845
+ * [Applicable socket types] all
846
+ *
847
+ * == ZMQ::AFFINITY: Set I/O thread affinity
848
+ * The ZMQ::AFFINITY option shall set the I/O thread affinity for newly created
849
+ * connections on the specified socket.
850
+ *
851
+ * Affinity determines which threads from the 0MQ I/O thread pool associated
852
+ * with the socket’s _context_ shall handle newly created connections. A value of
853
+ * zero specifies no affinity, meaning that work shall be distributed fairly
854
+ * among all 0MQ I/O threads in the thread pool. For non-zero values, the lowest
855
+ * bit corresponds to thread 1, second lowest bit to thread 2 and so on. For
856
+ * example, a value of 3 specifies that subsequent connections on socket shall
857
+ * be handled exclusively by I/O threads 1 and 2.
858
+ *
859
+ * See also ZMQ::Context#new for details on allocating the number of I/O threads
860
+ * for a specific _context_.
861
+ *
862
+ * [Option value type] Integer
863
+ * [Option value unit] N/A (bitmap)
864
+ * [Default value] 0
865
+ * [Applicable socket types] all
866
+ *
867
+ * == ZMQ::IDENTITY: Set socket identity
868
+ * The ZMQ::IDENTITY option shall set the identity of the specified socket.
869
+ * Socket identity determines if existing 0MQ infastructure (<em>message queues</em>,
870
+ * <em>forwarding devices</em>) shall be identified with a specific application and
871
+ * persist across multiple runs of the application.
872
+ *
873
+ * If the socket has no identity, each run of an application is completely
874
+ * separate from other runs. However, with identity set the socket shall re-use
875
+ * any existing 0MQ infrastructure configured by the previous run(s). Thus the
876
+ * application may receive messages that were sent in the meantime, <em>message
877
+ * queue</em> limits shall be shared with previous run(s) and so on.
878
+ *
879
+ * Identity should be at least one byte and at most 255 bytes long. Identities
880
+ * starting with binary zero are reserved for use by 0MQ infrastructure.
881
+ *
882
+ * [Option value type] String
883
+ * [Option value unit] N/A
884
+ * [Default value] nil
885
+ * [Applicable socket types] all
886
+ *
887
+ * ZMQ::SUBSCRIBE: Establish message filter
888
+ * The ZMQ::SUBSCRIBE option shall establish a new message filter on a ZMQ::SUB
889
+ * socket. Newly created ZMQ::SUB sockets shall filter out all incoming messages,
890
+ * therefore you should call this option to establish an initial message filter.
891
+ *
892
+ * An empty _value_ of length zero shall subscribe to all incoming messages. A
893
+ * non-empty _value_ shall subscribe to all messages beginning with the
894
+ * specified prefix. Mutiple filters may be attached to a single ZMQ::SUB socket,
895
+ * in which case a message shall be accepted if it matches at least one filter.
896
+ *
897
+ * [Option value type] String
898
+ * [Option value unit] N/A
899
+ * [Default value] N/A
900
+ * [Applicable socket types] ZMQ::SUB
901
+ *
902
+ * == ZMQ::UNSUBSCRIBE: Remove message filter
903
+ * The ZMQ::UNSUBSCRIBE option shall remove an existing message filter on a
904
+ * ZMQ::SUB socket. The filter specified must match an existing filter
905
+ * previously established with the ZMQ::SUBSCRIBE option. If the socket has
906
+ * several instances of the same filter attached the ZMQ::UNSUBSCRIBE option
907
+ * shall remove only one instance, leaving the rest in place and functional.
908
+ *
909
+ * [Option value type] String
910
+ * [Option value unit] N/A
911
+ * [Default value] nil
912
+ * [Applicable socket types] all
913
+ *
914
+ * == ZMQ::RATE: Set multicast data rate
915
+ * The ZMQ::RATE option shall set the maximum send or receive data rate for
916
+ * multicast transports such as _pgm_ using the specified socket.
917
+ *
918
+ * [Option value type] Integer
919
+ * [Option value unit] kilobits per second
920
+ * [Default value] 100
921
+ * [Applicable socket types] all, when using multicast transports
922
+ *
923
+ * == ZMQ::RECOVERY_IVL: Set multicast recovery interval
924
+ * The ZMQ::RECOVERY_IVL option shall set the recovery interval for multicast
925
+ * transports using the specified _socket_. The recovery interval determines the
926
+ * maximum time in seconds that a receiver can be absent from a multicast group
927
+ * before unrecoverable data loss will occur.
928
+ *
929
+ * <b>Caution:</b> Exercise care when setting large recovery intervals as the data needed for recovery will be held in memory. For example, a 1 minute recovery interval at a data rate of 1Gbps requires a 7GB in-memory buffer.
930
+ *
931
+ * [Option value type] Integer
932
+ * [Option value unit] seconds
933
+ * [Default value] 10
934
+ * [Applicable socket types] all, when using multicast transports
935
+ *
936
+ * == ZMQ::MCAST_LOOP: Control multicast loopback
937
+ * The ZMQ::MCAST_LOOP option shall control whether data sent via multicast
938
+ * transports using the specified _socket_ can also be received by the sending
939
+ * host via loopback. A value of zero disables the loopback functionality, while
940
+ * the default value of 1 enables the loopback functionality. Leaving multicast
941
+ * loopback enabled when it is not required can have a negative impact on
942
+ * performance. Where possible, disable ZMQ::MCAST_LOOP in production
943
+ * environments.
944
+ *
945
+ * [Option value type] Boolean
946
+ * [Option value unit] N/A
947
+ * [Default value] true
948
+ * [Applicable socket types] all, when using multicast transports
949
+ *
950
+ * == ZMQ::SNDBUF: Set kernel transmit buffer size
951
+ * The ZMQ::SNDBUF option shall set the underlying kernel transmit buffer size
952
+ * for the socket to the specified size in bytes. A value of zero means leave
953
+ * the OS default unchanged. For details please refer to your operating system
954
+ * documentation for the SO_SNDBUF socket option.
955
+ *
956
+ * [Option value type] Integer
957
+ * [Option value unit] bytes
958
+ * [Default value] 0
959
+ * [Applicable socket types] all
960
+ *
961
+ * == ZMQ::RCVBUF: Set kernel receive buffer size
962
+ * The ZMQ::RCVBUF option shall set the underlying kernel receive buffer size
963
+ * for the socket to the specified size in bytes. A value of zero means leave
964
+ * the OS default unchanged. For details refer to your operating system
965
+ * documentation for the SO_RCVBUF socket option.
966
+ *
967
+ * [Option value type] Integer
968
+ * [Option value unit] bytes
969
+ * [Default value] 0
970
+ * [Applicable socket types] all
971
+ *
972
+ */
973
+ static VALUE socket_setsockopt (VALUE self_, VALUE option_,
974
+ VALUE optval_)
975
+ {
976
+
977
+ int rc = 0;
978
+ void * s;
979
+
980
+ Data_Get_Struct (self_, void, s);
981
+ Check_Socket (s);
982
+
983
+ switch (NUM2INT (option_)) {
984
+ case ZMQ_HWM:
985
+ case ZMQ_SWAP:
986
+ case ZMQ_AFFINITY:
987
+ case ZMQ_RATE:
988
+ case ZMQ_RECOVERY_IVL:
989
+ case ZMQ_MCAST_LOOP:
990
+ case ZMQ_SNDBUF:
991
+ case ZMQ_RCVBUF:
992
+ {
993
+ uint64_t optval = FIX2LONG (optval_);
994
+
995
+ // Forward the code to native 0MQ library.
996
+ rc = zmq_setsockopt (s, NUM2INT (option_),
997
+ (void*) &optval, sizeof (optval));
998
+ }
999
+ break;
1000
+
1001
+ case ZMQ_IDENTITY:
1002
+ case ZMQ_SUBSCRIBE:
1003
+ case ZMQ_UNSUBSCRIBE:
1004
+
1005
+ // Forward the code to native 0MQ library.
1006
+ rc = zmq_setsockopt (s, NUM2INT (option_),
1007
+ (void *) StringValueCStr (optval_), RSTRING_LEN (optval_));
1008
+ break;
1009
+
1010
+ default:
1011
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (EINVAL));
1012
+ return Qnil;
1013
+ }
1014
+
1015
+ if (rc != 0) {
1016
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1017
+ return Qnil;
1018
+ }
1019
+
1020
+ return self_;
1021
+ }
1022
+
1023
+ /*
1024
+ * call-seq:
1025
+ * socket.bind(endpoint) -> nil
1026
+ *
1027
+ * Creates an endpoint for accepting connections and binds it to the socket.
1028
+ *
1029
+ * The _endpoint_ argument is a string consisting of two parts as follows:
1030
+ * _transport://address_. The _transport_ part specifies the underlying
1031
+ * transport protocol to use. The meaning of the _address_ part is specific
1032
+ * to the underlying transport protocol selected.
1033
+ *
1034
+ * The following transports are defined:
1035
+ *
1036
+ * [_inproc_] local in-process (inter-thread) communication transport
1037
+ * [_ipc_] local inter-process communication transport
1038
+ * [_tcp_] unicast transport using TCP
1039
+ * [_pgm_, _epgm_] reliable multicast transport using PGM
1040
+ *
1041
+ * With the exception of ZMQ:PAIR sockets, a single socket may be connected to
1042
+ * multiple endpoints using connect(), while simultaneously accepting
1043
+ * incoming connections from multiple endpoints bound to the socket using
1044
+ * bind(). Refer to ZMQ::Socket for a description of the exact semantics
1045
+ * involved when connecting or binding a socket to multiple endpoints.
1046
+ */
1047
+ static VALUE socket_bind (VALUE self_, VALUE addr_)
1048
+ {
1049
+ void * s;
1050
+ Data_Get_Struct (self_, void, s);
1051
+ Check_Socket (s);
1052
+
1053
+ int rc = zmq_bind (s, rb_string_value_cstr (&addr_));
1054
+ if (rc != 0) {
1055
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1056
+ return Qnil;
1057
+ }
1058
+
1059
+ return Qnil;
1060
+ }
1061
+
1062
+ /*
1063
+ * call-seq:
1064
+ * socket.connect(endpoint) -> nil
1065
+ *
1066
+ * Connects the socket to the endpoint specified by the _endpoint_ argument.
1067
+ *
1068
+ * The _endpoint_ argument is a string consisting of two parts as follows:
1069
+ * _transport://address_. The _transport_ part specifies the underlying
1070
+ * transport protocol to use. The meaning of the _address_ part is specific
1071
+ * to the underlying transport protocol selected.
1072
+ *
1073
+ * The following transports are defined:
1074
+ *
1075
+ * [_inproc_] local in-process (inter-thread) communication transport
1076
+ * [_ipc_] local inter-process communication transport
1077
+ * [_tcp_] unicast transport using TCP
1078
+ * [_pgm_, _epgm_] reliable multicast transport using PGM
1079
+ *
1080
+ * With the exception of ZMQ:PAIR sockets, a single socket may be connected to
1081
+ * multiple endpoints using connect(), while simultaneously accepting
1082
+ * incoming connections from multiple endpoints bound to the socket using
1083
+ * bind(). Refer to ZMQ::Socket for a description of the exact semantics
1084
+ * involved when connecting or binding a socket to multiple endpoints.
1085
+ *
1086
+ * <b>NOTE:</b> The connection will not be performed immediately, but as needed by
1087
+ * 0MQ. Thus, a successful invocation of connect() does not indicate that
1088
+ * a physical connection was or can actually be established.
1089
+ */
1090
+ static VALUE socket_connect (VALUE self_, VALUE addr_)
1091
+ {
1092
+ void * s;
1093
+ Data_Get_Struct (self_, void, s);
1094
+ Check_Socket (s);
1095
+
1096
+ int rc = zmq_connect (s, rb_string_value_cstr (&addr_));
1097
+ if (rc != 0) {
1098
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1099
+ return Qnil;
1100
+ }
1101
+
1102
+ return Qnil;
1103
+ }
1104
+
1105
+ #ifdef HAVE_RUBY_INTERN_H
1106
+ struct zmq_send_recv_args {
1107
+ void *socket;
1108
+ zmq_msg_t *msg;
1109
+ int flags;
1110
+ int rc;
1111
+ };
1112
+
1113
+ static VALUE zmq_send_blocking (void* args_)
1114
+ {
1115
+ struct zmq_send_recv_args *send_args = (struct zmq_send_recv_args *)args_;
1116
+
1117
+ send_args->rc = zmq_send(send_args->socket, send_args->msg, send_args->flags);
1118
+
1119
+ return Qnil;
1120
+ }
1121
+ #endif
1122
+
1123
+ /*
1124
+ * call-seq:
1125
+ * socket.send(message, flags=0) -> true | false
1126
+ *
1127
+ * Queue the message referenced by the _msg_ argument to be send to the
1128
+ * _socket_. The _flags_ argument is a combination of the flags defined
1129
+ * below:
1130
+ *
1131
+ * [ZMQ::NOBLOCK] Specifies that the operation should be performed in non-blocking mode. If the message cannot be queued on the _socket_, the function shall fail and return _false_.
1132
+ * [ZMQ::SNDMORE] Specifies that the message being sent is a multi-part message, and that further message parts are to follow. Refer to the section regarding multi-part messages below for a detailed description.
1133
+ *
1134
+ * <b>NOTE:</b> A successful invocation of send() does not indicate that the
1135
+ * message has been transmitted to the network, only that it has been queued on
1136
+ * the socket and 0MQ has assumed responsibility for the message.
1137
+ *
1138
+ * == Multi-part messages
1139
+ * A 0MQ message is composed of 1 or more message parts. 0MQ ensures atomic
1140
+ * delivery of messages; peers shall receive either all <em>message parts</em> of a
1141
+ * message or none at all.
1142
+ *
1143
+ * The total number of message parts is unlimited.
1144
+ *
1145
+ * An application wishing to send a multi-part message does so by specifying the
1146
+ * ZMQ::SNDMORE flag to send(). The presence of this flag indicates to 0MQ
1147
+ * that the message being sent is a multi-part message and that more message
1148
+ * parts are to follow. When the application wishes to send the final message
1149
+ * part it does so by calling send() without the ZMQ::SNDMORE flag; this
1150
+ * indicates that no more message parts are to follow.
1151
+ *
1152
+ * This function returns _true_ if successful, _false_ if not.
1153
+ */
1154
+ static VALUE socket_send (int argc_, VALUE* argv_, VALUE self_)
1155
+ {
1156
+ VALUE msg_, flags_;
1157
+
1158
+ rb_scan_args (argc_, argv_, "11", &msg_, &flags_);
1159
+
1160
+ void * s;
1161
+ Data_Get_Struct (self_, void, s);
1162
+ Check_Socket (s);
1163
+
1164
+ Check_Type (msg_, T_STRING);
1165
+
1166
+ int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
1167
+
1168
+ zmq_msg_t msg;
1169
+ int rc = zmq_msg_init_size (&msg, RSTRING_LEN (msg_));
1170
+ if (rc != 0) {
1171
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1172
+ return Qnil;
1173
+ }
1174
+ memcpy (zmq_msg_data (&msg), RSTRING_PTR (msg_), RSTRING_LEN (msg_));
1175
+
1176
+ #ifdef HAVE_RUBY_INTERN_H
1177
+ if (!(flags & ZMQ_NOBLOCK)) {
1178
+ struct zmq_send_recv_args send_args;
1179
+ send_args.socket = s;
1180
+ send_args.msg = &msg;
1181
+ send_args.flags = flags;
1182
+ rb_thread_blocking_region (zmq_send_blocking, (void*) &send_args, NULL, NULL);
1183
+ rc = send_args.rc;
1184
+ }
1185
+ else
1186
+ #endif
1187
+ rc = zmq_send (s, &msg, flags);
1188
+ if (rc != 0 && zmq_errno () == EAGAIN) {
1189
+ rc = zmq_msg_close (&msg);
1190
+ assert (rc == 0);
1191
+ return Qfalse;
1192
+ }
1193
+
1194
+ if (rc != 0) {
1195
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1196
+ rc = zmq_msg_close (&msg);
1197
+ assert (rc == 0);
1198
+ return Qnil;
1199
+ }
1200
+
1201
+ rc = zmq_msg_close (&msg);
1202
+ assert (rc == 0);
1203
+ return Qtrue;
1204
+ }
1205
+
1206
+ #ifdef HAVE_RUBY_INTERN_H
1207
+ static VALUE zmq_recv_blocking (void* args_)
1208
+ {
1209
+ struct zmq_send_recv_args *recv_args = (struct zmq_send_recv_args *)args_;
1210
+
1211
+ recv_args->rc = zmq_recv(recv_args->socket, recv_args->msg, recv_args->flags);
1212
+
1213
+ return Qnil;
1214
+ }
1215
+ #endif
1216
+
1217
+ /*
1218
+ * call-seq:
1219
+ * socket.recv(flags=0) -> message | nil
1220
+ *
1221
+ * Receives a message from the _socket_. If there are no messages available
1222
+ * on the _socket_, the recv() function shall block until the request can be
1223
+ * satisfied. The _flags_ argument is a combination of the flags defined
1224
+ * below:
1225
+ *
1226
+ * [ZMQ::NOBLOCK] Specifies that the operation should be performed in non-blocking mode. If there are no messages available on the _socket_, the recv() function shall fail and return _nil_.
1227
+ *
1228
+ * == Multi-part messages
1229
+ * A 0MQ message is composed of 1 or more message parts. 0MQ ensures atomic
1230
+ * delivery of messages; peers shall receive either all <em>message parts</em> of a
1231
+ * message or none at all.
1232
+ *
1233
+ * The total number of message parts is unlimited.
1234
+ *
1235
+ * An application wishing to determine if a message is composed of multiple
1236
+ * parts does so by retrieving the value of the ZMQ::RCVMORE socket option on the
1237
+ * socket it is receiving the message from, using getsockopt(). If there are no
1238
+ * message parts to follow, or if the message is not composed of multiple parts,
1239
+ * ZMQ::RCVMORE shall report a value of false. Otherwise, ZMQ::RCVMORE shall
1240
+ * report a value of true, indicating that more message parts are to follow.
1241
+ */
1242
+ static VALUE socket_recv (int argc_, VALUE* argv_, VALUE self_)
1243
+ {
1244
+ VALUE flags_;
1245
+
1246
+ rb_scan_args (argc_, argv_, "01", &flags_);
1247
+
1248
+ void * s;
1249
+ Data_Get_Struct (self_, void, s);
1250
+ Check_Socket (s);
1251
+
1252
+ int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
1253
+
1254
+ zmq_msg_t msg;
1255
+ int rc = zmq_msg_init (&msg);
1256
+ assert (rc == 0);
1257
+
1258
+ #ifdef HAVE_RUBY_INTERN_H
1259
+ if (!(flags & ZMQ_NOBLOCK)) {
1260
+ struct zmq_send_recv_args recv_args;
1261
+ recv_args.socket = s;
1262
+ recv_args.msg = &msg;
1263
+ recv_args.flags = flags;
1264
+ rb_thread_blocking_region (zmq_recv_blocking, (void*) &recv_args, NULL, NULL);
1265
+ rc = recv_args.rc;
1266
+ }
1267
+ else
1268
+ #endif
1269
+ rc = zmq_recv (s, &msg, flags);
1270
+ if (rc != 0 && zmq_errno () == EAGAIN) {
1271
+ rc = zmq_msg_close (&msg);
1272
+ assert (rc == 0);
1273
+ return Qnil;
1274
+ }
1275
+
1276
+ if (rc != 0) {
1277
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1278
+ rc = zmq_msg_close (&msg);
1279
+ assert (rc == 0);
1280
+ return Qnil;
1281
+ }
1282
+
1283
+ VALUE message = rb_str_new ((char*) zmq_msg_data (&msg),
1284
+ zmq_msg_size (&msg));
1285
+ rc = zmq_msg_close (&msg);
1286
+ assert (rc == 0);
1287
+ return message;
1288
+ }
1289
+
1290
+ /*
1291
+ * call-seq:
1292
+ * socket.close() -> nil
1293
+ *
1294
+ * Destroys the 0MQ socket. All active connections on the socket shall be
1295
+ * terminated, and resources associated with the socket shall be released.
1296
+ * Any outstanding messages sent with send() but not yet physically sent
1297
+ * to the network shall be dropped. Likewise, any outstanding messages
1298
+ * physically received from the network but not yet received by the
1299
+ * application with recv() shall also be dropped.
1300
+ */
1301
+ static VALUE socket_close (VALUE self_)
1302
+ {
1303
+ void * s = NULL;
1304
+ Data_Get_Struct (self_, void, s);
1305
+ if (s != NULL) {
1306
+ int rc = zmq_close (s);
1307
+ if (rc != 0) {
1308
+ rb_raise (rb_eRuntimeError, "%s", zmq_strerror (zmq_errno ()));
1309
+ return Qnil;
1310
+ }
1311
+
1312
+ DATA_PTR (self_) = NULL;
1313
+ }
1314
+ return Qnil;
1315
+ }
1316
+
1317
+ void Init_zmq ()
1318
+ {
1319
+ VALUE zmq_module = rb_define_module ("ZMQ");
1320
+ rb_define_singleton_method (zmq_module, "version", module_version, 0);
1321
+ rb_define_singleton_method (zmq_module, "select", module_select, -1);
1322
+
1323
+ VALUE context_type = rb_define_class_under (zmq_module, "Context",
1324
+ rb_cObject);
1325
+ rb_define_alloc_func (context_type, context_alloc);
1326
+ rb_define_method (context_type, "initialize", context_initialize, -1);
1327
+ rb_define_method (context_type, "socket", context_socket, 1);
1328
+ rb_define_method (context_type, "close", context_close, 0);
1329
+
1330
+ socket_type = rb_define_class_under (zmq_module, "Socket", rb_cObject);
1331
+ rb_undef_alloc_func(socket_type);
1332
+ rb_define_method (socket_type, "getsockopt", socket_getsockopt, 1);
1333
+ rb_define_method (socket_type, "setsockopt", socket_setsockopt, 2);
1334
+ rb_define_method (socket_type, "bind", socket_bind, 1);
1335
+ rb_define_method (socket_type, "connect", socket_connect, 1);
1336
+ rb_define_method (socket_type, "send", socket_send, -1);
1337
+ rb_define_method (socket_type, "recv", socket_recv, -1);
1338
+ rb_define_method (socket_type, "close", socket_close, 0);
1339
+
1340
+ rb_define_const (zmq_module, "HWM", INT2NUM (ZMQ_HWM));
1341
+ rb_define_const (zmq_module, "SWAP", INT2NUM (ZMQ_SWAP));
1342
+ rb_define_const (zmq_module, "AFFINITY", INT2NUM (ZMQ_AFFINITY));
1343
+ rb_define_const (zmq_module, "IDENTITY", INT2NUM (ZMQ_IDENTITY));
1344
+ rb_define_const (zmq_module, "SUBSCRIBE", INT2NUM (ZMQ_SUBSCRIBE));
1345
+ rb_define_const (zmq_module, "UNSUBSCRIBE", INT2NUM (ZMQ_UNSUBSCRIBE));
1346
+ rb_define_const (zmq_module, "RATE", INT2NUM (ZMQ_RATE));
1347
+ rb_define_const (zmq_module, "RECOVERY_IVL", INT2NUM (ZMQ_RECOVERY_IVL));
1348
+ rb_define_const (zmq_module, "MCAST_LOOP", INT2NUM (ZMQ_MCAST_LOOP));
1349
+ rb_define_const (zmq_module, "SNDBUF", INT2NUM (ZMQ_SNDBUF));
1350
+ rb_define_const (zmq_module, "RCVBUF", INT2NUM (ZMQ_RCVBUF));
1351
+ rb_define_const (zmq_module, "SNDMORE", INT2NUM (ZMQ_SNDMORE));
1352
+ rb_define_const (zmq_module, "RCVMORE", INT2NUM (ZMQ_RCVMORE));
1353
+
1354
+ rb_define_const (zmq_module, "NOBLOCK", INT2NUM (ZMQ_NOBLOCK));
1355
+
1356
+ rb_define_const (zmq_module, "PAIR", INT2NUM (ZMQ_PAIR));
1357
+ rb_define_const (zmq_module, "SUB", INT2NUM (ZMQ_SUB));
1358
+ rb_define_const (zmq_module, "PUB", INT2NUM (ZMQ_PUB));
1359
+ rb_define_const (zmq_module, "REQ", INT2NUM (ZMQ_REQ));
1360
+ rb_define_const (zmq_module, "REP", INT2NUM (ZMQ_REP));
1361
+ rb_define_const (zmq_module, "XREQ", INT2NUM (ZMQ_XREQ));
1362
+ rb_define_const (zmq_module, "XREP", INT2NUM (ZMQ_XREP));
1363
+ rb_define_const (zmq_module, "UPSTREAM", INT2NUM (ZMQ_UPSTREAM));
1364
+ rb_define_const (zmq_module, "DOWNSTREAM", INT2NUM (ZMQ_DOWNSTREAM));
1365
+ }