rbczmq 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +23 -0
  2. data/.travis.yml +19 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +19 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +247 -0
  7. data/Rakefile +67 -0
  8. data/examples/loop.rb +109 -0
  9. data/examples/poller.rb +37 -0
  10. data/examples/pub_sub.rb +101 -0
  11. data/examples/push_pull.rb +104 -0
  12. data/examples/req_rep.rb +100 -0
  13. data/ext/czmq.tar.gz +0 -0
  14. data/ext/rbczmq/context.c +280 -0
  15. data/ext/rbczmq/context.h +26 -0
  16. data/ext/rbczmq/extconf.rb +138 -0
  17. data/ext/rbczmq/frame.c +401 -0
  18. data/ext/rbczmq/frame.h +24 -0
  19. data/ext/rbczmq/jruby.h +22 -0
  20. data/ext/rbczmq/loop.c +413 -0
  21. data/ext/rbczmq/loop.h +24 -0
  22. data/ext/rbczmq/message.c +620 -0
  23. data/ext/rbczmq/message.h +24 -0
  24. data/ext/rbczmq/poller.c +308 -0
  25. data/ext/rbczmq/poller.h +29 -0
  26. data/ext/rbczmq/pollitem.c +251 -0
  27. data/ext/rbczmq/pollitem.h +25 -0
  28. data/ext/rbczmq/rbczmq_ext.c +198 -0
  29. data/ext/rbczmq/rbczmq_ext.h +94 -0
  30. data/ext/rbczmq/rbczmq_prelude.h +22 -0
  31. data/ext/rbczmq/rubinius.h +24 -0
  32. data/ext/rbczmq/ruby18.h +43 -0
  33. data/ext/rbczmq/ruby19.h +15 -0
  34. data/ext/rbczmq/socket.c +1570 -0
  35. data/ext/rbczmq/socket.h +136 -0
  36. data/ext/rbczmq/timer.c +110 -0
  37. data/ext/rbczmq/timer.h +23 -0
  38. data/ext/zeromq.tar.gz +0 -0
  39. data/lib/rbczmq.rb +3 -0
  40. data/lib/zmq.rb +77 -0
  41. data/lib/zmq/context.rb +50 -0
  42. data/lib/zmq/default_handler.rb +16 -0
  43. data/lib/zmq/frame.rb +11 -0
  44. data/lib/zmq/handler.rb +76 -0
  45. data/lib/zmq/loop.rb +131 -0
  46. data/lib/zmq/message.rb +9 -0
  47. data/lib/zmq/poller.rb +22 -0
  48. data/lib/zmq/pollitem.rb +31 -0
  49. data/lib/zmq/socket.rb +125 -0
  50. data/lib/zmq/socket/dealer.rb +33 -0
  51. data/lib/zmq/socket/pair.rb +39 -0
  52. data/lib/zmq/socket/pub.rb +30 -0
  53. data/lib/zmq/socket/pull.rb +29 -0
  54. data/lib/zmq/socket/push.rb +32 -0
  55. data/lib/zmq/socket/rep.rb +37 -0
  56. data/lib/zmq/socket/req.rb +37 -0
  57. data/lib/zmq/socket/router.rb +38 -0
  58. data/lib/zmq/socket/sub.rb +27 -0
  59. data/lib/zmq/timer.rb +12 -0
  60. data/lib/zmq/version.rb +5 -0
  61. data/perf/pair.rb +7 -0
  62. data/perf/pair/local.rb +22 -0
  63. data/perf/pair/remote.rb +25 -0
  64. data/perf/pub_sub.rb +7 -0
  65. data/perf/pub_sub/local.rb +22 -0
  66. data/perf/pub_sub/remote.rb +25 -0
  67. data/perf/push_pull.rb +7 -0
  68. data/perf/push_pull/local.rb +21 -0
  69. data/perf/push_pull/remote.rb +25 -0
  70. data/perf/req_rep.rb +7 -0
  71. data/perf/req_rep/local.rb +35 -0
  72. data/perf/req_rep/remote.rb +28 -0
  73. data/perf/runner.rb +142 -0
  74. data/rbczmq.gemspec +22 -0
  75. data/test/helper.rb +21 -0
  76. data/test/socket/test_dealer_socket.rb +14 -0
  77. data/test/socket/test_pair_socket.rb +24 -0
  78. data/test/socket/test_pair_sockets.rb +74 -0
  79. data/test/socket/test_pub_socket.rb +17 -0
  80. data/test/socket/test_pub_sub_sockets.rb +87 -0
  81. data/test/socket/test_pull_socket.rb +17 -0
  82. data/test/socket/test_push_pull_sockets.rb +81 -0
  83. data/test/socket/test_push_socket.rb +17 -0
  84. data/test/socket/test_rep_socket.rb +25 -0
  85. data/test/socket/test_req_rep_sockets.rb +42 -0
  86. data/test/socket/test_req_socket.rb +27 -0
  87. data/test/socket/test_router_socket.rb +14 -0
  88. data/test/socket/test_routing.rb +66 -0
  89. data/test/socket/test_sub_socket.rb +17 -0
  90. data/test/test_context.rb +86 -0
  91. data/test/test_frame.rb +78 -0
  92. data/test/test_handler.rb +28 -0
  93. data/test/test_loop.rb +252 -0
  94. data/test/test_message.rb +201 -0
  95. data/test/test_poller.rb +154 -0
  96. data/test/test_pollitem.rb +78 -0
  97. data/test/test_socket.rb +403 -0
  98. data/test/test_threading.rb +34 -0
  99. data/test/test_timer.rb +37 -0
  100. data/test/test_zmq.rb +62 -0
  101. metadata +208 -0
