ffi-rzmq 0.9.3 → 0.9.6

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.
@@ -1,7 +1,7 @@
1
1
  module ZMQ
2
2
 
3
3
  # Wraps the libzmq library and attaches to the functions that are
4
- # common across the 2.x, 3.x and 4.x APIs.
4
+ # common across the 2.x and 3.x APIs.
5
5
  #
6
6
  module LibZMQ
7
7
  extend FFI::Library
@@ -10,18 +10,32 @@ module ZMQ
10
10
  # bias the library discovery to a path inside the gem first, then
11
11
  # to the usual system paths
12
12
  inside_gem = File.join(File.dirname(__FILE__), '..', '..', 'ext')
13
+ if FFI::Platform::IS_WINDOWS
14
+ local_path=ENV['PATH'].split(';')
15
+ else
16
+ local_path=ENV['PATH'].split(':')
17
+ end
13
18
  ZMQ_LIB_PATHS = [
14
- inside_gem, '/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
19
+ inside_gem, '/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
15
20
  ].map{|path| "#{path}/libzmq.#{FFI::Platform::LIBSUFFIX}"}
16
21
  ffi_lib(ZMQ_LIB_PATHS + %w{libzmq})
17
22
  rescue LoadError
18
- STDERR.puts "Unable to load this gem. The libzmq library (or DLL) could not be found."
19
- STDERR.puts "If this is a Windows platform, make sure libzmq.dll is on the PATH."
20
- STDERR.puts "For non-Windows platforms, make sure libzmq is located in this search path:"
21
- STDERR.puts ZMQ_LIB_PATHS.inspect
22
- exit 255
23
+ if ZMQ_LIB_PATHS.push(*local_path).any? {|path|
24
+ File.file? File.join(path, "libzmq.#{FFI::Platform::LIBSUFFIX}")}
25
+ warn "Unable to load this gem. The libzmq library exists, but cannot be loaded."
26
+ warn "If this is Windows:"
27
+ warn "- Check that you have MSVC runtime installed or statically linked"
28
+ warn "- Check that your DLL is compiled for #{FFI::Platform::ADDRESS_SIZE} bit"
29
+ else
30
+ warn "Unable to load this gem. The libzmq library (or DLL) could not be found."
31
+ warn "If this is a Windows platform, make sure libzmq.dll is on the PATH."
32
+ warn "If the DLL was built with mingw, make sure the other two dependent DLLs,"
33
+ warn "libgcc_s_sjlj-1.dll and libstdc++6.dll, are also on the PATH."
34
+ warn "For non-Windows platforms, make sure libzmq is located in this search path:"
35
+ warn ZMQ_LIB_PATHS.inspect
36
+ end
37
+ raise LoadError, "The libzmq library (or DLL) could not be loaded"
23
38
  end
24
-
25
39
  # Size_t not working properly on Windows
26
40
  find_type(:size_t) rescue typedef(:ulong, :size_t)
27
41
 
@@ -38,20 +52,14 @@ module ZMQ
38
52
  # otherwise the runtime hangs (and requires a kill -9 to terminate)
39
53
  #
40
54
  @blocking = true
41
- attach_function :zmq_init, [:int], :pointer
42
- @blocking = true
43
- attach_function :zmq_socket, [:pointer, :int], :pointer
44
- @blocking = true
45
- attach_function :zmq_term, [:pointer], :int
55
+ attach_function :zmq_version, [:pointer, :pointer, :pointer], :void
46
56
  @blocking = true
47
57
  attach_function :zmq_errno, [], :int
48
58
  @blocking = true
49
59
  attach_function :zmq_strerror, [:int], :pointer
50
- @blocking = true
51
- attach_function :zmq_version, [:pointer, :pointer, :pointer], :void
52
60
 
53
61
  def self.version
54
- unless @version
62
+ if @version.nil?
55
63
  major = FFI::MemoryPointer.new :int
56
64
  minor = FFI::MemoryPointer.new :int
57
65
  patch = FFI::MemoryPointer.new :int
@@ -64,12 +72,15 @@ module ZMQ
64
72
 
65
73
  def self.version2?() version[:major] == 2 && version[:minor] >= 1 end
66
74
 
67
- def self.version3?() version[:major] == 3 && version[:minor] >= 1 end
68
-
69
- def self.version4?() version[:major] == 4 end
75
+ def self.version3?() version[:major] == 3 && version[:minor] >= 2 end
70
76
 
77
+ # Context initialization and destruction
78
+ @blocking = true
79
+ attach_function :zmq_init, [:int], :pointer
80
+ @blocking = true
81
+ attach_function :zmq_term, [:pointer], :int
71
82
 
72
- # Message api
83
+ # Message API
73
84
  @blocking = true
74
85
  attach_function :zmq_msg_init, [:pointer], :int
75
86
  @blocking = true
@@ -96,27 +107,41 @@ module ZMQ
96
107
  :vsm_data, [:uint8, 30]
97
108
  end # class Msg
98
109
 
99
- # Socket api
110
+ # Socket API
111
+ @blocking = true
112
+ attach_function :zmq_socket, [:pointer, :int], :pointer
100
113
  @blocking = true
101
114
  attach_function :zmq_setsockopt, [:pointer, :int, :pointer, :int], :int
102
115
  @blocking = true
116
+ attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
117
+ @blocking = true
103
118
  attach_function :zmq_bind, [:pointer, :string], :int
104
119
  @blocking = true
105
120
  attach_function :zmq_connect, [:pointer, :string], :int
106
121
  @blocking = true
107
122
  attach_function :zmq_close, [:pointer], :int
108
123
 
109
- # Poll api
124
+ # Device API
125
+ @blocking = true
126
+ attach_function :zmq_device, [:int, :pointer, :pointer], :int
127
+
128
+ # Poll API
110
129
  @blocking = true
111
130
  attach_function :zmq_poll, [:pointer, :int, :long], :int
112
131
 
113
132
  module PollItemLayout
114
133
  def self.included(base)
134
+ if FFI::Platform::IS_WINDOWS && FFI::Platform::ADDRESS_SIZE==64
135
+ # On Windows, zmq.h defines fd as a SOCKET, which is 64 bits on x64.
136
+ fd_type=:uint64
137
+ else
138
+ fd_type=:int
139
+ end
115
140
  base.class_eval do
116
141
  layout :socket, :pointer,
117
- :fd, :int,
118
- :events, :short,
119
- :revents, :short
142
+ :fd, fd_type,
143
+ :events, :short,
144
+ :revents, :short
120
145
  end
121
146
  end
122
147
  end # module PollItemLayout
@@ -125,7 +150,7 @@ module ZMQ
125
150
  include PollItemLayout
126
151
 
127
152
  def socket() self[:socket]; end
128
-
153
+
129
154
  def fd() self[:fd]; end
130
155
 
131
156
  def readable?
@@ -157,13 +182,9 @@ module ZMQ
157
182
  module LibZMQ
158
183
  # Socket api
159
184
  @blocking = true
160
- attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
161
- @blocking = true
162
185
  attach_function :zmq_recv, [:pointer, :pointer, :int], :int
163
186
  @blocking = true
164
187
  attach_function :zmq_send, [:pointer, :pointer, :int], :int
165
- @blocking = true
166
- attach_function :zmq_device, [:int, :pointer, :pointer], :int
167
188
  end
168
189
  end
169
190
 
@@ -173,9 +194,37 @@ module ZMQ
173
194
  if LibZMQ.version3?
174
195
 
175
196
  module LibZMQ
176
- # Socket api
197
+ # New Context API
198
+ @blocking = true
199
+ attach_function :zmq_ctx_new, [], :pointer
200
+ @blocking = true
201
+ attach_function :zmq_ctx_destroy, [:pointer], :int
202
+ @blocking = true
203
+ attach_function :zmq_ctx_set, [:pointer, :int, :int], :int
204
+ @blocking = true
205
+ attach_function :zmq_ctx_get, [:pointer, :int], :int
206
+
207
+ # Message API
177
208
  @blocking = true
178
- attach_function :zmq_getsockopt, [:pointer, :int, :pointer, :pointer], :int
209
+ attach_function :zmq_msg_send, [:pointer, :pointer, :int], :int
210
+ @blocking = true
211
+ attach_function :zmq_msg_recv, [:pointer, :pointer, :int], :int
212
+ @blocking = true
213
+ attach_function :zmq_msg_more, [:pointer], :int
214
+ @blocking = true
215
+ attach_function :zmq_msg_get, [:pointer, :int], :int
216
+ @blocking = true
217
+ attach_function :zmq_msg_set, [:pointer, :int, :int], :int
218
+
219
+ # Monitoring API
220
+ @blocking = true
221
+ attach_function :zmq_ctx_set_monitor, [:pointer, :pointer], :int
222
+
223
+ # Socket API
224
+ @blocking = true
225
+ attach_function :zmq_unbind, [:pointer, :string], :int
226
+ @blocking = true
227
+ attach_function :zmq_disconnect, [:pointer, :string], :int
179
228
  @blocking = true
180
229
  attach_function :zmq_recvmsg, [:pointer, :pointer, :int], :int
181
230
  @blocking = true
@@ -184,6 +233,33 @@ module ZMQ
184
233
  attach_function :zmq_sendmsg, [:pointer, :pointer, :int], :int
185
234
  @blocking = true
186
235
  attach_function :zmq_send, [:pointer, :pointer, :size_t, :int], :int
236
+
237
+ module EventDataLayout
238
+ def self.included(base)
239
+ base.class_eval do
240
+ layout :addr, :string,
241
+ :field2, :int
242
+ end
243
+ end
244
+ end # module EventDataLayout
245
+
246
+ class EventData < FFI::Struct
247
+ include EventDataLayout
248
+
249
+ def addr() self[:addr]; end
250
+ alias :address :addr
251
+
252
+ def fd() self[:field2]; end
253
+ alias :err :fd
254
+ alias :interval :fd
255
+
256
+ def inspect
257
+ "addr [#{addr}], fd [#{fd}], field2 [#{fd}]"
258
+ end
259
+
260
+ def to_s; inspect; end
261
+ end # class EventData
262
+
187
263
  end
188
264
  end
189
265
 
@@ -194,8 +270,7 @@ module ZMQ
194
270
  unless LibZMQ.version2? || LibZMQ.version3?
195
271
  hash = LibZMQ.version
196
272
  version = "#{hash[:major]}.#{hash[:minor]}.#{hash[:patch]}"
197
- STDERR.puts "Unable to load this gem. The libzmq version #{version} is incompatible with ffi-rzmq."
198
- exit 255
273
+ raise LoadError, "The libzmq version #{version} is incompatible with ffi-rzmq."
199
274
  end
200
275
 
201
276
  end # module ZMQ
@@ -30,7 +30,7 @@ module ZMQ
30
30
  #
31
31
  # received_message = Message.create
32
32
  # if received_message
33
- # rc = socket.recv(received_message)
33
+ # rc = socket.recvmsg(received_message)
34
34
  # if ZMQ::Util.resultcode_ok?(rc)
35
35
  # puts "Message contained: #{received_message.copy_out_string}"
36
36
  # else
@@ -84,7 +84,6 @@ module ZMQ
84
84
  # puts "value1 is #{message.value1}"
85
85
  #
86
86
  class Message
87
- include ZMQ::Util
88
87
 
89
88
  # Recommended way to create a standard message. A Message object is
90
89
  # returned upon success, nil when allocation fails.
@@ -199,6 +198,28 @@ module ZMQ
199
198
  def self.msg_size() @msg_size; end
200
199
 
201
200
  end # class Message
201
+
202
+ if LibZMQ.version3?
203
+ class Message
204
+ # Version3 only
205
+ #
206
+ def get(property)
207
+ LibZMQ.zmq_msg_get(@pointer, property)
208
+ end
209
+
210
+ # Version3 only
211
+ #
212
+ # Returns true if this message has additional parts coming.
213
+ #
214
+ def more?
215
+ Util.resultcode_ok?(get(MORE))
216
+ end
217
+
218
+ def set(property, value)
219
+ LibZMQ.zmq_msg_set(@pointer, property, value)
220
+ end
221
+ end
222
+ end
202
223
 
203
224
 
204
225
 
data/lib/ffi-rzmq/poll.rb CHANGED
@@ -2,7 +2,6 @@
2
2
  module ZMQ
3
3
 
4
4
  class Poller
5
- include ZMQ::Util
6
5
 
7
6
  attr_reader :readables, :writables
8
7
 
@@ -15,7 +14,7 @@ module ZMQ
15
14
  end
16
15
 
17
16
  # Checks each registered socket for selectability based on the poll items'
18
- # registered +events+. Will block for up to +timeout+ milliseconds
17
+ # registered +events+. Will block for up to +timeout+ milliseconds.
19
18
  # A millisecond is 1/1000 of a second, so to block for 1 second
20
19
  # pass the value "1000" to #poll.
21
20
  #
@@ -100,7 +99,7 @@ module ZMQ
100
99
 
101
100
  item = @items.get(@sockets.index(sock))
102
101
 
103
- if item
102
+ if item && (item[:events] & events) > 0
104
103
  # change the value in place
105
104
  item[:events] ^= events
106
105
 
@@ -139,11 +138,11 @@ module ZMQ
139
138
  # when a socket has been deregistered and has no more events
140
139
  # registered anywhere.
141
140
  #
141
+ # Can also be called directly to remove the socket from the polling
142
+ # array.
143
+ #
142
144
  def delete sock
143
- removed_readable = deregister_readable sock
144
- removed_writable = deregister_writable sock
145
-
146
- unless (removed_readable || removed_writable) || (size = @sockets.size).zero?
145
+ unless (size = @sockets.size).zero?
147
146
  @sockets.delete_if { |socket| socket.socket.address == sock.socket.address }
148
147
  socket_deleted = size != @sockets.size
149
148
 
@@ -154,8 +153,7 @@ module ZMQ
154
153
  socket_deleted && item_deleted && raw_deleted
155
154
 
156
155
  else
157
- # return result of deregistration
158
- removed_readable || removed_writable
156
+ false
159
157
  end
160
158
  end
161
159
 
@@ -2,7 +2,6 @@
2
2
  module ZMQ
3
3
 
4
4
  module CommonSocketBehavior
5
- include ZMQ::Util
6
5
 
7
6
  attr_reader :socket, :name
8
7
 
@@ -82,6 +81,7 @@ module ZMQ
82
81
  raise ContextError.new 'zmq_socket', 0, ETERM, "Context pointer was null"
83
82
  end
84
83
 
84
+ @longlong_cache = @int_cache = nil
85
85
  @more_parts_array = []
86
86
  @option_lookup = []
87
87
  populate_option_lookup
@@ -157,12 +157,12 @@ module ZMQ
157
157
  #
158
158
  # message_parts = []
159
159
  # message = Message.new
160
- # rc = socket.recv(message)
160
+ # rc = socket.recvmsg(message)
161
161
  # if ZMQ::Util.resultcode_ok?(rc)
162
162
  # message_parts << message
163
163
  # while more_parts?
164
164
  # message = Message.new
165
- # rc = socket.recv(message)
165
+ # rc = socket.recvmsg(message)
166
166
  # message_parts.push(message) if resulcode_ok?(rc)
167
167
  # end
168
168
  # end
@@ -183,7 +183,7 @@ module ZMQ
183
183
 
184
184
  # Connects the socket to an +address+.
185
185
  #
186
- # socket.connect("tcp://127.0.0.1:5555")
186
+ # rc = socket.connect("tcp://127.0.0.1:5555")
187
187
  #
188
188
  def connect address
189
189
  rc = LibZMQ.zmq_connect @socket, address
@@ -210,6 +210,238 @@ module ZMQ
210
210
  end
211
211
  end
212
212
 
