rbczmq 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }