zmq 1.0 → 2.0.7

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