213
+ # Queues the message for transmission. Message is assumed to conform to the
214
+ # same public API as #Message.
215
+ #
216
+ # +flags+ may take two values:
217
+ # * 0 (default) - blocking operation
218
+ # * ZMQ::NonBlocking - non-blocking operation
219
+ # * ZMQ::SNDMORE - this message is part of a multi-part message
220
+ #
221
+ # Returns 0 when the message was successfully enqueued.
222
+ # Returns -1 under two conditions.
223
+ # 1. The message could not be enqueued
224
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
225
+ #
226
+ # With a -1 return code, the user must check ZMQ.errno to determine the
227
+ # cause.
228
+ #
229
+ def sendmsg message, flags = 0
230
+ __sendmsg__(@socket, message.address, flags)
231
+ end
232
+
233
+ # Helper method to make a new #Message instance out of the +string+ passed
234
+ # in for transmission.
235
+ #
236
+ # +flags+ may be ZMQ::NonBlocking and ZMQ::SNDMORE.
237
+ #
238
+ # Returns 0 when the message was successfully enqueued.
239
+ # Returns -1 under two conditions.
240
+ # 1. The message could not be enqueued
241
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
242
+ #
243
+ # With a -1 return code, the user must check ZMQ.errno to determine the
244
+ # cause.
245
+ #
246
+ def send_string string, flags = 0
247
+ message = Message.new string
248
+ send_and_close message, flags
249
+ end
250
+
251
+ # Send a sequence of strings as a multipart message out of the +parts+
252
+ # passed in for transmission. Every element of +parts+ should be
253
+ # a String.
254
+ #
255
+ # +flags+ may be ZMQ::NonBlocking.
256
+ #
257
+ # Returns 0 when the messages were successfully enqueued.
258
+ # Returns -1 under two conditions.
259
+ # 1. A message could not be enqueued
260
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
261
+ #
262
+ # With a -1 return code, the user must check ZMQ.errno to determine the
263
+ # cause.
264
+ #
265
+ def send_strings parts, flags = 0
266
+ return -1 if !parts || parts.empty?
267
+ flags = NonBlocking if dontwait?(flags)
268
+
269
+ parts[0..-2].each do |part|
270
+ rc = send_string part, (flags | ZMQ::SNDMORE)
271
+ return rc unless Util.resultcode_ok?(rc)
272
+ end
273
+
274
+ send_string parts[-1], flags
275
+ end
276
+
277
+ # Send a sequence of messages as a multipart message out of the +parts+
278
+ # passed in for transmission. Every element of +parts+ should be
279
+ # a Message (or subclass).
280
+ #
281
+ # +flags+ may be ZMQ::NonBlocking.
282
+ #
283
+ # Returns 0 when the messages were successfully enqueued.
284
+ # Returns -1 under two conditions.
285
+ # 1. A message could not be enqueued
286
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
287
+ #
288
+ # With a -1 return code, the user must check ZMQ.errno to determine the
289
+ # cause.
290
+ #
291
+ def sendmsgs parts, flags = 0
292
+ return -1 if !parts || parts.empty?
293
+ flags = NonBlocking if dontwait?(flags)
294
+
295
+ parts[0..-2].each do |part|
296
+ rc = sendmsg part, (flags | ZMQ::SNDMORE)
297
+ return rc unless Util.resultcode_ok?(rc)
298
+ end
299
+
300
+ sendmsg parts[-1], flags
301
+ end
302
+
303
+ # Sends a message. This will automatically close the +message+ for both successful
304
+ # and failed sends.
305
+ #
306
+ # Returns 0 when the message was successfully enqueued.
307
+ # Returns -1 under two conditions.
308
+ # 1. The message could not be enqueued
309
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
310
+ #
311
+ # With a -1 return code, the user must check ZMQ.errno to determine the
312
+ # cause.
313
+ #
314
+ def send_and_close message, flags = 0
315
+ rc = sendmsg message, flags
316
+ message.close
317
+ rc
318
+ end
319
+
320
+ # Dequeues a message from the underlying queue. By default, this is a blocking operation.
321
+ #
322
+ # +flags+ may take two values:
323
+ # 0 (default) - blocking operation
324
+ # ZMQ::NonBlocking - non-blocking operation
325
+ #
326
+ # Returns 0 when the message was successfully dequeued.
327
+ # Returns -1 under two conditions.
328
+ # 1. The message could not be dequeued
329
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
330
+ #
331
+ # With a -1 return code, the user must check ZMQ.errno to determine the
332
+ # cause.
333
+ #
334
+ # The application code is responsible for handling the +message+ object lifecycle
335
+ # when #recv returns an error code.
336
+ #
337
+ def recvmsg message, flags = 0
338
+ #LibZMQ.zmq_recvmsg @socket, message.address, flags
339
+ __recvmsg__(@socket, message.address, flags)
340
+ end
341
+
342
+ # Helper method to make a new #Message instance and convert its payload
343
+ # to a string.
344
+ #
345
+ # +flags+ may be ZMQ::NonBlocking.
346
+ #
347
+ # Returns 0 when the message was successfully dequeued.
348
+ # Returns -1 under two conditions.
349
+ # 1. The message could not be dequeued
350
+ # 2. When +flags+ is set with ZMQ::NonBlocking and the socket returned EAGAIN.
351
+ #
352
+ # With a -1 return code, the user must check ZMQ.errno to determine the
353
+ # cause.
354
+ #
355
+ # The application code is responsible for handling the +message+ object lifecycle
356
+ # when #recv returns an error code.
357
+ #
358
+ def recv_string string, flags = 0
359
+ message = @receiver_klass.new
360
+ rc = recvmsg message, flags
361
+ string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
362
+ message.close
363
+ rc
364
+ end
365
+
366
+ # Receive a multipart message as a list of strings.
367
+ #
368
+ # +flag+ may be ZMQ::NonBlocking. Any other flag will be
369
+ # removed.
370
+ #
371
+ def recv_strings list, flag = 0
372
+ array = []
373
+ rc = recvmsgs array, flag
374
+
375
+ if Util.resultcode_ok?(rc)
376
+ array.each do |message|
377
+ list << message.copy_out_string
378
+ message.close
379
+ end
380
+ end
381
+
382
+ rc
383
+ end
384
+
385
+ # Receive a multipart message as an array of objects
386
+ # (by default these are instances of Message).
387
+ #
388
+ # +flag+ may be ZMQ::NonBlocking. Any other flag will be
389
+ # removed.
390
+ #
391
+ def recvmsgs list, flag = 0
392
+ flag = NonBlocking if dontwait?(flag)
393
+
394
+ message = @receiver_klass.new
395
+ rc = recvmsg message, flag
396
+
397
+ if Util.resultcode_ok?(rc)
398
+ list << message
399
+
400
+ # check rc *first*; necessary because the call to #more_parts? can reset
401
+ # the zmq_errno to a weird value, so the zmq_errno that was set on the
402
+ # call to #recv gets lost
403
+ while Util.resultcode_ok?(rc) && more_parts?
404
+ message = @receiver_klass.new
405
+ rc = recvmsg message, flag
406
+
407
+ if Util.resultcode_ok?(rc)
408
+ list << message
409
+ else
410
+ message.close
411
+ list.each { |msg| msg.close }
412
+ list.clear
413
+ end
414
+ end
415
+ else
416
+ message.close
417
+ end
418
+
419
+ rc
420
+ end
421
+
422
+ # Should only be used for XREQ, XREP, DEALER and ROUTER type sockets. Takes
423
+ # a +list+ for receiving the message body parts and a +routing_envelope+
424
+ # for receiving the message parts comprising the 0mq routing information.
425
+ #
426
+ def recv_multipart list, routing_envelope, flag = 0
427
+ parts = []
428
+ rc = recvmsgs parts, flag
429
+
430
+ if Util.resultcode_ok?(rc)
431
+ routing = true
432
+ parts.each do |part|
433
+ if routing
434
+ routing_envelope << part
435
+ routing = part.size > 0
436
+ else
437
+ list << part
438
+ end
439
+ end
440
+ end
441
+
442
+ rc
443
+ end
444
+
213
445
 