@@ -0,0 +1,25 @@
1
+ #ifndef RBCZMQ_POLLITEM_H
2
+ #define RBCZMQ_POLLITEM_H
3
+
4
+ typedef struct {
5
+ VALUE socket;
6
+ VALUE io;
7
+ VALUE events;
8
+ VALUE handler;
9
+ zmq_pollitem_t *item;
10
+ } zmq_pollitem_wrapper;
11
+
12
+ #define ZmqAssertPollitem(obj) ZmqAssertType(obj, rb_cZmqPollitem, "ZMQ::Pollitem")
13
+ #define ZmqGetPollitem(obj) \
14
+ zmq_pollitem_wrapper *pollitem = NULL; \
15
+ ZmqAssertPollitem(obj); \
16
+ Data_Get_Struct(obj, zmq_pollitem_wrapper, pollitem); \
17
+ if (!pollitem) rb_raise(rb_eTypeError, "uninitialized ZMQ pollitem!");
18
+
19
+ VALUE rb_czmq_pollitem_coerce(VALUE pollable);
20
+ VALUE rb_czmq_pollitem_pollable(VALUE obj);
21
+ VALUE rb_czmq_pollitem_events(VALUE obj);
22
+
23
+ void _init_rb_czmq_pollitem();
24
+
25
+ #endif
@@ -0,0 +1,198 @@
1
+ #include <rbczmq_ext.h>
2
+
3
+ VALUE rb_mZmq;
4
+ VALUE rb_eZmqError;
5
+ VALUE rb_cZmqContext;
6
+
7
+ VALUE rb_cZmqSocket;
8
+ VALUE rb_cZmqPubSocket;
9
+ VALUE rb_cZmqSubSocket;
10
+ VALUE rb_cZmqPushSocket;
11
+ VALUE rb_cZmqPullSocket;
12
+ VALUE rb_cZmqRouterSocket;
13
+ VALUE rb_cZmqDealerSocket;
14
+ VALUE rb_cZmqRepSocket;
15
+ VALUE rb_cZmqReqSocket;
16
+ VALUE rb_cZmqPairSocket;
17
+
18
+ VALUE rb_cZmqFrame;
19
+ VALUE rb_cZmqMessage;
20
+ VALUE rb_cZmqLoop;
21
+ VALUE rb_cZmqTimer;
22
+ VALUE rb_cZmqPoller;
23
+ VALUE rb_cZmqPollitem;
24
+
25
+ st_table *frames_map = NULL;
26
+
27
+ #ifdef HAVE_RUBY_ENCODING_H
28
+ rb_encoding *binary_encoding;
29
+ #endif
30
+
31
+ /*
32
+ * call-seq:
33
+ * ZMQ.interrupted? => boolean
34
+ *
35
+ * Returns true if the process was interrupted by signal.
36
+ *
37
+ * === Examples
38
+ * ZMQ.interrupted? => boolean
39
+ *
40
+ */
41
+
42
+ static VALUE rb_czmq_m_interrupted_p(ZMQ_UNUSED VALUE obj)
43
+ {
44
+ return (zctx_interrupted == TRUE) ? Qtrue : Qfalse;
45
+ }
46
+
47
+ /*
48
+ * call-seq:
49
+ * ZMQ.version => Array
50
+ *
51
+ * Returns the libzmq version linked against.
52
+ *
53
+ * === Examples
54
+ * ZMQ.version => [2,1,11]
55
+ *
56
+ */
57
+
58
+ static VALUE rb_czmq_m_version(ZMQ_UNUSED VALUE obj)
59
+ {
60
+ int major, minor, patch;
61
+ zmq_version(&major, &minor, &patch);
62
+ return rb_ary_new3(3, INT2NUM(major), INT2NUM(minor), INT2NUM(patch));
63
+ }
64
+
65
+ /*
66
+ * call-seq:
67
+ * ZMQ.now => Fixnum
68
+ *
69
+ * Returns a current timestamp as a Fixnum
70
+ *
71
+ * === Examples
72
+ * ZMQ.now => 1323206405148
73
+ *
74
+ */
75
+
76
+ static VALUE rb_czmq_m_now(ZMQ_UNUSED VALUE obj)
77
+ {
78
+ return INT2NUM(zclock_time());
79
+ }
80
+
81
+ /*
82
+ * call-seq:
83
+ * ZMQ.log("msg") => nil
84
+ *
85
+ * Logs a timestamped message to stdout.
86
+ *
87
+ * === Examples
88
+ * ZMQ.log("msg") => nil # 11-12-06 21:20:55 msg
89
+ *
90
+ */
91
+
92
+ static VALUE rb_czmq_m_log(ZMQ_UNUSED VALUE obj, VALUE msg)
93
+ {
94
+ Check_Type(msg, T_STRING);
95
+ zclock_log(StringValueCStr(msg));
96
+ return Qnil;
97
+ }
98
+
99
+ /*
100
+ * call-seq:
101
+ * ZMQ.error => ZMQ::Error
102
+ *
103
+ * Returns the last known ZMQ error (if any) as a ZMQ::Error instance.
104
+ *
105
+ * === Examples
106
+ * ZMQ.error => ZMQ::Error or nil
107
+ *
108
+ */
109
+
110
+ static VALUE rb_czmq_m_error(ZMQ_UNUSED VALUE obj)
111
+ {
112
+ int err;
113
+ err = zmq_errno();
114
+ if (err == 0) return Qnil;
115
+ return rb_exc_new2(rb_eZmqError, zmq_strerror(zmq_errno()));
116
+ }
117
+
118
+ /*
119
+ * call-seq:
120
+ * ZMQ.errno => Fixnum
121
+ *
122
+ * Returns the last known ZMQ errno (if any) as a Fixnum.
123
+ *
124
+ * === Examples
125
+ * ZMQ.errno => 0
126
+ *
127
+ */
128
+
129
+ static VALUE rb_czmq_m_errno(ZMQ_UNUSED VALUE obj)
130
+ {
131
+ return INT2NUM(zmq_errno());
132
+ }
133
+
134
+ /*
135
+ * call-seq:
136
+ * ZMQ.interrupted! => nil
137
+ *
138
+ * Callback for Ruby signal handlers for terminating blocking functions and the reactor loop in libczmq.
139
+ *
140
+ * === Examples
141
+ * ZMQ.interrupted! => nil
142
+ *
143
+ */
144
+
145
+ static VALUE rb_czmq_m_interrupted_bang(ZMQ_UNUSED VALUE obj)
146
+ {
147
+ zctx_interrupted = 1;
148
+ return Qnil;
149
+ }
150
+
151
+ void Init_rbczmq_ext()
152
+ {
153
+ frames_map = st_init_numtable();
154
+
155
+ #ifdef HAVE_RUBY_ENCODING_H
156
+ binary_encoding = rb_enc_find("binary");
157
+ #endif
158
+
159
+ rb_mZmq = rb_define_module("ZMQ");
160
+
161
+ rb_eZmqError = rb_define_class_under(rb_mZmq, "Error", rb_eStandardError);
162
+
163
+ rb_define_module_function(rb_mZmq, "interrupted?", rb_czmq_m_interrupted_p, 0);
164
+ rb_define_module_function(rb_mZmq, "version", rb_czmq_m_version, 0);
165
+ rb_define_module_function(rb_mZmq, "now", rb_czmq_m_now, 0);
166
+ rb_define_module_function(rb_mZmq, "log", rb_czmq_m_log, 1);
167
+ rb_define_module_function(rb_mZmq, "error", rb_czmq_m_error, 0);
168
+ rb_define_module_function(rb_mZmq, "errno", rb_czmq_m_errno, 0);
169
+ rb_define_module_function(rb_mZmq, "interrupted!", rb_czmq_m_interrupted_bang, 0);
170
+
171
+ rb_define_const(rb_mZmq, "POLLIN", INT2NUM(ZMQ_POLLIN));
172
+ rb_define_const(rb_mZmq, "POLLOUT", INT2NUM(ZMQ_POLLOUT));
173
+ rb_define_const(rb_mZmq, "POLLERR", INT2NUM(ZMQ_POLLERR));
174
+
175
+ rb_define_const(rb_mZmq, "PAIR", INT2NUM(ZMQ_PAIR));
176
+ rb_define_const(rb_mZmq, "SUB", INT2NUM(ZMQ_SUB));
177
+ rb_define_const(rb_mZmq, "PUB", INT2NUM(ZMQ_PUB));
178
+ rb_define_const(rb_mZmq, "REQ", INT2NUM(ZMQ_REQ));
179
+ rb_define_const(rb_mZmq, "REP", INT2NUM(ZMQ_REP));
180
+ rb_define_const(rb_mZmq, "DEALER", INT2NUM(ZMQ_DEALER));
181
+ rb_define_const(rb_mZmq, "ROUTER", INT2NUM(ZMQ_ROUTER));
182
+ rb_define_const(rb_mZmq, "PUSH", INT2NUM(ZMQ_PUSH));
183
+ rb_define_const(rb_mZmq, "PULL", INT2NUM(ZMQ_PULL));
184
+
185
+ rb_define_const(rb_mZmq, "EFSM", INT2NUM(EFSM));
186
+ rb_define_const(rb_mZmq, "ENOCOMPATPROTO", INT2NUM(ENOCOMPATPROTO));
187
+ rb_define_const(rb_mZmq, "ETERM", INT2NUM(ETERM));
188
+ rb_define_const(rb_mZmq, "EMTHREAD", INT2NUM(EMTHREAD));
189
+
190
+ _init_rb_czmq_context();
191
+ _init_rb_czmq_socket();
192
+ _init_rb_czmq_frame();
193
+ _init_rb_czmq_message();
194
+ _init_rb_czmq_timer();
195
+ _init_rb_czmq_loop();
196
+ _init_rb_czmq_poller();
197
+ _init_rb_czmq_pollitem();
198
+ }
@@ -0,0 +1,94 @@
1
+ #ifndef RBCZMQ_EXT_H
2
+ #define RBCZMQ_EXT_H
3
+
4
+ #include <czmq.h>
5
+ #include "ruby.h"
6
+
7
+ /* Compiler specific */
8
+
9
+ #if defined(__GNUC__) && (__GNUC__ >= 3)
10
+ #define ZMQ_UNUSED __attribute__ ((unused))
11
+ #define ZMQ_NOINLINE __attribute__ ((noinline))
12
+ #else
13
+ #define ZMQ_UNUSED
14
+ #define ZMQ_NOINLINE
15
+ #endif
16
+
17
+ #include <rbczmq_prelude.h>
18
+
19
+ #define ZmqRaiseSysError() { \
20
+ printf("Sys error location: %s:%d\n", __FILE__,__LINE__); \
21
+ rb_sys_fail(zmq_strerror(zmq_errno())); \
22
+ }
23
+ #define ZmqAssertSysError() if (zmq_errno() != 0 && zmq_errno() != EAGAIN) ZmqRaiseSysError();
24
+ #define ZmqAssert(rc) \
25
+ if (rc == -1) { \
26
+ ZmqAssertSysError(); \
27
+ if (rc == ENOMEM) rb_memerror(); \
28
+ return Qfalse; \
29
+ }
30
+ #define ZmqAssertObjOnAlloc(obj, wrapper) \
31
+ if (obj == NULL) { \
32
+ xfree(wrapper); \
33
+ ZmqAssertSysError(); \
34
+ rb_memerror(); \
35
+ }
36
+ #define ZmqAssertType(obj, type, desc) \
37
+ if (!rb_obj_is_kind_of(obj,type)) \
38
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s): %s", rb_obj_classname(obj), desc, RSTRING_PTR(rb_obj_as_string(obj)));
39
+
40
+ extern VALUE rb_mZmq;
41
+ extern VALUE rb_eZmqError;
42
+ extern VALUE rb_cZmqContext;
43
+
44
+ extern VALUE rb_cZmqSocket;
45
+ extern VALUE rb_cZmqPubSocket;
46
+ extern VALUE rb_cZmqSubSocket;
47
+ extern VALUE rb_cZmqPushSocket;
48
+ extern VALUE rb_cZmqPullSocket;
49
+ extern VALUE rb_cZmqRouterSocket;
50
+ extern VALUE rb_cZmqDealerSocket;
51
+ extern VALUE rb_cZmqRepSocket;
52
+ extern VALUE rb_cZmqReqSocket;
53
+ extern VALUE rb_cZmqPairSocket;
54
+
55
+ extern VALUE rb_cZmqFrame;
56
+ extern VALUE rb_cZmqMessage;
57
+ extern VALUE rb_cZmqLoop;
58
+ extern VALUE rb_cZmqTimer;
59
+ extern VALUE rb_cZmqPoller;
60
+ extern VALUE rb_cZmqPollitem;
61
+
62
+ extern st_table *frames_map;
63
+
64
+ #include <context.h>
65
+ #include <socket.h>
66
+ #include <frame.h>
67
+ #include <message.h>
68
+ #include <loop.h>
69
+ #include <timer.h>
70
+ #include <poller.h>
71
+ #include <pollitem.h>
72
+
73
+ static inline char *rb_czmq_formatted_current_time()
74
+ {
75
+ time_t curtime = time (NULL);
76
+ struct tm *loctime = localtime(&curtime);
77
+ char *formatted;
78
+ formatted = (char*)xmalloc(20);
79
+ strftime(formatted, 20, "%y-%m-%d %H:%M:%S ", loctime);
80
+ return formatted;
81
+ }
82
+
83
+ struct nogvl_device_args {
84
+ int type;
85
+ #ifndef HAVE_RB_THREAD_BLOCKING_REGION
86
+ zctx_t *ctx;
87
+ #endif
88
+ zmq_sock_wrapper *in;
89
+ zmq_sock_wrapper *out;
90
+ int rc;
91
+ };
92
+ typedef struct nogvl_device_args nogvl_device_args_t;
93
+
94
+ #endif
@@ -0,0 +1,22 @@
1
+ #ifndef RBCZMQ_PRELUDE_H
2
+ #define RBCZMQ_PRELUDE_H
3
+
4
+ #ifndef RFLOAT_VALUE
5
+ #define RFLOAT_VALUE(v) (RFLOAT(v)->value)
6
+ #endif
7
+
8
+ #ifdef RUBINIUS
9
+ #include <rubinius.h>
10
+ #else
11
+ #ifdef JRUBY
12
+ #include <jruby.h>
13
+ #else
14
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
15
+ #include <ruby19.h>
16
+ #else
17
+ #include <ruby18.h>
18
+ #endif
19
+ #endif
20
+ #endif
21
+
22
+ #endif
@@ -0,0 +1,24 @@
1
+ #ifndef RBCZMQ_RUBINIUS_H
2
+ #define RBCZMQ_RUBINIUS_H
3
+
4
+ #define RSTRING_NOT_MODIFIED
5
+
6
+ #ifdef HAVE_RUBY_ENCODING_H
7
+ #include <ruby/st.h>
8
+ #include <ruby/encoding.h>
9
+ #include <ruby/io.h>
10
+ extern rb_encoding *binary_encoding;
11
+ #define ZmqEncode(str) rb_enc_associate(str, binary_encoding)
12
+ #else
13
+ #include "st.h"
14
+ #define ZmqEncode(str) str
15
+ #endif
16
+
17
+ #define TRAP_BEG
18
+ #define TRAP_END
19
+
20
+ #define ZMQ_DEFAULT_SOCKET_TIMEOUT Qnil
21
+
22
+ #define THREAD_PASS rb_thread_schedule();
23
+
24
+ #endif
@@ -0,0 +1,43 @@
1
+ #ifndef RBCZMQ_RUBY18_H
2
+ #define RBCZMQ_RUBY18_H
3
+
4
+ #define THREAD_PASS rb_thread_schedule();
5
+ #define ZmqEncode(str) str
6
+ #include "rubyio.h"
7
+ #include "rubysig.h"
8
+ #include "st.h"
9
+
10
+ #ifndef RSTRING_PTR
11
+ #define RSTRING_PTR(str) RSTRING(str)->ptr
12
+ #endif
13
+ #ifndef RSTRING_LEN
14
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
15
+ #endif
16
+
17
+ /*
18
+ * partial emulation of the 1.9 rb_thread_blocking_region under 1.8,
19
+ * this is enough for dealing with blocking I/O functions in the
20
+ * presence of threads.
21
+ */
22
+
23
+ #define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
24
+ typedef void rb_unblock_function_t(void *);
25
+ typedef VALUE rb_blocking_function_t(void *);
26
+ static VALUE
27
+ rb_thread_blocking_region(
28
+ rb_blocking_function_t *func, void *data1,
29
+ ZMQ_UNUSED rb_unblock_function_t *ubf,
30
+ ZMQ_UNUSED void *data2)
31
+ {
32
+ VALUE rv;
33
+ TRAP_BEG;
34
+ rv = func(data1);
35
+ TRAP_END;
36
+ return rv;
37
+ }
38
+
39
+ struct timeval rb_time_interval _((VALUE));
40
+
41
+ #define rb_errinfo() ruby_errinfo
42
+
43
+ #endif
@@ -0,0 +1,15 @@
1
+ #ifndef RBCZMQ_RUBY19_H
2
+ #define RBCZMQ_RUBY19_H
3
+
4
+ #include <ruby/encoding.h>
5
+ #include <ruby/io.h>
6
+ extern rb_encoding *binary_encoding;
7
+ #define ZmqEncode(str) rb_enc_associate(str, binary_encoding)
8
+ #ifndef THREAD_PASS
9
+ #define THREAD_PASS rb_thread_schedule();
10
+ #endif
11
+
12
+ #define TRAP_BEG
13
+ #define TRAP_END
14
+
15
+ #endif
@@ -0,0 +1,1570 @@
1
+ #include <rbczmq_ext.h>
2
+
3
+ /*
4
+ * :nodoc:
5
+ * Destroy the socket while the GIL is released - may block depending on socket linger value.
6
+ *
7
+ */
8
+ static VALUE rb_czmq_nogvl_zsocket_destroy(void *ptr)
9
+ {
10
+ zmq_sock_wrapper *sock = ptr;
11
+ errno = 0;
12
+ zsocket_destroy(sock->ctx, sock->socket);
13
+ return Qnil;
14
+ }
15
+
16
+ /*
17
+ * :nodoc:
18
+ * Free all resources for a socket - invoked by the lower level ZMQ::Socket#destroy as well as the GC callback (some
19
+ * regressions here still though).
20
+ *
21
+ */
22
+ void rb_czmq_free_sock(zmq_sock_wrapper *sock)
23
+ {
24
+ if (sock->ctx) {
25
+ rb_thread_blocking_region(rb_czmq_nogvl_zsocket_destroy, sock, RUBY_UBF_IO, 0);
26
+ if (zmq_errno() == ENOTSOCK) ZmqRaiseSysError();
27
+ sock->socket = NULL;
28
+ sock->flags |= ZMQ_SOCKET_DESTROYED;
29
+ }
30
+ }
31
+
32
+ /*
33
+ * :nodoc:
34
+ * GC mark callback
35
+ *
36
+ */
37
+ void rb_czmq_mark_sock(void *ptr)
38
+ {
39
+ zmq_sock_wrapper *sock = (zmq_sock_wrapper *)ptr;
40
+ if (sock){
41
+ if (sock->verbose)
42
+ zclock_log ("I: %s socket %p, context %p: GC mark", zsocket_type_str(sock->socket), sock, sock->ctx);
43
+ rb_gc_mark(sock->endpoint);
44
+ rb_gc_mark(sock->thread);
45
+ rb_gc_mark(sock->recv_timeout);
46
+ rb_gc_mark(sock->send_timeout);
47
+ }
48
+ }
49
+
50
+ /*
51
+ * :nodoc:
52
+ * GC free callback
53
+ *
54
+ */
55
+ void rb_czmq_free_sock_gc(void *ptr)
56
+ {
57
+ zmq_sock_wrapper *sock = (zmq_sock_wrapper *)ptr;
58
+ if (sock){
59
+ if (sock->verbose)
60
+ zclock_log ("I: %s socket %p, context %p: GC free", zsocket_type_str(sock->socket), sock, sock->ctx);
61
+ /*
62
+ XXX: cyclic dependency
63
+ #4 0x0000000100712524 in zsockopt_set_linger (linger=1, socket=<value temporarily unavailable, due to optimizations>) at zsockopt.c:288
64
+ if (sock->socket != NULL && !(sock->flags & ZMQ_SOCKET_DESTROYED)) rb_czmq_free_sock(sock);
65
+ */
66
+ #ifndef HAVE_RB_THREAD_BLOCKING_REGION
67
+ zlist_destroy(&(sock->str_buffer));
68
+ zlist_destroy(&(sock->frame_buffer));
69
+ zlist_destroy(&(sock->msg_buffer));
70
+ #endif
71
+ xfree(sock);
72
+ }
73
+ }
74
+
75
+ /*
76
+ * call-seq:
77
+ * sock.close => nil
78
+ *
79
+ * Closes a socket. The GC will take the same action if a socket object is not reachable anymore on the next GC cycle.
80
+ * This is a lower level API.
81
+ *
82
+ * === Examples
83
+ * sock.close => nil
84
+ *
85
+ */
86
+
87
+ static VALUE rb_czmq_socket_close(VALUE obj)
88
+ {
89
+ zmq_sock_wrapper *sock = NULL;
90
+ GetZmqSocket(obj);
91
+ ZmqSockGuardCrossThread(sock);
92
+ /* This is useless for production / real use cases as we can't query the state again OR assume
93
+ anything about the underlying connection. Merely doing the right thing. */
94
+ sock->state = ZMQ_SOCKET_PENDING;
95
+ rb_czmq_free_sock(sock);
96
+ return Qnil;
97
+ }
98
+
99
+ /*
100
+ * call-seq:
101
+ * sock.endpoint => String or nil
102
+ *
103
+ * Returns the endpoint this socket is currently connected to, if any.
104
+ *
105
+ * === Examples
106
+ * ctx = ZMQ::Context.new
107
+ * sock = ctx.socket(:PUSH)
108
+ * sock.endpoint => nil
109
+ * sock.bind("inproc://test")
110
+ * sock.endpoint => "inproc://test"
111
+ *
112
+ */
113
+
114
+ static VALUE rb_czmq_socket_endpoint(VALUE obj)
115
+ {
116
+ zmq_sock_wrapper *sock = NULL;
117
+ GetZmqSocket(obj);
118
+ return sock->endpoint;
119
+ }
120
+
121
+ /*
122
+ * call-seq:
123
+ * sock.state => String
124
+ *
125
+ * Returns the current socket state, one of ZMQ::Socket::PENDING, ZMQ::Socket::BOUND or ZMQ::Socket::CONNECTED
126
+ *
127
+ * === Examples
128
+ * ctx = ZMQ::Context.new
129
+ * sock = ctx.socket(:PUSH)
130
+ * sock.state => ZMQ::Socket::PENDING
131
+ * sock.bind("inproc://test")
132
+ * sock.state => ZMQ::Socket::BOUND
133
+ *
134
+ */
135
+
136
+ static VALUE rb_czmq_socket_state(VALUE obj)
137
+ {
138
+ zmq_sock_wrapper *sock = NULL;
139
+ GetZmqSocket(obj);
140
+ return INT2NUM(sock->state);
141
+ }
142
+
143
+ /*
144
+ * call-seq:
145
+ * sock.fd => Fixnum
146
+ *
147
+ * Returns a file descriptor reference for integrating this socket with an externel event loop or multiplexor.
148
+ * Edge-triggered notification of I/O state changes.
149
+ *
150
+ * === Examples
151
+ * ctx = ZMQ::Context.new
152
+ * sock = ctx.socket(:PUSH)
153
+ * sock.fd => -1
154
+ * sock.bind("inproc://test")
155
+ * sock.fd => 4
156
+ *
157
+ */
158
+
159
+ static VALUE rb_czmq_socket_fd(VALUE obj)
160
+ {
161
+ zmq_sock_wrapper *sock = NULL;
162
+ GetZmqSocket(obj);
163
+ if (sock->state == ZMQ_SOCKET_PENDING) return INT2NUM(-1);
164
+ return INT2NUM(zsockopt_fd(sock->socket));
165
+ }
166
+
167
+ /*
168
+ * :nodoc:
169
+ * Binds to an endpoint while the GIL is released.
170
+ *
171
+ */
172
+ VALUE rb_czmq_nogvl_socket_bind(void *ptr)
173
+ {
174
+ int rc;
175
+ struct nogvl_conn_args *args = ptr;
176
+ errno = 0;
177
+ zmq_sock_wrapper *socket = args->socket;
178
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
179
+ rc = zsocket_bind(socket->socket, args->endpoint);
180
+ #else
181
+ rc = zsocket_bind(socket->socket, args->endpoint);
182
+ #endif
183
+ return (VALUE)rc;
184
+ }
185
+
186
+ /*
187
+ * :nodoc:
188
+ * Connects to an endpoint while the GIL is released.
189
+ *
190
+ */
191
+ VALUE rb_czmq_nogvl_socket_connect(void *ptr)
192
+ {
193
+ int rc;
194
+ struct nogvl_conn_args *args = ptr;
195
+ errno = 0;
196
+ zmq_sock_wrapper *socket = args->socket;
197
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
198
+ rc = zsocket_connect(socket->socket, args->endpoint);
199
+ #else
200
+ rc = zsocket_connect(socket->socket, args->endpoint);
201
+ #endif
202
+ return (VALUE)rc;
203
+ }
204
+
205
+ /*
206
+ * call-seq:
207
+ * sock.bind("inproc://test") => Fixnum
208
+ *
209
+ * Binds to a given endpoint. When the port number is '*', attempts to bind to a free port. Always returns the port
210
+ * number on success.
211
+ *
212
+ * === Examples
213
+ * ctx = ZMQ::Context.new
214
+ * sock = ctx.socket(:PUSH)
215
+ * sock.bind("tcp://localhost:*") => 5432
216
+ *
217
+ */
218
+
219
+ static VALUE rb_czmq_socket_bind(VALUE obj, VALUE endpoint)
220
+ {
221
+ struct nogvl_conn_args args;
222
+ int rc;
223
+ zmq_sock_wrapper *sock = NULL;
224
+ GetZmqSocket(obj);
225
+ ZmqSockGuardCrossThread(sock);
226
+ Check_Type(endpoint, T_STRING);
227
+ args.socket = sock;
228
+ args.endpoint = StringValueCStr(endpoint);
229
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_socket_bind, (void *)&args, RUBY_UBF_IO, 0);
230
+ if (rc == -1) ZmqRaiseSysError();
231
+ if (sock->verbose)
232
+ zclock_log ("I: %s socket %p: bound \"%s\"", zsocket_type_str(sock->socket), obj, StringValueCStr(endpoint));
233
+ sock->state = ZMQ_SOCKET_BOUND;
234
+ sock->endpoint = rb_str_new4(endpoint);
235
+ return INT2NUM(rc);
236
+ }
237
+
238
+ /*
239
+ * call-seq:
240
+ * sock.connect("tcp://localhost:3456") => boolean
241
+ *
242
+ * Attempts to connect to a given endpoint.
243
+ *
244
+ * === Examples
245
+ * ctx = ZMQ::Context.new
246
+ * rep = ctx.socket(:REP)
247
+ * port = rep.bind("tcp://localhost:*") => 5432
248
+ * req = ctx.socket(:REQ)
249
+ * req.connect("tcp://localhost:#{port}") => true
250
+ *
251
+ */
252
+
253
+ static VALUE rb_czmq_socket_connect(VALUE obj, VALUE endpoint)
254
+ {
255
+ struct nogvl_conn_args args;
256
+ int rc;
257
+ zmq_sock_wrapper *sock = NULL;
258
+ GetZmqSocket(obj);
259
+ ZmqSockGuardCrossThread(sock);
260
+ Check_Type(endpoint, T_STRING);
261
+ args.socket = sock;
262
+ args.endpoint = StringValueCStr(endpoint);
263
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_socket_connect, (void *)&args, RUBY_UBF_IO, 0);
264
+ ZmqAssert(rc);
265
+ if (sock->verbose)
266
+ zclock_log ("I: %s socket %p: connected \"%s\"", zsocket_type_str(sock->socket), obj, StringValueCStr(endpoint));
267
+ sock->state = ZMQ_SOCKET_CONNECTED;
268
+ sock->endpoint = rb_str_new4(endpoint);
269
+ return Qtrue;
270
+ }
271
+
272
+ /*
273
+ * call-seq:
274
+ * sock.verbose = true => nil
275
+ *
276
+ * Let this socket be verbose - dumps a lot of data to stdout for debugging.
277
+ *
278
+ * === Examples
279
+ * ctx = ZMQ::Context.new
280
+ * sock = ctx.socket(:REP)
281
+ * sock.verbose = true => nil
282
+ *
283
+ */
284
+
285
+ static VALUE rb_czmq_socket_set_verbose(VALUE obj, VALUE level)
286
+ {
287
+ Bool vlevel;
288
+ zmq_sock_wrapper *sock = NULL;
289
+ GetZmqSocket(obj);
290
+ vlevel = (level == Qtrue) ? TRUE : FALSE;
291
+ sock->verbose = vlevel;
292
+ return Qnil;
293
+ }
294
+
295
+ /*
296
+ * :nodoc:
297
+ * Sends a raw string while the GIL is released.
298
+ *
299
+ */
300
+ static VALUE rb_czmq_nogvl_zstr_send(void *ptr)
301
+ {
302
+ struct nogvl_send_args *args = ptr;
303
+ errno = 0;
304
+ zmq_sock_wrapper *socket = args->socket;
305
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
306
+ return (VALUE)zstr_send(socket->socket, args->msg);
307
+ #else
308
+ if (rb_thread_alone()) return (VALUE)zstr_send_nowait(socket->socket, args->msg);
309
+ try_writable:
310
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLOUT) == ZMQ_POLLOUT) {
311
+ return (VALUE)zstr_send_nowait(socket->socket, args->msg);
312
+ } else {
313
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
314
+ goto try_writable;
315
+ }
316
+ #endif
317
+ }
318
+
319
+ /*
320
+ * :nodoc:
321
+ * Sends a raw string with the multi flag set while the GIL is released.
322
+ *
323
+ */
324
+ static VALUE rb_czmq_nogvl_zstr_sendm(void *ptr)
325
+ {
326
+ struct nogvl_send_args *args = ptr;
327
+ errno = 0;
328
+ zmq_sock_wrapper *socket = args->socket;
329
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
330
+ return (VALUE)zstr_sendm(socket->socket, args->msg);
331
+ #else
332
+ if (rb_thread_alone()) return (VALUE)zstr_sendm(socket->socket, args->msg);
333
+ try_writable:
334
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLOUT) == ZMQ_POLLOUT) {
335
+ return (VALUE)zstr_sendm(socket->socket, args->msg);
336
+ } else {
337
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
338
+ goto try_writable;
339
+ }
340
+ #endif
341
+ }
342
+
343
+ /*
344
+ * call-seq:
345
+ * sock.send("message") => boolean
346
+ *
347
+ * Sends a string to this ZMQ socket.
348
+ *
349
+ * === Examples
350
+ * ctx = ZMQ::Context.new
351
+ * sock = ctx.socket(:REQ)
352
+ * sock.connect("inproc://test")
353
+ * sock.send("message") => true
354
+ *
355
+ */
356
+
357
+ static VALUE rb_czmq_socket_send(VALUE obj, VALUE msg)
358
+ {
359
+ int rc;
360
+ struct nogvl_send_args args;
361
+ zmq_sock_wrapper *sock = NULL;
362
+ GetZmqSocket(obj);
363
+ ZmqAssertSocketNotPending(sock, "can only send on a bound or connected socket!");
364
+ ZmqSockGuardCrossThread(sock);
365
+ Check_Type(msg, T_STRING);
366
+ args.socket = sock;
367
+ args.msg = StringValueCStr(msg);
368
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_zstr_send, (void *)&args, RUBY_UBF_IO, 0);
369
+ ZmqAssert(rc);
370
+ if (sock->verbose)
371
+ zclock_log ("I: %s socket %p: send \"%s\"", zsocket_type_str(sock->socket), obj, StringValueCStr(msg));
372
+ return Qtrue;
373
+ }
374
+
375
+ /*
376
+ * call-seq:
377
+ * sock.sendm("message") => boolean
378
+ *
379
+ * Sends a string to this ZMQ socket, with a more flag set.
380
+ *
381
+ * === Examples
382
+ * ctx = ZMQ::Context.new
383
+ * sock = ctx.socket(:REQ)
384
+ * sock.connect("inproc://test")
385
+ * sock.sendm("mes") => true
386
+ * sock.sendm("sage") => true
387
+ *
388
+ */
389
+
390
+ static VALUE rb_czmq_socket_sendm(VALUE obj, VALUE msg)
391
+ {
392
+ int rc;
393
+ struct nogvl_send_args args;
394
+ zmq_sock_wrapper *sock = NULL;
395
+ GetZmqSocket(obj);
396
+ ZmqAssertSocketNotPending(sock, "can only send on a bound or connected socket!");
397
+ ZmqSockGuardCrossThread(sock);
398
+ Check_Type(msg, T_STRING);
399
+ args.socket = sock;
400
+ args.msg = StringValueCStr(msg);
401
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_zstr_sendm, (void *)&args, RUBY_UBF_IO, 0);
402
+ ZmqAssert(rc);
403
+ if (sock->verbose)
404
+ zclock_log ("I: %s socket %p: sendm \"%s\"", zsocket_type_str(sock->socket), sock->socket, StringValueCStr(msg));
405
+ return Qtrue;
406
+ }
407
+
408
+ /*
409
+ * :nodoc:
410
+ * Receives a raw string while the GIL is released.
411
+ *
412
+ */
413
+ static VALUE rb_czmq_nogvl_recv(void *ptr)
414
+ {
415
+ struct nogvl_recv_args *args = ptr;
416
+ errno = 0;
417
+ zmq_sock_wrapper *socket = args->socket;
418
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
419
+ return (VALUE)zstr_recv(socket->socket);
420
+ #else
421
+ if (zlist_size(socket->str_buffer) != 0)
422
+ return (VALUE)zlist_pop(socket->str_buffer);
423
+ try_readable:
424
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLIN) == ZMQ_POLLIN) {
425
+ do {
426
+ zlist_append(socket->str_buffer, zstr_recv_nowait(socket->socket));
427
+ } while (zmq_errno() != EAGAIN && zmq_errno() != EINTR);
428
+ return (VALUE)zlist_pop(socket->str_buffer);
429
+ } else {
430
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
431
+ goto try_readable;
432
+ }
433
+ #endif
434
+ }
435
+
436
+ /*
437
+ * call-seq:
438
+ * sock.recv => String or nil
439
+ *
440
+ * Receive a string from this ZMQ socket. May block depending on the socket type.
441
+ *
442
+ * === Examples
443
+ * ctx = ZMQ::Context.new
444
+ * sock = ctx.socket(:REP)
445
+ * sock.bind("inproc://test")
446
+ * sock.recv => "message"
447
+ *
448
+ */
449
+
450
+ static VALUE rb_czmq_socket_recv(VALUE obj)
451
+ {
452
+ char *str = NULL;
453
+ struct nogvl_recv_args args;
454
+ VALUE result = Qnil;
455
+ zmq_sock_wrapper *sock = NULL;
456
+ GetZmqSocket(obj);
457
+ ZmqAssertSocketNotPending(sock, "can only receive on a bound or connected socket!");
458
+ ZmqSockGuardCrossThread(sock);
459
+ args.socket = sock;
460
+ str = (char *)rb_thread_blocking_region(rb_czmq_nogvl_recv, (void *)&args, RUBY_UBF_IO, 0);
461
+ if (str == NULL) return result;
462
+ ZmqAssertSysError();
463
+ if (sock->verbose)
464
+ zclock_log ("I: %s socket %p: recv \"%s\"", zsocket_type_str(sock->socket), sock->socket, str);
465
+ result = ZmqEncode(rb_str_new2(str));
466
+ free(str);
467
+ return result;
468
+ }
469
+
470
+ /*
471
+ * call-seq:
472
+ * sock.recv_nonblock => String or nil
473
+ *
474
+ * Receive a string from this ZMQ socket. Does not block.
475
+ *
476
+ * === Examples
477
+ * ctx = ZMQ::Context.new
478
+ * sock = ctx.socket(:REP)
479
+ * sock.bind("inproc://test")
480
+ * sock.recv_nonblock => "message"
481
+ *
482
+ */
483
+
484
+ static VALUE rb_czmq_socket_recv_nonblock(VALUE obj)
485
+ {
486
+ char *str = NULL;
487
+ errno = 0;
488
+ VALUE result = Qnil;
489
+ zmq_sock_wrapper *sock = NULL;
490
+ GetZmqSocket(obj);
491
+ ZmqAssertSocketNotPending(sock, "can only receive on a bound or connected socket!");
492
+ ZmqSockGuardCrossThread(sock);
493
+ str = zstr_recv_nowait(sock->socket);
494
+ if (str == NULL) return result;
495
+ ZmqAssertSysError();
496
+ if (sock->verbose)
497
+ zclock_log ("I: %s socket %p: recv_nonblock \"%s\"", zsocket_type_str(sock->socket), sock->socket, str);
498
+ result = ZmqEncode(rb_str_new2(str));
499
+ free(str);
500
+ return result;
501
+ }
502
+
503
+ /*
504
+ * :nodoc:
505
+ * Sends a frame while the GIL is released.
506
+ *
507
+ */
508
+ static VALUE rb_czmq_nogvl_send_frame(void *ptr)
509
+ {
510
+ struct nogvl_send_frame_args *args = ptr;
511
+ errno = 0;
512
+ zmq_sock_wrapper *socket = args->socket;
513
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
514
+ return (VALUE)zframe_send(&(args->frame), socket->socket, args->flags);
515
+ #else
516
+ if (rb_thread_alone()) return (VALUE)zframe_send(&(args->frame), socket->socket, args->flags);
517
+ try_writable:
518
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLOUT) == ZMQ_POLLOUT) {
519
+ return (VALUE)zframe_send(&(args->frame), socket->socket, args->flags);
520
+ } else {
521
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
522
+ goto try_writable;
523
+ }
524
+ #endif
525
+ }
526
+
527
+ /*
528
+ * call-seq:
529
+ * sock.send_frame(frame) => nil
530
+ *
531
+ * Sends a ZMQ::Frame instance to this socket.
532
+ *
533
+ * === Examples
534
+ * ctx = ZMQ::Context.new
535
+ * sock = ctx.socket(:REP)
536
+ * sock.bind("inproc://test")
537
+ * frame = ZMQ::Frame("frame")
538
+ * sock.send_frame(frame) => nil
539
+ * frame = ZMQ::Frame("multi")
540
+ * sock.send_frame(frame, ZMQ::Frame::MORE)
541
+ *
542
+ */
543
+
544
+ static VALUE rb_czmq_socket_send_frame(int argc, VALUE *argv, VALUE obj)
545
+ {
546
+ struct nogvl_send_frame_args args;
547
+ VALUE frame_obj;
548
+ VALUE flags;
549
+ char print_prefix[255];
550
+ char *cur_time = NULL;
551
+ zframe_t *print_frame = NULL;
552
+ int rc, flgs;
553
+ zmq_sock_wrapper *sock = NULL;
554
+ GetZmqSocket(obj);
555
+ ZmqAssertSocketNotPending(sock, "can only send on a bound or connected socket!");
556
+ ZmqSockGuardCrossThread(sock);
557
+ rb_scan_args(argc, argv, "11", &frame_obj, &flags);
558
+ ZmqGetFrame(frame_obj);
559
+
560
+ if (NIL_P(flags)) {
561
+ flgs = 0;
562
+ } else {
563
+ if (SYMBOL_P(flags)) flags = rb_const_get_at(rb_cZmqFrame, rb_to_id(flags));
564
+ Check_Type(flags, T_FIXNUM);
565
+ flgs = FIX2INT(flags);
566
+ }
567
+
568
+ if (sock->verbose) {
569
+ cur_time = rb_czmq_formatted_current_time();
570
+ print_frame = (flgs & ZFRAME_REUSE) ? frame : zframe_dup(frame);
571
+ }
572
+ args.socket = sock;
573
+ args.frame = frame;
574
+ args.flags = flgs;
575
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_send_frame, (void *)&args, RUBY_UBF_IO, 0);
576
+ ZmqAssert(rc);
577
+ if (sock->verbose) ZmqDumpFrame("send_frame", print_frame);
578
+ return Qtrue;
579
+ }
580
+
581
+ /*
582
+ * :nodoc:
583
+ * Sends a message while the GIL is released.
584
+ *
585
+ */
586
+ static VALUE rb_czmq_nogvl_send_message(void *ptr)
587
+ {
588
+ struct nogvl_send_message_args *args = ptr;
589
+ zmq_sock_wrapper *socket = args->socket;
590
+ errno = 0;
591
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
592
+ zmsg_send(&(args->message), socket->socket);
593
+ #else
594
+ if (rb_thread_alone()) {
595
+ zmsg_send(&(args->message), socket->socket);
596
+ return Qnil;
597
+ }
598
+ try_writable:
599
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLOUT) == ZMQ_POLLOUT) {
600
+ zmsg_send(&(args->message), socket->socket);
601
+ } else {
602
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
603
+ goto try_writable;
604
+ }
605
+ #endif
606
+ return Qnil;
607
+ }
608
+
609
+ /*
610
+ * call-seq:
611
+ * sock.send_message(msg) => nil
612
+ *
613
+ * Sends a ZMQ::Message instance to this socket.
614
+ *
615
+ * === Examples
616
+ * ctx = ZMQ::Context.new
617
+ * sock = ctx.socket(:REP)
618
+ * sock.bind("inproc://test")
619
+ * msg = ZMQ::Message.new
620
+ * msg.push ZMQ::Frame("header")
621
+ * sock.send_message(msg) => nil
622
+ *
623
+ */
624
+
625
+ static VALUE rb_czmq_socket_send_message(VALUE obj, VALUE message_obj)
626
+ {
627
+ struct nogvl_send_message_args args;
628
+ zmsg_t *print_message = NULL;
629
+ zmq_sock_wrapper *sock = NULL;
630
+ GetZmqSocket(obj);
631
+ ZmqAssertSocketNotPending(sock, "can only send on a bound or connected socket!");
632
+ ZmqSockGuardCrossThread(sock);
633
+ ZmqGetMessage(message_obj);
634
+ if (sock->verbose) print_message = zmsg_dup(message->message);
635
+ args.socket = sock;
636
+ args.message = message->message;
637
+ rb_thread_blocking_region(rb_czmq_nogvl_send_message, (void *)&args, RUBY_UBF_IO, 0);
638
+ message->flags |= ZMQ_MESSAGE_DESTROYED;
639
+ if (sock->verbose) ZmqDumpMessage("send_message", print_message);
640
+ return Qnil;
641
+ }
642
+
643
+ /*
644
+ * :nodoc:
645
+ * Receives a frame while the GIL is released.
646
+ *
647
+ */
648
+ static VALUE rb_czmq_nogvl_recv_frame(void *ptr)
649
+ {
650
+ struct nogvl_recv_args *args = ptr;
651
+ errno = 0;
652
+ zmq_sock_wrapper *socket = args->socket;
653
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
654
+ return (VALUE)zframe_recv(socket->socket);
655
+ #else
656
+ if (zlist_size(socket->frame_buffer) != 0)
657
+ return (VALUE)zlist_pop(socket->frame_buffer);
658
+ try_readable:
659
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLIN) == ZMQ_POLLIN) {
660
+ do {
661
+ zlist_append(socket->frame_buffer, zframe_recv_nowait(socket->socket));
662
+ } while (zmq_errno() != EAGAIN && zmq_errno() != EINTR);
663
+ return (VALUE)zlist_pop(socket->frame_buffer);
664
+ } else {
665
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
666
+ goto try_readable;
667
+ }
668
+ #endif
669
+ }
670
+
671
+ /*
672
+ * call-seq:
673
+ * sock.recv_frame => ZMQ::Frame or nil
674
+ *
675
+ * Receives a ZMQ frame from this socket.
676
+ *
677
+ * === Examples
678
+ * ctx = ZMQ::Context.new
679
+ * sock = ctx.socket(:REP)
680
+ * sock.bind("inproc://test")
681
+ * sock.recv_frame => ZMQ::Frame or nil
682
+ *
683
+ */
684
+
685
+ static VALUE rb_czmq_socket_recv_frame(VALUE obj)
686
+ {
687
+ zframe_t *frame = NULL;
688
+ struct nogvl_recv_args args;
689
+ char print_prefix[255];
690
+ char *cur_time = NULL;
691
+ zmq_sock_wrapper *sock = NULL;
692
+ GetZmqSocket(obj);
693
+ ZmqAssertSocketNotPending(sock, "can only receive on a bound or connected socket!");
694
+ ZmqSockGuardCrossThread(sock);
695
+ args.socket = sock;
696
+ frame = (zframe_t *)rb_thread_blocking_region(rb_czmq_nogvl_recv_frame, (void *)&args, RUBY_UBF_IO, 0);
697
+ if (frame == NULL) return Qnil;
698
+ if (sock->verbose) {
699
+ cur_time = rb_czmq_formatted_current_time();
700
+ ZmqDumpFrame("recv_frame", frame);
701
+ }
702
+ return rb_czmq_alloc_frame(frame);
703
+ }
704
+
705
+ /*
706
+ * call-seq:
707
+ * sock.recv_frame_nonblock => ZMQ::Frame or nil
708
+ *
709
+ * Receives a ZMQ frame from this socket. Does not block
710
+ *
711
+ * === Examples
712
+ * ctx = ZMQ::Context.new
713
+ * sock = ctx.socket(:REP)
714
+ * sock.bind("inproc://test")
715
+ * sock.recv_frame_nonblock => ZMQ::Frame or nil
716
+ *
717
+ */
718
+
719
+ static VALUE rb_czmq_socket_recv_frame_nonblock(VALUE obj)
720
+ {
721
+ zframe_t *frame = NULL;
722
+ char print_prefix[255];
723
+ char *cur_time = NULL;
724
+ errno = 0;
725
+ zmq_sock_wrapper *sock = NULL;
726
+ GetZmqSocket(obj);
727
+ ZmqAssertSocketNotPending(sock, "can only receive on a bound or connected socket!");
728
+ ZmqSockGuardCrossThread(sock);
729
+ frame = zframe_recv_nowait(sock->socket);
730
+ if (frame == NULL) return Qnil;
731
+ if (sock->verbose) {
732
+ cur_time = rb_czmq_formatted_current_time();
733
+ ZmqDumpFrame("recv_frame_nonblock", frame);
734
+ }
735
+ return rb_czmq_alloc_frame(frame);
736
+ }
737
+
738
+ /*
739
+ * :nodoc:
740
+ * Receives a message while the GIL is released.
741
+ *
742
+ */
743
+ static VALUE rb_czmq_nogvl_recv_message(void *ptr)
744
+ {
745
+ struct nogvl_recv_args *args = ptr;
746
+ errno = 0;
747
+ zmq_sock_wrapper *socket = args->socket;
748
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
749
+ return (VALUE)zmsg_recv(socket->socket);
750
+ #else
751
+ if (zlist_size(socket->msg_buffer) != 0)
752
+ return (VALUE)zlist_pop(socket->msg_buffer);
753
+ try_readable:
754
+ if ((zsockopt_events(socket->socket) & ZMQ_POLLIN) == ZMQ_POLLIN) {
755
+ do {
756
+ zlist_append(socket->msg_buffer, zmsg_recv(socket->socket));
757
+ } while (zmq_errno() != EAGAIN && zmq_errno() != EINTR);
758
+ return (VALUE)zlist_pop(socket->msg_buffer);
759
+ } else {
760
+ rb_thread_wait_fd(zsockopt_fd(socket->socket));
761
+ goto try_readable;
762
+ }
763
+ #endif
764
+ }
765
+
766
+ /*
767
+ * call-seq:
768
+ * sock.recv_message => ZMQ::Message or nil
769
+ *
770
+ * Receives a ZMQ message from this socket.
771
+ *
772
+ * === Examples
773
+ * ctx = ZMQ::Context.new
774
+ * sock = ctx.socket(:REP)
775
+ * sock.bind("inproc://test")
776
+ * sock.recv_message => ZMQ::Message or nil
777
+ *
778
+ */
779
+
780
+ static VALUE rb_czmq_socket_recv_message(VALUE obj)
781
+ {
782
+ zmsg_t *message = NULL;
783
+ struct nogvl_recv_args args;
784
+ zmq_sock_wrapper *sock = NULL;
785
+ GetZmqSocket(obj);
786
+ ZmqAssertSocketNotPending(sock, "can only receive on a bound or connected socket!");
787
+ ZmqSockGuardCrossThread(sock);
788
+ args.socket = sock;
789
+ message = (zmsg_t *)rb_thread_blocking_region(rb_czmq_nogvl_recv_message, (void *)&args, RUBY_UBF_IO, 0);
790
+ if (message == NULL) return Qnil;
791
+ if (sock->verbose) ZmqDumpMessage("recv_message", message);
792
+ return rb_czmq_alloc_message(message);
793
+ }
794
+
795
+ /*
796
+ * call-seq:
797
+ * sock.recv_timeout = 5 => nil
798
+ *
799
+ * Sets a receive timeout for this socket.
800
+ *
801
+ * === Examples
802
+ * ctx = ZMQ::Context.new
803
+ * sock = ctx.socket(:REP)
804
+ * sock.recv_timeout = 5 => nil
805
+ *
806
+ */
807
+
808
+ static VALUE rb_czmq_socket_set_recv_timeout(VALUE obj, VALUE timeout)
809
+ {
810
+ zmq_sock_wrapper *sock = NULL;
811
+ GetZmqSocket(obj);
812
+ if (TYPE(timeout) != T_FIXNUM && TYPE(timeout) != T_FLOAT) rb_raise(rb_eTypeError, "wrong timeout type %s (expected Fixnum or Float)", RSTRING_PTR(rb_obj_as_string(timeout)));
813
+ sock->recv_timeout = timeout;
814
+ return Qnil;
815
+ }
816
+
817
+ /*
818
+ * call-seq:
819
+ * sock.recv_timeout => Fixnum or nil
820
+ *
821
+ * Returns the recv timeout currently associated with this socket.
822
+ *
823
+ * === Examples
824
+ * ctx = ZMQ::Context.new
825
+ * sock = ctx.socket(:REP)
826
+ * sock.recv_timeout = 5
827
+ * sock.recv_timeout => 5
828
+ *
829
+ */
830
+
831
+ static VALUE rb_czmq_socket_recv_timeout(VALUE obj)
832
+ {
833
+ zmq_sock_wrapper *sock = NULL;
834
+ GetZmqSocket(obj);
835
+ return sock->recv_timeout;
836
+ }
837
+
838
+ /*
839
+ * call-seq:
840
+ * sock.send_timeout = 5 => nil
841
+ *
842
+ * Sets a send timeout for this socket.
843
+ *
844
+ * === Examples
845
+ * ctx = ZMQ::Context.new
846
+ * sock = ctx.socket(:REP)
847
+ * sock.send_timeout = 5 => nil
848
+ *
849
+ */
850
+
851
+ static VALUE rb_czmq_socket_set_send_timeout(VALUE obj, VALUE timeout)
852
+ {
853
+ zmq_sock_wrapper *sock = NULL;
854
+ GetZmqSocket(obj);
855
+ if (TYPE(timeout) != T_FIXNUM && TYPE(timeout) != T_FLOAT) rb_raise(rb_eTypeError, "wrong timeout type %s (expected Fixnum or Float)", RSTRING_PTR(rb_obj_as_string(timeout)));
856
+ sock->send_timeout = timeout;
857
+ return Qnil;
858
+ }
859
+
860
+ /*
861
+ * call-seq:
862
+ * sock.send_timeout => Fixnum or nil
863
+ *
864
+ * Returns the send timeout currently associated with this socket.
865
+ *
866
+ * === Examples
867
+ * ctx = ZMQ::Context.new
868
+ * sock = ctx.socket(:REP)
869
+ * sock.send_timeout = 5
870
+ * sock.send_timeout => 5
871
+ *
872
+ */
873
+
874
+ static VALUE rb_czmq_socket_send_timeout(VALUE obj)
875
+ {
876
+ zmq_sock_wrapper *sock = NULL;
877
+ GetZmqSocket(obj);
878
+ return sock->send_timeout;
879
+ }
880
+
881
+ /*
882
+ * call-seq:
883
+ * sock.hwm => Fixnum
884
+ *
885
+ * Returns the socket HWM (High Water Mark) value.
886
+ *
887
+ * === Examples
888
+ * ctx = ZMQ::Context.new
889
+ * sock = ctx.socket(:REP)
890
+ * sock.hwm => 0
891
+ *
892
+ */
893
+
894
+ static VALUE rb_czmq_socket_opt_hwm(VALUE obj)
895
+ {
896
+ zmq_sock_wrapper *sock = NULL;
897
+ GetZmqSocket(obj);
898
+ return INT2NUM(zsockopt_hwm(sock->socket));
899
+ }
900
+
901
+ /*
902
+ * call-seq:
903
+ * sock.hwm = 100 => nil
904
+ *
905
+ * Sets the socket HWM (High Water Mark() value.
906
+ *
907
+ * === Examples
908
+ * ctx = ZMQ::Context.new
909
+ * sock = ctx.socket(:REP)
910
+ * sock.hwm = 100 => nil
911
+ * sock.hwm => 100
912
+ *
913
+ */
914
+
915
+ static VALUE rb_czmq_socket_set_opt_hwm(VALUE obj, VALUE value)
916
+ {
917
+ zmq_sock_wrapper *sock = NULL;
918
+ ZmqSetSockOpt(obj, zsockopt_set_hwm, "HWM", value);
919
+ }
920
+
921
+ /*
922
+ * call-seq:
923
+ * sock.swap => Fixnum
924
+ *
925
+ * Returns the socket SWAP value.
926
+ *
927
+ * === Examples
928
+ * ctx = ZMQ::Context.new
929
+ * sock = ctx.socket(:REP)
930
+ * sock.swap => 0
931
+ *
932
+ */
933
+
934
+ static VALUE rb_czmq_socket_opt_swap(VALUE obj)
935
+ {
936
+ zmq_sock_wrapper *sock = NULL;
937
+ GetZmqSocket(obj);
938
+ return INT2NUM(zsockopt_swap(sock->socket));
939
+ }
940
+
941
+ /*
942
+ * call-seq:
943
+ * sock.swap = 100 => nil
944
+ *
945
+ * Sets the socket SWAP value.
946
+ *
947
+ * === Examples
948
+ * ctx = ZMQ::Context.new
949
+ * sock = ctx.socket(:REP)
950
+ * sock.swap = 100 => nil
951
+ *
952
+ */
953
+
954
+ static VALUE rb_czmq_socket_set_opt_swap(VALUE obj, VALUE value)
955
+ {
956
+ zmq_sock_wrapper *sock = NULL;
957
+ ZmqSetSockOpt(obj, zsockopt_set_swap, "SWAP", value);
958
+ }
959
+
960
+ /*
961
+ * call-seq:
962
+ * sock.affinity => Fixnum
963
+ *
964
+ * Returns the socket AFFINITY value.
965
+ *
966
+ * === Examples
967
+ * ctx = ZMQ::Context.new
968
+ * sock = ctx.socket(:REP)
969
+ * sock.affinity => 0
970
+ *
971
+ */
972
+
973
+ static VALUE rb_czmq_socket_opt_affinity(VALUE obj)
974
+ {
975
+ zmq_sock_wrapper *sock = NULL;
976
+ GetZmqSocket(obj);
977
+ return INT2NUM(zsockopt_affinity(sock->socket));
978
+ }
979
+
980
+ /*
981
+ * call-seq:
982
+ * sock.affinity = 1 => nil
983
+ *
984
+ * Sets the socket AFFINITY value.
985
+ *
986
+ * === Examples
987
+ * ctx = ZMQ::Context.new
988
+ * sock = ctx.socket(:REP)
989
+ * sock.affinity = 1 => nil
990
+ *
991
+ */
992
+
993
+ static VALUE rb_czmq_socket_set_opt_affinity(VALUE obj, VALUE value)
994
+ {
995
+ zmq_sock_wrapper *sock = NULL;
996
+ ZmqSetSockOpt(obj, zsockopt_set_affinity, "AFFINITY", value);
997
+ }
998
+
999
+ /*
1000
+ * call-seq:
1001
+ * sock.rate => Fixnum
1002
+ *
1003
+ * Returns the socket RATE value.
1004
+ *
1005
+ * === Examples
1006
+ * ctx = ZMQ::Context.new
1007
+ * sock = ctx.socket(:REP)
1008
+ * sock.rate => 40000
1009
+ *
1010
+ */
1011
+
1012
+ static VALUE rb_czmq_socket_opt_rate(VALUE obj)
1013
+ {
1014
+ zmq_sock_wrapper *sock = NULL;
1015
+ GetZmqSocket(obj);
1016
+ return INT2NUM(zsockopt_rate(sock->socket));
1017
+ }
1018
+
1019
+ /*
1020
+ * call-seq:
1021
+ * sock.rate = 50000 => nil
1022
+ *
1023
+ * Sets the socket RATE value.
1024
+ *
1025
+ * === Examples
1026
+ * ctx = ZMQ::Context.new
1027
+ * sock = ctx.socket(:REP)
1028
+ * sock.rate = 50000 => nil
1029
+ *
1030
+ */
1031
+
1032
+ static VALUE rb_czmq_socket_set_opt_rate(VALUE obj, VALUE value)
1033
+ {
1034
+ zmq_sock_wrapper *sock = NULL;
1035
+ ZmqSetSockOpt(obj, zsockopt_set_rate, "RATE", value);
1036
+ }
1037
+
1038
+ /*
1039
+ * call-seq:
1040
+ * sock.recovery_ivl => Fixnum
1041
+ *
1042
+ * Returns the socket RECOVERY_IVL value.
1043
+ *
1044
+ * === Examples
1045
+ * ctx = ZMQ::Context.new
1046
+ * sock = ctx.socket(:REP)
1047
+ * sock.recovery_ivl => 10
1048
+ *
1049
+ */
1050
+
1051
+ static VALUE rb_czmq_socket_opt_recovery_ivl(VALUE obj)
1052
+ {
1053
+ zmq_sock_wrapper *sock = NULL;
1054
+ GetZmqSocket(obj);
1055
+ return INT2NUM(zsockopt_recovery_ivl(sock->socket));
1056
+ }
1057
+
1058
+ /*
1059
+ * call-seq:
1060
+ * sock.recovery_ivl = 20 => nil
1061
+ *
1062
+ * Sets the socket RECOVERY_IVL value.
1063
+ *
1064
+ * === Examples
1065
+ * ctx = ZMQ::Context.new
1066
+ * sock = ctx.socket(:REP)
1067
+ * sock.recovery_ivl = 20 => nil
1068
+ *
1069
+ */
1070
+
1071
+ static VALUE rb_czmq_socket_set_opt_recovery_ivl(VALUE obj, VALUE value)
1072
+ {
1073
+ zmq_sock_wrapper *sock = NULL;
1074
+ ZmqSetSockOpt(obj, zsockopt_set_recovery_ivl, "RECOVERY_IVL", value);
1075
+ }
1076
+
1077
+ /*
1078
+ * call-seq:
1079
+ * sock.recovery_ivl_msec => Fixnum
1080
+ *
1081
+ * Returns the socket RECOVERY_IVL_MSEC value.
1082
+ *
1083
+ * === Examples
1084
+ * ctx = ZMQ::Context.new
1085
+ * sock = ctx.socket(:REP)
1086
+ * sock.recovery_ivl_msec => -1
1087
+ *
1088
+ */
1089
+
1090
+ static VALUE rb_czmq_socket_opt_recovery_ivl_msec(VALUE obj)
1091
+ {
1092
+ zmq_sock_wrapper *sock = NULL;
1093
+ GetZmqSocket(obj);
1094
+ return INT2NUM(zsockopt_recovery_ivl_msec(sock->socket));
1095
+ }
1096
+
1097
+ /*
1098
+ * call-seq:
1099
+ * sock.recovery_ivl_msec = 20 => nil
1100
+ *
1101
+ * Sets the socket RECOVERY_IVL_MSEC value.
1102
+ *
1103
+ * === Examples
1104
+ * ctx = ZMQ::Context.new
1105
+ * sock = ctx.socket(:REP)
1106
+ * sock.recovery_ivl_msec = 20 => nil
1107
+ *
1108
+ */
1109
+
1110
+ static VALUE rb_czmq_socket_set_opt_recovery_ivl_msec(VALUE obj, VALUE value)
1111
+ {
1112
+ zmq_sock_wrapper *sock = NULL;
1113
+ ZmqSetSockOpt(obj, zsockopt_set_recovery_ivl_msec, "RECOVERY_IVL_MSEC", value);
1114
+ }
1115
+
1116
+ /*
1117
+ * call-seq:
1118
+ * sock.mcast_loop? => boolean
1119
+ *
1120
+ * Returns the socket MCAST_LOOP status.
1121
+ *
1122
+ * === Examples
1123
+ * ctx = ZMQ::Context.new
1124
+ * sock = ctx.socket(:REP)
1125
+ * sock.mcast_loop? => true
1126
+ *
1127
+ */
1128
+
1129
+ static VALUE rb_czmq_socket_opt_mcast_loop(VALUE obj)
1130
+ {
1131
+ zmq_sock_wrapper *sock = NULL;
1132
+ GetZmqSocket(obj);
1133
+ return (zsockopt_mcast_loop(sock->socket) == 1) ? Qtrue : Qfalse;
1134
+ }
1135
+
1136
+ /*
1137
+ * call-seq:
1138
+ * sock.mcast_loop = false => nil
1139
+ *
1140
+ * Sets the socket MCAST_LOOP value.
1141
+ *
1142
+ * === Examples
1143
+ * ctx = ZMQ::Context.new
1144
+ * sock = ctx.socket(:REP)
1145
+ * sock.mcast_loop = false => nil
1146
+ *
1147
+ */
1148
+
1149
+ static VALUE rb_czmq_socket_set_opt_mcast_loop(VALUE obj, VALUE value)
1150
+ {
1151
+ zmq_sock_wrapper *sock = NULL;
1152
+ ZmqSetBooleanSockOpt(obj, zsockopt_set_mcast_loop, "MCAST_LOOP", value);
1153
+ }
1154
+
1155
+ /*
1156
+ * call-seq:
1157
+ * sock.sndbuf => Fixnum
1158
+ *
1159
+ * Returns the socket SNDBUF value.
1160
+ *
1161
+ * === Examples
1162
+ * ctx = ZMQ::Context.new
1163
+ * sock = ctx.socket(:REP)
1164
+ * sock.sndbuf => 0
1165
+ *
1166
+ */
1167
+
1168
+ static VALUE rb_czmq_socket_opt_sndbuf(VALUE obj)
1169
+ {
1170
+ zmq_sock_wrapper *sock = NULL;
1171
+ GetZmqSocket(obj);
1172
+ return INT2NUM(zsockopt_sndbuf(sock->socket));
1173
+ }
1174
+
1175
+ /*
1176
+ * call-seq:
1177
+ * sock.sndbuf = 1000 => nil
1178
+ *
1179
+ * Sets the socket SNDBUF value.
1180
+ *
1181
+ * === Examples
1182
+ * ctx = ZMQ::Context.new
1183
+ * sock = ctx.socket(:REP)
1184
+ * sock.sndbuf = 1000 => nil
1185
+ *
1186
+ */
1187
+
1188
+ static VALUE rb_czmq_socket_set_opt_sndbuf(VALUE obj, VALUE value)
1189
+ {
1190
+ zmq_sock_wrapper *sock = NULL;
1191
+ ZmqSetSockOpt(obj, zsockopt_set_sndbuf, "SNDBUF", value);
1192
+ }
1193
+
1194
+ /*
1195
+ * call-seq:
1196
+ * sock.rcvbuf => Fixnum
1197
+ *
1198
+ * Returns the socket RCVBUF value.
1199
+ *
1200
+ * === Examples
1201
+ * ctx = ZMQ::Context.new
1202
+ * sock = ctx.socket(:REP)
1203
+ * sock.rcvbuf => 0
1204
+ *
1205
+ */
1206
+
1207
+ static VALUE rb_czmq_socket_opt_rcvbuf(VALUE obj)
1208
+ {
1209
+ zmq_sock_wrapper *sock = NULL;
1210
+ GetZmqSocket(obj);
1211
+ return INT2NUM(zsockopt_rcvbuf(sock->socket));
1212
+ }
1213
+
1214
+ /*
1215
+ * call-seq:
1216
+ * sock.rcvbuf = 1000 => nil
1217
+ *
1218
+ * Sets the socket RCVBUF value.
1219
+ *
1220
+ * === Examples
1221
+ * ctx = ZMQ::Context.new
1222
+ * sock = ctx.socket(:REP)
1223
+ * sock.rcvbuf = 1000 => nil
1224
+ *
1225
+ */
1226
+
1227
+ static VALUE rb_czmq_socket_set_opt_rcvbuf(VALUE obj, VALUE value)
1228
+ {
1229
+ zmq_sock_wrapper *sock = NULL;
1230
+ ZmqSetSockOpt(obj, zsockopt_set_rcvbuf, "RCVBUF", value);
1231
+ }
1232
+
1233
+ /*
1234
+ * call-seq:
1235
+ * sock.linger => Fixnum
1236
+ *
1237
+ * Returns the socket LINGER value.
1238
+ *
1239
+ * === Examples
1240
+ * ctx = ZMQ::Context.new
1241
+ * sock = ctx.socket(:REP)
1242
+ * sock.linger => -1
1243
+ *
1244
+ */
1245
+
1246
+ static VALUE rb_czmq_socket_opt_linger(VALUE obj)
1247
+ {
1248
+ zmq_sock_wrapper *sock = NULL;
1249
+ GetZmqSocket(obj);
1250
+ return INT2NUM(zsockopt_linger(sock->socket));
1251
+ }
1252
+
1253
+ /*
1254
+ * call-seq:
1255
+ * sock.linger = 1000 => nil
1256
+ *
1257
+ * Sets the socket LINGER value in ms.
1258
+ *
1259
+ * === Examples
1260
+ * ctx = ZMQ::Context.new
1261
+ * sock = ctx.socket(:REP)
1262
+ * sock.linger = 1000 => nil
1263
+ *
1264
+ */
1265
+
1266
+ static VALUE rb_czmq_socket_set_opt_linger(VALUE obj, VALUE value)
1267
+ {
1268
+ zmq_sock_wrapper *sock = NULL;
1269
+ ZmqSetSockOpt(obj, zsockopt_set_linger, "LINGER", value);
1270
+ }
1271
+
1272
+ /*
1273
+ * call-seq:
1274
+ * sock.backlog => Fixnum
1275
+ *
1276
+ * Returns the socket BACKLOG value.
1277
+ *
1278
+ * === Examples
1279
+ * ctx = ZMQ::Context.new
1280
+ * sock = ctx.socket(:REP)
1281
+ * sock.backlog => 100
1282
+ *
1283
+ */
1284
+
1285
+ static VALUE rb_czmq_socket_opt_backlog(VALUE obj)
1286
+ {
1287
+ zmq_sock_wrapper *sock = NULL;
1288
+ GetZmqSocket(obj);
1289
+ return INT2NUM(zsockopt_backlog(sock->socket));
1290
+ }
1291
+
1292
+ /*
1293
+ * call-seq:
1294
+ * sock.backlog = 200 => nil
1295
+ *
1296
+ * Sets the socket BACKLOG value.
1297
+ *
1298
+ * === Examples
1299
+ * ctx = ZMQ::Context.new
1300
+ * sock = ctx.socket(:REP)
1301
+ * sock.backlog = 200 => nil
1302
+ *
1303
+ */
1304
+
1305
+ static VALUE rb_czmq_socket_set_opt_backlog(VALUE obj, VALUE value)
1306
+ {
1307
+ zmq_sock_wrapper *sock = NULL;
1308
+ ZmqSetSockOpt(obj, zsockopt_set_backlog, "BACKLOG", value);
1309
+ }
1310
+
1311
+ /*
1312
+ * call-seq:
1313
+ * sock.reconnect_ivl => Fixnum
1314
+ *
1315
+ * Returns the socket RECONNECT_IVL value.
1316
+ *
1317
+ * === Examples
1318
+ * ctx = ZMQ::Context.new
1319
+ * sock = ctx.socket(:REP)
1320
+ * sock.reconnect_ivl => 100
1321
+ *
1322
+ */
1323
+
1324
+ static VALUE rb_czmq_socket_opt_reconnect_ivl(VALUE obj)
1325
+ {
1326
+ zmq_sock_wrapper *sock = NULL;
1327
+ GetZmqSocket(obj);
1328
+ return INT2NUM(zsockopt_reconnect_ivl(sock->socket));
1329
+ }
1330
+
1331
+ /*
1332
+ * call-seq:
1333
+ * sock.reconnect_ivl = 200 => nil
1334
+ *
1335
+ * Sets the socket RECONNECT_IVL value.
1336
+ *
1337
+ * === Examples
1338
+ * ctx = ZMQ::Context.new
1339
+ * sock = ctx.socket(:REP)
1340
+ * sock.reconnect_ivl = 200 => nil
1341
+ *
1342
+ */
1343
+
1344
+ static VALUE rb_czmq_socket_set_opt_reconnect_ivl(VALUE obj, VALUE value)
1345
+ {
1346
+ zmq_sock_wrapper *sock = NULL;
1347
+ ZmqSetSockOpt(obj, zsockopt_set_reconnect_ivl, "RECONNECT_IVL", value);
1348
+ }
1349
+
1350
+ /*
1351
+ * call-seq:
1352
+ * sock.reconnect_ivl_max => Fixnum
1353
+ *
1354
+ * Returns the socket RECONNECT_IVL_MAX value.
1355
+ *
1356
+ * === Examples
1357
+ * ctx = ZMQ::Context.new
1358
+ * sock = ctx.socket(:REP)
1359
+ * sock.reconnect_ivl_max => 0
1360
+ *
1361
+ */
1362
+
1363
+ static VALUE rb_czmq_socket_opt_reconnect_ivl_max(VALUE obj)
1364
+ {
1365
+ zmq_sock_wrapper *sock = NULL;
1366
+ GetZmqSocket(obj);
1367
+ return INT2NUM(zsockopt_reconnect_ivl_max(sock->socket));
1368
+ }
1369
+
1370
+ /*
1371
+ * call-seq:
1372
+ * sock.reconnect_ivl_max = 5 => nil
1373
+ *
1374
+ * Sets the socket RECONNECT_IVL_MAX value.
1375
+ *
1376
+ * === Examples
1377
+ * ctx = ZMQ::Context.new
1378
+ * sock = ctx.socket(:REP)
1379
+ * sock.reconnect_ivl_max = 5 => nil
1380
+ *
1381
+ */
1382
+
1383
+ static VALUE rb_czmq_socket_set_opt_reconnect_ivl_max(VALUE obj, VALUE value)
1384
+ {
1385
+ zmq_sock_wrapper *sock = NULL;
1386
+ ZmqSetSockOpt(obj, zsockopt_set_reconnect_ivl_max, "RECONNECT_IVL_MAX", value);
1387
+ }
1388
+
1389
+ /*
1390
+ * call-seq:
1391
+ * sock.identity = "anonymous" => nil
1392
+ *
1393
+ * Sets the socket IDENTITY value.
1394
+ *
1395
+ * === Examples
1396
+ * ctx = ZMQ::Context.new
1397
+ * sock = ctx.socket(:REP)
1398
+ * sock.identity = "anonymous" => nil
1399
+ *
1400
+ */
1401
+
1402
+ static VALUE rb_czmq_socket_set_opt_identity(VALUE obj, VALUE value)
1403
+ {
1404
+ char *val;
1405
+ zmq_sock_wrapper *sock = NULL;
1406
+ GetZmqSocket(obj);
1407
+ ZmqSockGuardCrossThread(sock);
1408
+ Check_Type(value, T_STRING);
1409
+ if (RSTRING_LEN(value) == 0) rb_raise(rb_eZmqError, "socket identity cannot be empty.");
1410
+ if (RSTRING_LEN(value) > 255) rb_raise(rb_eZmqError, "maximum socket identity is 255 chars.");
1411
+ val = StringValueCStr(value);
1412
+ zsockopt_set_identity(sock->socket, val);
1413
+ if (sock->verbose)
1414
+ zclock_log ("I: %s socket %p: set option \"IDENTITY\" \"%s\"", zsocket_type_str(sock->socket), obj, val);
1415
+ return Qnil;
1416
+ }
1417
+
1418
+ /*
1419
+ * call-seq:
1420
+ * sock.subscribe "ruby" => nil
1421
+ *
1422
+ * Subscribes this SUB socket to a topic.
1423
+ *
1424
+ * === Examples
1425
+ * ctx = ZMQ::Context.new
1426
+ * sock = ctx.socket(:SUB)
1427
+ * sock.subscribe "ruby" => nil
1428
+ *
1429
+ */
1430
+
1431
+ static VALUE rb_czmq_socket_set_opt_subscribe(VALUE obj, VALUE value)
1432
+ {
1433
+ zmq_sock_wrapper *sock = NULL;
1434
+ ZmqSetStringSockOpt(obj, zsockopt_set_subscribe, "SUBSCRIBE", value, {
1435
+ ZmqAssertSockOptFor(ZMQ_SUB)
1436
+ });
1437
+ }
1438
+
1439
+ /*
1440
+ * call-seq:
1441
+ * sock.unsubscribe "ruby" => nil
1442
+ *
1443
+ * Unsubscribes this SUB socket from a topic.
1444
+ *
1445
+ * === Examples
1446
+ * ctx = ZMQ::Context.new
1447
+ * sock = ctx.socket(:SUB)
1448
+ * sock.unsubscribe "ruby" => nil
1449
+ *
1450
+ */
1451
+
1452
+ static VALUE rb_czmq_socket_set_opt_unsubscribe(VALUE obj, VALUE value)
1453
+ {
1454
+ zmq_sock_wrapper *sock = NULL;
1455
+ ZmqSetStringSockOpt(obj, zsockopt_set_unsubscribe, "UNSUBSCRIBE", value, {
1456
+ ZmqAssertSockOptFor(ZMQ_SUB)
1457
+ });
1458
+ }
1459
+
1460
+ /*
1461
+ * call-seq:
1462
+ * sock.rcvmore => boolean
1463
+ *
1464
+ * Query if there's more messages to receive.
1465
+ *
1466
+ * === Examples
1467
+ * ctx = ZMQ::Context.new
1468
+ * sock = ctx.socket(:SUB)
1469
+ * sock.rcvmore => true
1470
+ *
1471
+ */
1472
+
1473
+ static VALUE rb_czmq_socket_opt_rcvmore(VALUE obj)
1474
+ {
1475
+ zmq_sock_wrapper *sock = NULL;
1476
+ GetZmqSocket(obj);
1477
+ return (zsockopt_rcvmore(sock->socket) == 1) ? Qtrue : Qfalse;
1478
+ }
1479
+
1480
+ /*
1481
+ * call-seq:
1482
+ * sock.events => Fixnum
1483
+ *
1484
+ * Query if this socket is in a readable or writable state.
1485
+ *
1486
+ * === Examples
1487
+ * ctx = ZMQ::Context.new
1488
+ * sock = ctx.socket(:SUB)
1489
+ * sock.events => ZMQ::POLLIN
1490
+ *
1491
+ */
1492
+
1493
+ static VALUE rb_czmq_socket_opt_events(VALUE obj)
1494
+ {
1495
+ zmq_sock_wrapper *sock = NULL;
1496
+ GetZmqSocket(obj);
1497
+ return INT2NUM(zsockopt_events(sock->socket));
1498
+ }
1499
+
1500
+ void _init_rb_czmq_socket()
1501
+ {
1502
+ rb_cZmqSocket = rb_define_class_under(rb_mZmq, "Socket", rb_cObject);
1503
+ rb_cZmqPubSocket = rb_define_class_under(rb_cZmqSocket, "Pub", rb_cZmqSocket);
1504
+ rb_cZmqSubSocket = rb_define_class_under(rb_cZmqSocket, "Sub", rb_cZmqSocket);;
1505
+ rb_cZmqPushSocket = rb_define_class_under(rb_cZmqSocket, "Push", rb_cZmqSocket);;
1506
+ rb_cZmqPullSocket = rb_define_class_under(rb_cZmqSocket, "Pull", rb_cZmqSocket);;
1507
+ rb_cZmqRouterSocket = rb_define_class_under(rb_cZmqSocket, "Router", rb_cZmqSocket);;
1508
+ rb_cZmqDealerSocket = rb_define_class_under(rb_cZmqSocket, "Dealer", rb_cZmqSocket);;
1509
+ rb_cZmqRepSocket = rb_define_class_under(rb_cZmqSocket, "Rep", rb_cZmqSocket);;
1510
+ rb_cZmqReqSocket = rb_define_class_under(rb_cZmqSocket, "Req", rb_cZmqSocket);;
1511
+ rb_cZmqPairSocket = rb_define_class_under(rb_cZmqSocket, "Pair", rb_cZmqSocket);;
1512
+
1513
+ rb_define_const(rb_cZmqSocket, "PENDING", INT2NUM(ZMQ_SOCKET_PENDING));
1514
+ rb_define_const(rb_cZmqSocket, "BOUND", INT2NUM(ZMQ_SOCKET_BOUND));
1515
+ rb_define_const(rb_cZmqSocket, "CONNECTED", INT2NUM(ZMQ_SOCKET_CONNECTED));
1516
+
1517
+ rb_define_method(rb_cZmqSocket, "close", rb_czmq_socket_close, 0);
1518
+ rb_define_method(rb_cZmqSocket, "endpoint", rb_czmq_socket_endpoint, 0);
1519
+ rb_define_method(rb_cZmqSocket, "state", rb_czmq_socket_state, 0);
1520
+ rb_define_method(rb_cZmqSocket, "bind", rb_czmq_socket_bind, 1);
1521
+ rb_define_method(rb_cZmqSocket, "connect", rb_czmq_socket_connect, 1);
1522
+ rb_define_method(rb_cZmqSocket, "fd", rb_czmq_socket_fd, 0);
1523
+ rb_define_alias(rb_cZmqSocket, "to_i", "fd");
1524
+ rb_define_method(rb_cZmqSocket, "verbose=", rb_czmq_socket_set_verbose, 1);
1525
+ rb_define_method(rb_cZmqSocket, "send", rb_czmq_socket_send, 1);
1526
+ rb_define_method(rb_cZmqSocket, "sendm", rb_czmq_socket_sendm, 1);
1527
+ rb_define_method(rb_cZmqSocket, "send_frame", rb_czmq_socket_send_frame, -1);
1528
+ rb_define_method(rb_cZmqSocket, "send_message", rb_czmq_socket_send_message, 1);
1529
+ rb_define_method(rb_cZmqSocket, "recv", rb_czmq_socket_recv, 0);
1530
+ rb_define_method(rb_cZmqSocket, "recv_nonblock", rb_czmq_socket_recv_nonblock, 0);
1531
+ rb_define_method(rb_cZmqSocket, "recv_frame", rb_czmq_socket_recv_frame, 0);
1532
+ rb_define_method(rb_cZmqSocket, "recv_frame_nonblock", rb_czmq_socket_recv_frame_nonblock, 0);
1533
+ rb_define_method(rb_cZmqSocket, "recv_message", rb_czmq_socket_recv_message, 0);
1534
+ rb_define_method(rb_cZmqSocket, "recv_timeout=", rb_czmq_socket_set_recv_timeout, 1);
1535
+ rb_define_method(rb_cZmqSocket, "recv_timeout", rb_czmq_socket_recv_timeout, 0);
1536
+ rb_define_method(rb_cZmqSocket, "send_timeout=", rb_czmq_socket_set_send_timeout, 1);
1537
+ rb_define_method(rb_cZmqSocket, "send_timeout", rb_czmq_socket_send_timeout, 0);
1538
+
1539
+ rb_define_method(rb_cZmqSocket, "hwm", rb_czmq_socket_opt_hwm, 0);
1540
+ rb_define_method(rb_cZmqSocket, "hwm=", rb_czmq_socket_set_opt_hwm, 1);
1541
+ rb_define_method(rb_cZmqSocket, "swap", rb_czmq_socket_opt_swap, 0);
1542
+ rb_define_method(rb_cZmqSocket, "swap=", rb_czmq_socket_set_opt_swap, 1);
1543
+ rb_define_method(rb_cZmqSocket, "affinity", rb_czmq_socket_opt_affinity, 0);
1544
+ rb_define_method(rb_cZmqSocket, "affinity=", rb_czmq_socket_set_opt_affinity, 1);
1545
+ rb_define_method(rb_cZmqSocket, "rate", rb_czmq_socket_opt_rate, 0);
1546
+ rb_define_method(rb_cZmqSocket, "rate=", rb_czmq_socket_set_opt_rate, 1);
1547
+ rb_define_method(rb_cZmqSocket, "recovery_ivl", rb_czmq_socket_opt_recovery_ivl, 0);
1548
+ rb_define_method(rb_cZmqSocket, "recovery_ivl=", rb_czmq_socket_set_opt_recovery_ivl, 1);
1549
+ rb_define_method(rb_cZmqSocket, "recovery_ivl_msec", rb_czmq_socket_opt_recovery_ivl_msec, 0);
1550
+ rb_define_method(rb_cZmqSocket, "recovery_ivl_msec=", rb_czmq_socket_set_opt_recovery_ivl_msec, 1);
1551
+ rb_define_method(rb_cZmqSocket, "mcast_loop?", rb_czmq_socket_opt_mcast_loop, 0);
1552
+ rb_define_method(rb_cZmqSocket, "mcast_loop=", rb_czmq_socket_set_opt_mcast_loop, 1);
1553
+ rb_define_method(rb_cZmqSocket, "sndbuf", rb_czmq_socket_opt_sndbuf, 0);
1554
+ rb_define_method(rb_cZmqSocket, "sndbuf=", rb_czmq_socket_set_opt_sndbuf, 1);
1555
+ rb_define_method(rb_cZmqSocket, "rcvbuf", rb_czmq_socket_opt_rcvbuf, 0);
1556
+ rb_define_method(rb_cZmqSocket, "rcvbuf=", rb_czmq_socket_set_opt_rcvbuf, 1);
1557
+ rb_define_method(rb_cZmqSocket, "linger", rb_czmq_socket_opt_linger, 0);
1558
+ rb_define_method(rb_cZmqSocket, "linger=", rb_czmq_socket_set_opt_linger, 1);
1559
+ rb_define_method(rb_cZmqSocket, "backlog", rb_czmq_socket_opt_backlog, 0);
1560
+ rb_define_method(rb_cZmqSocket, "backlog=", rb_czmq_socket_set_opt_backlog, 1);
1561
+ rb_define_method(rb_cZmqSocket, "reconnect_ivl", rb_czmq_socket_opt_reconnect_ivl, 0);
1562
+ rb_define_method(rb_cZmqSocket, "reconnect_ivl=", rb_czmq_socket_set_opt_reconnect_ivl, 1);
1563
+ rb_define_method(rb_cZmqSocket, "reconnect_ivl_max", rb_czmq_socket_opt_reconnect_ivl_max, 0);
1564
+ rb_define_method(rb_cZmqSocket, "reconnect_ivl_max=", rb_czmq_socket_set_opt_reconnect_ivl_max, 1);
1565
+ rb_define_method(rb_cZmqSocket, "identity=", rb_czmq_socket_set_opt_identity, 1);
1566
+ rb_define_method(rb_cZmqSocket, "subscribe", rb_czmq_socket_set_opt_subscribe, 1);
1567
+ rb_define_method(rb_cZmqSocket, "unsubscribe", rb_czmq_socket_set_opt_unsubscribe, 1);
1568
+ rb_define_method(rb_cZmqSocket, "rcvmore?", rb_czmq_socket_opt_rcvmore, 0);
1569
+ rb_define_method(rb_cZmqSocket, "events", rb_czmq_socket_opt_events, 0);
1570
+ }