214
446
  private
215
447
 
@@ -217,7 +449,7 @@ module ZMQ
217
449
  # a small optimization so we only have to determine the option
218
450
  # type a single time; gives approx 5% speedup to do it this way.
219
451
  option_type = @option_lookup[name]
220
-
452
+
221
453
  value, length = sockopt_buffers option_type
222
454
 
223
455
  rc = LibZMQ.zmq_getsockopt @socket, name, value, length
@@ -276,14 +508,14 @@ module ZMQ
276
508
  @int_cache
277
509
  end
278
510
  end
279
-
511
+
280
512
  def populate_option_lookup
281
513
  # integer options
282
- [EVENTS, LINGER, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
514
+ [EVENTS, LINGER, RCVTIMEO, SNDTIMEO, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
283
515
 
284
516
  # long long options
285
517
  [RCVMORE, AFFINITY].each { |option| @option_lookup[option] = 1 }
286
-
518
+
287
519
  # string options
288
520
  [SUBSCRIBE, UNSUBSCRIBE].each { |option| @option_lookup[option] = 2 }
289
521
  end
@@ -292,6 +524,11 @@ module ZMQ
292
524
  @longlong_cache = nil
293
525
  @int_cache = nil
294
526
  end
527
+
528
+ def dontwait?(flags)
529
+ (NonBlocking & flags) == NonBlocking
530
+ end
531
+ alias :noblock? :dontwait?
295
532
  end # module CommonSocketBehavior
296
533
 
297
534
 
@@ -313,14 +550,14 @@ module ZMQ
313
550
 
314
551
 
315
552
  private
316
-
553
+
317
554
  def populate_option_lookup
318
555
  super()
319
-
556
+
320
557
  # string options
321
558
  [IDENTITY].each { |option| @option_lookup[option] = 2 }
322
559
  end
323
-
560
+
324
561
  end # module IdentitySupport
325
562
 
326
563
 
@@ -380,280 +617,26 @@ module ZMQ
380
617
  rc
381
618
  end
382
619
 
383
- # Queues the message for transmission. Message is assumed to conform to the
384
- # same public API as #Message.
385
- #
386
- # +flags+ may take two values:
387
- # * 0 (default) - blocking operation
388
- # * ZMQ::NOBLOCK - non-blocking operation
389
- # * ZMQ::SNDMORE - this message is part of a multi-part message
390
- #
391
- # Returns 0 when the message was successfully enqueued.
392
- # Returns -1 under two conditions.
393
- # 1. The message could not be enqueued
394
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
395
- #
396
- # With a -1 return code, the user must check ZMQ.errno to determine the
397
- # cause.
398
- #
399
- # The application code is responsible for handling the +message+ object
400
- # lifecycle when #send returns. Regardless of the return code, the user
401
- # is responsible for calling message.close to free the memory in use.
402
- #
403
- def send message, flags = 0
404
- LibZMQ.zmq_send @socket, message.address, flags
405
- end
406
-
407
- # Helper method to make a new #Message instance out of the +message_string+ passed
408
- # in for transmission.
409
- #
410
- # +flags+ may be ZMQ::NOBLOCK.
411
- #
412
- # Returns 0 when the message was successfully enqueued.
413
- # Returns -1 under two conditions.
414
- # 1. The message could not be enqueued
415
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
416
- #
417
- # With a -1 return code, the user must check ZMQ.errno to determine the
418
- # cause.
419
- #
420
- def send_string message_string, flags = 0
421
- message = Message.new message_string
422
- send_and_close message, flags
423
- end
424
-
425
- # Send a sequence of strings as a multipart message out of the +parts+
426
- # passed in for transmission. Every element of +parts+ should be
427
- # a String.
428
- #
429
- # +flags+ may be ZMQ::NOBLOCK.
430
- #
431
- # Returns 0 when the message was successfully enqueued.
432
- # Returns -1 under two conditions.
433
- # 1. The message could not be enqueued
434
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
435
- #
436
- # With a -1 return code, the user must check ZMQ.errno to determine the
437
- # cause.
438
- #
439
- def send_strings parts, flags = 0
440
- return -1 if !parts || parts.empty?
441
-
442
- parts[0..-2].each do |part|
443
- rc = send_string part, flags | ZMQ::SNDMORE
444
- return rc unless Util.resultcode_ok?(rc)
445
- end
446
-
447
- send_string parts[-1], flags
448
- end
449
-
450
- # Send a sequence of messages as a multipart message out of the +parts+
451
- # passed in for transmission. Every element of +parts+ should be
452
- # a Message (or subclass).
453
- #
454
- # +flags+ may be ZMQ::NOBLOCK.
455
- #
456
- # Returns 0 when the message was successfully enqueued.
457
- # Returns -1 under two conditions.
458
- # 1. The message could not be enqueued
459
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
460
- #
461
- # With a -1 return code, the user must check ZMQ.errno to determine the
462
- # cause.
463
- #
464
- def sendmsgs parts, flags = 0
465
- return -1 if !parts || parts.empty?
466
-
467
- parts[0..-2].each do |part|
468
- rc = send part, flags | ZMQ::SNDMORE
469
- return rc unless Util.resultcode_ok?(rc)
470
- end
471
-
472
- send parts[-1], flags
473
- end
474
-
475
- # Sends a message. This will automatically close the +message+ for both successful
476
- # and failed sends.
477
- #
478
- # Returns 0 when the message was successfully enqueued.
479
- # Returns -1 under two conditions.
480
- # 1. The message could not be enqueued
481
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
482
- #
483
- # With a -1 return code, the user must check ZMQ.errno to determine the
484
- # cause.
485
- #
486
- def send_and_close message, flags = 0
487
- rc = send message, flags
488
- message.close
489
- rc
490
- end
491
-
492
- # Dequeues a message from the underlying queue. By default, this is a blocking operation.
493
- #
494
- # +flags+ may take two values:
495
- # 0 (default) - blocking operation
496
- # ZMQ::NOBLOCK - non-blocking operation
497
- #
498
- # Returns 0 when the message was successfully dequeued.
499
- # Returns -1 under two conditions.
500
- # 1. The message could not be dequeued
501
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
502
- #
503
- # With a -1 return code, the user must check ZMQ.errno to determine the
504
- # cause.
505
- #
506
- # The application code is responsible for handling the +message+ object lifecycle
507
- # when #recv returns an error code.
508
- #
509
- def recv message, flags = 0
510
- LibZMQ.zmq_recv @socket, message.address, flags
511
- end
512
-
513
- # Converts the received message to a string and replaces the +string+ arg
514
- # contents.
515
- #
516
- # +string+ should be an empty string, .e.g. ''
517
- # +flags+ may be ZMQ::NOBLOCK.
518
- #
519
- # Returns 0 when the message was successfully dequeued.
520
- # Returns -1 under two conditions.
521
- # 1. The message could not be dequeued
522
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
523
- #
524
- # With a -1 return code, the user must check ZMQ.errno to determine the
525
- # cause.
526
- #
527
- def recv_string string, flags = 0
528
- message = @receiver_klass.new
529
- rc = recv message, flags
530
- string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
531
- message.close
532
- rc
533
- end
534
-
535
- # Receive a multipart message as a list of strings.
536
- #
537
- # +list+ should be an object that responds to #append or #<< so received
538
- # strings can be appended to it
539
- # +flag+ may be ZMQ::NOBLOCK. Any other flag will be removed
540
- #
541
- # Returns 0 when all messages were successfully dequeued.
542
- # Returns -1 under two conditions.
543
- # 1. A message could not be dequeued
544
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
545
- #
546
- # With a -1 return code, the user must check ZMQ.errno to determine the
547
- # cause. Also, the +list+ will not be modified when there was an error.
548
- #
549
- def recv_strings list, flag = 0
550
- array = []
551
- rc = recvmsgs array, flag
552
620
 
553
- if Util.resultcode_ok?(rc)
554
- array.each do |message|
555
- list << message.copy_out_string
556
- message.close
557
- end
558
- end
559
-
560
- rc
561
- end
562
-
563
- # Receive a multipart message as an array of objects
564
- # (by default these are instances of Message).
565
- #
566
- # +list+ should be an object that responds to #append or #<< so received
567
- # messages can be appended to it
568
- # +flag+ may be ZMQ::NOBLOCK. Any other flag will be
569
- # removed.
570
- #
571
- # Returns 0 when all messages were successfully dequeued.
572
- # Returns -1 under two conditions.
573
- # 1. A message could not be dequeued
574
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
575
- #
576
- # With a -1 return code, the user must check ZMQ.errno to determine the
577
- # cause. Also, the +list+ will not be modified when there was an error.
578
- #
579
- def recvmsgs list, flag = 0
580
- flag = NOBLOCK if noblock?(flag)
581
-
582
- message = @receiver_klass.new
583
- rc = recv message, flag
584
-
585
- if Util.resultcode_ok?(rc)
586
- list << message
587
-
588
- # check rc *first*; necessary because the call to #more_parts? can reset
589
- # the zmq_errno to a weird value, so the zmq_errno that was set on the
590
- # call to #recv gets lost
591
- while Util.resultcode_ok?(rc) && more_parts?
592
- message = @receiver_klass.new
593
- rc = recv message, flag
594
-
595
- if Util.resultcode_ok?(rc)
596
- list << message
597
- else
598
- message.close
599
- list.each { |msg| msg.close }
600
- list.clear
601
- end
602
- end
603
- else
604
- message.close
605
- end
621
+ private
606
622
 
607
- rc
623
+ def __sendmsg__(socket, address, flags)
624
+ LibZMQ.zmq_send(socket, address, flags)
608
625
  end
609
626
 
610
- # Should only be used for XREQ, XREP, DEALER and ROUTER type sockets. Takes
611
- # a +list+ for receiving the message body parts and a +routing_envelope+
612
- # for receiving the message parts comprising the 0mq routing information.
613
- #
614
- # Returns 0 when all messages were successfully dequeued.
615
- # Returns -1 under two conditions.
616
- # 1. A message could not be dequeued
617
- # 2. When +flags+ is set with ZMQ::NOBLOCK and the socket returned EAGAIN.
618
- #
619
- # With a -1 return code, the user must check ZMQ.errno to determine the
620
- # cause. Also, the +list+ *may* be modified when there was an error.
621
- #
622
- def recv_multipart list, routing_envelope, flag = 0
623
- parts = []
624
- rc = recvmsgs parts, flag
625
-
626
- if Util.resultcode_ok?(rc)
627
- routing = true
628
- parts.each do |part|
629
- if routing
630
- routing_envelope << part
631
- routing = part.size > 0
632
- else
633
- list << part
634
- end
635
- end
636
- end
637
-
638
- rc
627
+ def __recvmsg__(socket, address, flags)
628
+ LibZMQ.zmq_recv(socket, address, flags)
639
629
  end
640
630
 
631
+ def populate_option_lookup
632
+ super()
641
633
 
642
- private
634
+ # integer options
635
+ [RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
643
636
 
644
- def noblock? flags
645
- (NOBLOCK & flags) == NOBLOCK
637
+ # long long options
638
+ [HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
646
639
  end
647
-
648
- def populate_option_lookup
649
- super()
650
-
651
- # integer options
652
- [RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
653
-
654
- # long long options
655
- [HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
656
- end
657
640
 
658
641
  # these finalizer-related methods cannot live in the CommonSocketBehavior
659
642
  # module; they *must* be in the class definition directly
@@ -702,6 +685,7 @@ module ZMQ
702
685
  # ZMQ::RECONNECT_IVL - integer measured in milliseconds
703
686
  # ZMQ::BACKLOG - integer
704
687
  # ZMQ::RECOVER_IVL_MSEC - integer measured in milliseconds
688
+ # ZMQ::IPV4ONLY - integer
705
689
  #
706
690
  # Returns 0 when the operation completed successfully.
707
691
  # Returns -1 when this operation failed.
@@ -724,263 +708,45 @@ module ZMQ
724
708
 
725
709
  rc
726
710
  end
727
-
728
- # Queues the message for transmission. Message is assumed to conform to the
729
- # same public API as #Message.
730
- #
731
- # +flags+ may take two values:
732
- # * 0 (default) - blocking operation
733
- # * ZMQ::DONTWAIT - non-blocking operation
734
- # * ZMQ::SNDMORE - this message is part of a multi-part message
735
- #
736
- # Returns 0 when the message was successfully enqueued.
737
- # Returns -1 under two conditions.
738
- # 1. The message could not be enqueued
739
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
740
- #
741
- # With a -1 return code, the user must check ZMQ.errno to determine the
742
- # cause.
743
- #
744
- def sendmsg message, flags = 0
745
- LibZMQ.zmq_sendmsg @socket, message.address, flags
746
- end
747
-
748
- # Helper method to make a new #Message instance out of the +string+ passed
749
- # in for transmission.
750
- #
751
- # +flags+ may be ZMQ::DONTWAIT and ZMQ::SNDMORE.
752
- #
753
- # Returns 0 when the message was successfully enqueued.
754
- # Returns -1 under two conditions.
755
- # 1. The message could not be enqueued
756
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
757
- #
758
- # With a -1 return code, the user must check ZMQ.errno to determine the
759
- # cause.
760
- #
761
- def send_string string, flags = 0
762
- message = Message.new string
763
- send_and_close message, flags
764
- end
765
-
766
- # Send a sequence of strings as a multipart message out of the +parts+
767
- # passed in for transmission. Every element of +parts+ should be
768
- # a String.
769
- #
770
- # +flags+ may be ZMQ::DONTWAIT.
771
- #
772
- # Returns 0 when the messages were successfully enqueued.
773
- # Returns -1 under two conditions.
774
- # 1. A message could not be enqueued
775
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
776
- #
777
- # With a -1 return code, the user must check ZMQ.errno to determine the
778
- # cause.
779
- #
780
- def send_strings parts, flags = 0
781
- return -1 if !parts || parts.empty?
782
- flags = DONTWAIT if dontwait?(flags)
783
-
784
- parts[0..-2].each do |part|
785
- rc = send_string part, (flags | ZMQ::SNDMORE)
786
- return rc unless Util.resultcode_ok?(rc)
787
- end
788
-
789
- send_string parts[-1], flags
790
- end
791
-
792
- # Send a sequence of messages as a multipart message out of the +parts+
793
- # passed in for transmission. Every element of +parts+ should be
794
- # a Message (or subclass).
795
- #
796
- # +flags+ may be ZMQ::DONTWAIT.
797
- #
798
- # Returns 0 when the messages were successfully enqueued.
799
- # Returns -1 under two conditions.
800
- # 1. A message could not be enqueued
801
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
802
- #
803
- # With a -1 return code, the user must check ZMQ.errno to determine the
804
- # cause.
805
- #
806
- def sendmsgs parts, flags = 0
807
- return -1 if !parts || parts.empty?
808
- flags = DONTWAIT if dontwait?(flags)
809
-
810
- parts[0..-2].each do |part|
811
- rc = sendmsg part, (flags | ZMQ::SNDMORE)
812
- return rc unless Util.resultcode_ok?(rc)
813
- end
814
-
815
- sendmsg parts[-1], flags
816
- end
817
-
818
- # Sends a message. This will automatically close the +message+ for both successful
819
- # and failed sends.
820
- #
821
- # Returns 0 when the message was successfully enqueued.
822
- # Returns -1 under two conditions.
823
- # 1. The message could not be enqueued
824
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
825
- #
826
- # With a -1 return code, the user must check ZMQ.errno to determine the
827
- # cause.
828
- #
829
- def send_and_close message, flags = 0
830
- rc = sendmsg message, flags
831
- message.close
832
- rc
833
- end
834
-
835
- # Dequeues a message from the underlying queue. By default, this is a blocking operation.
836
- #
837
- # +flags+ may take two values:
838
- # 0 (default) - blocking operation
839
- # ZMQ::DONTWAIT - non-blocking operation
840
- #
841
- # Returns 0 when the message was successfully dequeued.
842
- # Returns -1 under two conditions.
843
- # 1. The message could not be dequeued
844
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
845
- #
846
- # With a -1 return code, the user must check ZMQ.errno to determine the
847
- # cause.
711
+
712
+ # Version3 only
848
713
  #
849
- # The application code is responsible for handling the +message+ object lifecycle
850
- # when #recv returns an error code.
714
+ # Disconnect the socket from the given +endpoint+.
851
715
  #
852
- def recvmsg message, flags = 0
853
- LibZMQ.zmq_recvmsg @socket, message.address, flags
716
+ def disconnect(endpoint)
717
+ LibZMQ.zmq_disconnect(endpoint)
854
718
  end
855
-
856
- # Helper method to make a new #Message instance and convert its payload
857
- # to a string.
858
- #
859
- # +flags+ may be ZMQ::DONTWAIT.
860
- #
861
- # Returns 0 when the message was successfully dequeued.
862
- # Returns -1 under two conditions.
863
- # 1. The message could not be dequeued
864
- # 2. When +flags+ is set with ZMQ::DONTWAIT and the socket returned EAGAIN.
865
- #
866
- # With a -1 return code, the user must check ZMQ.errno to determine the
867
- # cause.
719
+
720
+ # Version3 only
868
721
  #
869
- # The application code is responsible for handling the +message+ object lifecycle
870
- # when #recv returns an error code.
722
+ # Unbind the socket from the given +endpoint+.
871
723
  #
872
- def recv_string string, flags = 0
873
- message = @receiver_klass.new
874
- rc = recvmsg message, flags
875
- string.replace(message.copy_out_string) if Util.resultcode_ok?(rc)
876
- message.close
877
- rc
724
+ def unbind(endpoint)
725
+ LibZMQ.zmq_unbind(endpoint)
878
726
  end
879
727
 
880
- # Receive a multipart message as a list of strings.
881
- #
882
- # +flag+ may be ZMQ::DONTWAIT. Any other flag will be
883
- # removed.
884
- #
885
- def recv_strings list, flag = 0
886
- array = []
887
- rc = recvmsgs array, flag
888
-
889
- if Util.resultcode_ok?(rc)
890
- array.each do |message|
891
- list << message.copy_out_string
892
- message.close
893
- end
894
- end
895
-
896
- rc
897
- end
898
728
 
899
- # Receive a multipart message as an array of objects
900
- # (by default these are instances of Message).
901
- #
902
- # +flag+ may be ZMQ::DONTWAIT. Any other flag will be
903
- # removed.
904
- #
905
- def recvmsgs list, flag = 0
906
- flag = DONTWAIT if dontwait?(flag)
907
-
908
- message = @receiver_klass.new
909
- rc = recvmsg message, flag
910
-
911
- if Util.resultcode_ok?(rc)
912
- list << message
913
-
914
- # check rc *first*; necessary because the call to #more_parts? can reset
915
- # the zmq_errno to a weird value, so the zmq_errno that was set on the
916
- # call to #recv gets lost
917
- while Util.resultcode_ok?(rc) && more_parts?
918
- message = @receiver_klass.new
919
- rc = recvmsg message, flag
920
-
921
- if Util.resultcode_ok?(rc)
922
- list << message
923
- else
924
- message.close
925
- list.each { |msg| msg.close }
926
- list.clear
927
- end
928
- end
929
- else
930
- message.close
931
- end
729
+ private
932
730
 
933
- rc
731
+ def __sendmsg__(socket, address, flags)
732
+ LibZMQ.zmq_sendmsg(socket, address, flags)
934
733
  end
935
734
 
936
- # Should only be used for XREQ, XREP, DEALER and ROUTER type sockets. Takes
937
- # a +list+ for receiving the message body parts and a +routing_envelope+
938
- # for receiving the message parts comprising the 0mq routing information.
939
- #
940
- def recv_multipart list, routing_envelope, flag = 0
941
- parts = []
942
- rc = recvmsgs parts, flag
943
-
944
- if Util.resultcode_ok?(rc)
945
- routing = true
946
- parts.each do |part|
947
- if routing
948
- routing_envelope << part
949
- routing = part.size > 0
950
- else
951
- list << part
952
- end
953
- end
954
- end
955
-
956
- rc
735
+ def __recvmsg__(socket, address, flags)
736
+ LibZMQ.zmq_recvmsg(socket, address, flags)
957
737
  end
958
738
 
739
+ def populate_option_lookup
740
+ super()
959
741
 
960
- private
961
-
962
- def dontwait? flags
963
- (DONTWAIT & flags) == DONTWAIT
742
+ # integer options
743
+ [RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF, IPV4ONLY,
744
+ ROUTER_BEHAVIOR, TCP_KEEPALIVE, TCP_KEEPALIVE_CNT,
745
+ TCP_KEEPALIVE_IDLE, TCP_KEEPALIVE_INTVL, TCP_ACCEPT_FILTER].each { |option| @option_lookup[option] = 0 }
746
+
747
+ # long long options
748
+ [MAXMSGSIZE].each { |option| @option_lookup[option] = 1 }
964
749
  end
965
- alias :noblock? :dontwait?
966
-
967
- def int_option? name
968
- super(name) ||
969
- RECONNECT_IVL_MAX == name ||
970
- RCVHWM == name ||
971
- SNDHWM == name ||
972
- RATE == name ||
973
- RECOVERY_IVL == name ||
974
- SNDBUF == name ||
975
- RCVBUF == name
976
- end
977
-
978
- def populate_option_lookup
979
- super()
980
-
981
- # integer options
982
- [RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 0 }
983
- end
984
750
 
985
751
  # these finalizer-related methods cannot live in the CommonSocketBehavior
986
752
  # module; they *must* be in the class definition directly