0mq 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5255703edba3faced3f3cc4cf411691e9a32657d
4
- data.tar.gz: 70d06c893160bc3b09176cdec4626ec565e5637a
3
+ metadata.gz: 620201ac4bf75176a5ab224bd0bf0f0c3598e028
4
+ data.tar.gz: c360991d9cf9aa84873672945bd84252cb191263
5
5
  SHA512:
6
- metadata.gz: 4114dc03d01056936a3bef1d4918e0f192616ee3283b4621d4249d4a4d8bb1dc05cc048ee7bf56a6c1167efc1636050839e59d83a762127d35c85e4df3558c62
7
- data.tar.gz: 9f5f9c14f49b2f34e2018406d173f02627973cdea41f0a09873f99370d226bd8fc8b4ca454f789d50c804d81e6a50b0c73c8602ba3e83107d4c75f820ef71c1c
6
+ metadata.gz: 32f96897d84651bcc51e2e9037401ceb4839963a2523b534cbd9a46ffa6c4bad2f58a7c35e641505bc8a8b924a6153f5342bdd57c73a3cd9dc99f2e94f2572a2
7
+ data.tar.gz: 448432e63a64c0fe205e277c0040cb41fa13e90772b57c9f0b03c7eae8e100f16ae0afe011dd301df7c7f3d34e126e3647b03d2efda86a215ac7fdba736ec034
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # 0mq
2
+ _Works like ZeroMQ. Feels like Ruby._
2
3
 
3
4
  [![Build Status](https://travis-ci.org/jemc/0mq.png)](https://travis-ci.org/jemc/0mq)
4
5
  [![Gem Version](https://badge.fury.io/rb/0mq.png)](http://badge.fury.io/rb/0mq)
@@ -21,10 +22,112 @@ Supported Ruby versions:
21
22
 
22
23
  ## Feature Requests / Bug Reports
23
24
 
24
- File them as issues or pull requests on [the github repository](https://github.com/jemc/0mq).
25
+ File them as issues or pull requests on the [0mq github repository](https://github.com/jemc/0mq).
25
26
 
26
27
  ## Authors
27
28
 
28
29
  - Joe McIlvain
29
30
 
30
31
  - Alex McLain
32
+
33
+ ## Installation / Prerequisites
34
+
35
+ - Requires the [libzmq library](http://zeromq.org/intro:get-the-software).
36
+
37
+ - PGM (multicast) requires compiling libzmq with ./configure --with-pgm
38
+
39
+ - Curve cryptography requires compiling libzmq with [libsodium](https://github.com/jedisct1/libsodium).
40
+
41
+ ## ZeroMQ Documentation
42
+
43
+ - Manual: http://zeromq.org/intro:read-the-manual
44
+
45
+ - API: http://api.zeromq.org/
46
+
47
+ ## Code Examples
48
+
49
+ ### Using The 0mq Gem
50
+
51
+ ``` ruby
52
+ require '0mq'
53
+ ```
54
+
55
+ ### Create A Socket
56
+
57
+ Sockets can be created by specifying the [ZMQ socket type](http://api.zeromq.org/4-0:zmq-socket). Any errors will be raised as exceptions.
58
+
59
+ ``` ruby
60
+ socket = ZMQ::Socket.new ZMQ::PULL
61
+ socket.connect 'tcp://127.0.0.1:10000'
62
+ ```
63
+
64
+ ### Send And Receive Data
65
+
66
+ ``` ruby
67
+ address = 'tcp://127.0.0.1:10000'
68
+
69
+ push = ZMQ::Socket.new ZMQ::PUSH
70
+ push.bind address
71
+
72
+ pull = ZMQ::Socket.new ZMQ::PULL
73
+ pull.connect address
74
+
75
+ push.send_string 'test'
76
+
77
+ string = pull.recv_string
78
+
79
+ puts string
80
+ ```
81
+
82
+ ### Poll A Socket For Data
83
+
84
+ ``` ruby
85
+ address = 'inproc://poll_example'
86
+
87
+ pull = ZMQ::Socket.new ZMQ::PULL
88
+ pull.bind address
89
+
90
+ # Push a message after a delay.
91
+ Thread.new do
92
+ push = ZMQ::Socket.new ZMQ::PUSH
93
+ push.connect address
94
+ sleep 3
95
+
96
+ push.send_string 'test'
97
+ end
98
+
99
+ # Check if pull has any data (it doesn't yet).
100
+ # (Non-blocking demonstration.)
101
+ result = ZMQ::Poll.poll_nonblock pull
102
+ puts "No data available yet." if result.empty?
103
+
104
+ # Do a blocking poll until the pull socket has data.
105
+ ZMQ::Poll.poll pull do |socket, event|
106
+ puts socket.recv_string
107
+ end
108
+ ```
109
+
110
+ ### Proxy Sockets
111
+
112
+ A proxy can be used to funnel multiple endpoints into a single connection.
113
+ See: [Pub-Sub Network with a Proxy](http://zguide.zeromq.org/page:all#The-Dynamic-Discovery-Problem)
114
+
115
+ ```ruby
116
+ # ---------------- ---------------- ---------------- ----------------
117
+ # | Endpoint REQ | --> | Proxy ROUTER | --> | Proxy DEALER | --> | Endpoint REP |
118
+ # ---------------- ---------------- ---------------- ----------------
119
+
120
+ # Create sockets.
121
+ endpoint_req = ZMQ::Socket.new(ZMQ::REQ).tap { |s| s.bind 'inproc://proxy_in' }
122
+ proxy_router = ZMQ::Socket.new(ZMQ::ROUTER).tap { |s| s.connect 'inproc://proxy_in' }
123
+ proxy_dealer = ZMQ::Socket.new(ZMQ::DEALER).tap { |s| s.bind 'inproc://proxy_out' }
124
+ endpoint_rep = ZMQ::Socket.new(ZMQ::REP).tap { |s| s.connect 'inproc://proxy_out' }
125
+
126
+ # Create the proxy.
127
+ Thread.new { ZMQ::Proxy.proxy proxy_router, proxy_dealer }
128
+
129
+ # Send a message.
130
+ endpoint_req.send_string 'test'
131
+
132
+ puts endpoint_rep.recv_string
133
+ ```
data/lib/0mq.rb CHANGED
@@ -6,3 +6,8 @@ require_relative '0mq/context'
6
6
  require_relative '0mq/socket'
7
7
  require_relative '0mq/proxy'
8
8
  require_relative '0mq/poll'
9
+ require_relative '0mq/curve'
10
+ require_relative '0mq/version'
11
+
12
+ # :nodoc:
13
+ module ZMQ; end
@@ -1,22 +1,26 @@
1
1
 
2
2
  module ZMQ
3
3
 
4
+ # The context object encapsulates all the global state associated
5
+ # with the library.
4
6
  class Context
5
- attr_reader :ptr
7
+
8
+ # The FFI pointer to the context.
9
+ attr_reader :pointer
6
10
 
7
11
  def initialize
8
- @ptr = LibZMQ.zmq_ctx_new
12
+ @pointer = LibZMQ.zmq_ctx_new
9
13
  end
10
14
 
11
15
  # Destroy the ØMQ context.
12
16
  def terminate
13
- if @ptr
17
+ if @pointer
14
18
  rc = LibZMQ.version4? ?
15
- LibZMQ.zmq_ctx_term(@ptr) :
16
- LibZMQ.zmq_term(@ptr)
19
+ LibZMQ.zmq_ctx_term(@pointer) :
20
+ LibZMQ.zmq_term(@pointer)
17
21
  ZMQ.error_check true if rc == -1
18
22
 
19
- @ptr = nil
23
+ @pointer = nil
20
24
  end
21
25
  end
22
26
 
@@ -26,8 +30,14 @@ module ZMQ
26
30
  ZMQ::Socket.new type, opts
27
31
  end
28
32
 
33
+ # Returns the context's FFI pointer.
34
+ def to_ptr
35
+ @pointer
36
+ end
37
+
29
38
  end
30
39
 
40
+ # The default context to be used if another context is not provided.
31
41
  DefaultContext = Context.new
32
42
 
33
43
  end
@@ -0,0 +1,26 @@
1
+
2
+ module ZMQ
3
+
4
+ # Secure authentication and confidentiality.
5
+ class Curve
6
+
7
+ # Generate a keypair.
8
+ # Returns a hash with the :public and :private keys.
9
+ def self.keypair
10
+ public_key = FFI::MemoryPointer.new :char, 41, true
11
+ private_key = FFI::MemoryPointer.new :char, 41, true
12
+
13
+ rc = LibZMQ::zmq_curve_keypair public_key, private_key
14
+
15
+ begin
16
+ ZMQ.error_check true if rc==-1
17
+ rescue Errno::EOPNOTSUPP
18
+ raise Errno::EOPNOTSUPP, "Curve requires libzmq to be compiled with libsodium."
19
+ end
20
+
21
+ { public: public_key.read_string, private: private_key.read_string }
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -1,18 +1,24 @@
1
1
 
2
2
  module ZMQ
3
3
 
4
+ # A hash of error number => exception class.
5
+ # Example: 1 => Errno::EPERM
4
6
  ErrorMap = Hash.new
5
7
 
6
8
  Errno.constants
7
- .map { |x| Errno.const_get x }
8
- .select { |x| x.is_a?(Class) && x < SystemCallError }
9
- .each { |x| ErrorMap[x.const_get(:Errno)] = x }
9
+ .map { |x| Errno.const_get x }
10
+ .select { |x| x.is_a?(Class) && x < SystemCallError }
11
+ .each { |x| ErrorMap[x.const_get(:Errno)] = x }
10
12
 
13
+
14
+ # Checks the libzmq global error number and raises it as an exception.
15
+ # Should be used after calling a libzmq resource that returns -1 on error.
16
+ # Example: ZMQ.error_check if rc == -1
11
17
  def self.error_check(adjust_backtrace=false)
12
18
  errno = LibZMQ.zmq_errno
13
19
  return true if errno == 25
14
20
 
15
- # str = LibZMQ.zmq_strerror(errno).read_string
21
+ # TODO: Use adjust_backtrace
16
22
  str = ''
17
23
  raise ErrorMap[errno], str, caller[0...-2]
18
24
  end
@@ -15,7 +15,8 @@ module ZMQ
15
15
  # See #initialize for parameters.
16
16
  # See #run for block and return value.
17
17
  def self.poll(*sockets, &block)
18
- new(*sockets).tap { |poll| poll.run(&block) }
18
+ poller = new *sockets
19
+ poller.run &block
19
20
  end
20
21
 
21
22
  # Non-blocking version of poll.
@@ -58,7 +59,7 @@ module ZMQ
58
59
  # This is an easy way to reconnect PollItem to ZMQ::Socket without
59
60
  # having to store multiple dimensions in the socks hash.
60
61
  @socket_lookup = {}
61
- @socks.each { |socket, event| @socket_lookup[socket.ptr.address] = socket }
62
+ @socks.each { |socket, event| @socket_lookup[socket.to_ptr.address] = socket }
62
63
 
63
64
  # Allocate space for C PollItem (zmq_pollitem_t) structs.
64
65
  @poll_structs = FFI::MemoryPointer.new LibZMQ::PollItem, @socks.count, true
@@ -90,7 +91,7 @@ module ZMQ
90
91
 
91
92
  # Poll
92
93
  rc = LibZMQ::zmq_poll @poll_structs, @poll_items.count, timeout
93
- ZMQ.error_check true if rc==-1
94
+ ZMQ.error_check true if rc == -1
94
95
 
95
96
  # Create a hash of the items with triggered events.
96
97
  # (ZMQ::Socket => revents)
@@ -115,7 +116,10 @@ module ZMQ
115
116
  end
116
117
 
117
118
 
119
+ # :nodoc:
118
120
  module LibZMQ
121
+
122
+ # :nodoc:
119
123
  class PollItem
120
124
 
121
125
  # Get the event flags:
@@ -142,7 +146,7 @@ module LibZMQ
142
146
  # Set the socket to poll for events on.
143
147
  # Accepts a ZMQ::Socket or a pointer.
144
148
  def socket=(sock)
145
- self[:socket] = sock.is_a?(FFI::Pointer) ? sock : sock.ptr
149
+ self[:socket] = sock.is_a?(FFI::Pointer) ? sock : sock.to_ptr
146
150
  end
147
151
 
148
152
  end
@@ -1,12 +1,24 @@
1
1
 
2
2
  module ZMQ
3
3
 
4
+ # The proxy connects a frontend socket to a backend socket. Conceptually,
5
+ # data flows from frontend to backend. Depending on the socket types,
6
+ # replies may flow in the opposite direction. The direction is conceptual
7
+ # only; the proxy is fully symmetric and there is no technical difference
8
+ # between frontend and backend.
4
9
  class Proxy
5
10
 
11
+ # Create a running proxy object.
12
+ def self.proxy(frontend, backend, capture = nil)
13
+ new(frontend, backend, capture).tap { |p| p.run }
14
+ end
15
+
16
+ # Accepts a frontend, backend, and optional capture socket.
17
+ # See http://api.zeromq.org/4-0:zmq-proxy
6
18
  def initialize(frontend, backend, capture = nil)
7
- @frontend = frontend.nil? ? nil : frontend.ptr
8
- @backend = backend.nil? ? nil : backend.ptr
9
- @capture = capture.nil? ? nil : capture.ptr
19
+ @frontend = frontend.nil? ? nil : frontend.to_ptr
20
+ @backend = backend.nil? ? nil : backend.to_ptr
21
+ @capture = capture.nil? ? nil : capture.to_ptr
10
22
  end
11
23
 
12
24
  # Block the current thread with the event loop of the proxy
@@ -3,16 +3,22 @@ require_relative 'socket/options'
3
3
 
4
4
  module ZMQ
5
5
 
6
+ # See http://api.zeromq.org/4-0:zmq-socket
7
+ # Not thread safe.
6
8
  class Socket
7
- attr_reader :ptr
9
+
10
+ # The FFI pointer to the socket.
11
+ attr_reader :pointer
12
+ # The socket's ZMQ::Context.
8
13
  attr_reader :context
14
+ # The socket's ZeroMQ socket type (e.g. ZMQ::ROUTER).
9
15
  attr_reader :type
10
16
 
11
17
  def initialize(type, opts={})
12
18
  @context = opts.fetch :context, ZMQ::DefaultContext
13
19
  @type = type
14
- @ptr = LibZMQ.zmq_socket @context.ptr, @type
15
- ZMQ.error_check true if @ptr.null?
20
+ @pointer = LibZMQ.zmq_socket @context.pointer, @type
21
+ ZMQ.error_check true if @pointer.null?
16
22
 
17
23
  @msgptr = FFI::MemoryPointer.new LibZMQ::Message.size, 1, false
18
24
 
@@ -22,20 +28,20 @@ module ZMQ
22
28
 
23
29
  # Close the socket
24
30
  def close
25
- if @ptr
31
+ if @pointer
26
32
  ObjectSpace.undefine_finalizer self
27
33
  @temp_buffers.clear if @temp_buffers
28
34
 
29
- rc = LibZMQ.zmq_close @ptr
35
+ rc = LibZMQ.zmq_close @pointer
30
36
  ZMQ.error_check true if rc==-1
31
37
 
32
- @ptr = nil
38
+ @pointer = nil
33
39
  end
34
40
  end
35
41
 
36
- # Create a safe finalizer for the socket ptr to close on GC of the object
37
- def self.finalizer(ptr, pid)
38
- Proc.new { LibZMQ.zmq_close ptr if Process.pid == pid }
42
+ # Create a safe finalizer for the socket pointer to close on GC of the object
43
+ def self.finalizer(pointer, pid)
44
+ Proc.new { LibZMQ.zmq_close pointer if Process.pid == pid }
39
45
  end
40
46
 
41
47
  # Get the socket type name as a symbol
@@ -45,25 +51,25 @@ module ZMQ
45
51
 
46
52
  # Bind to an endpoint
47
53
  def bind(endpoint)
48
- rc = LibZMQ.zmq_bind @ptr, endpoint
54
+ rc = LibZMQ.zmq_bind @pointer, endpoint
49
55
  ZMQ.error_check true if rc==-1
50
56
  end
51
57
 
52
58
  # Connect to an endpoint
53
59
  def connect(endpoint)
54
- rc = LibZMQ.zmq_connect @ptr, endpoint
60
+ rc = LibZMQ.zmq_connect @pointer, endpoint
55
61
  ZMQ.error_check true if rc==-1
56
62
  end
57
63
 
58
64
  # Unbind from an endpoint
59
65
  def unbind(endpoint)
60
- rc = LibZMQ.zmq_unbind @ptr, endpoint
66
+ rc = LibZMQ.zmq_unbind @pointer, endpoint
61
67
  ZMQ.error_check true if rc==-1
62
68
  end
63
69
 
64
- # Disconnect to an endpoint
70
+ # Disconnect from an endpoint
65
71
  def disconnect(endpoint)
66
- rc = LibZMQ.zmq_disconnect @ptr, endpoint
72
+ rc = LibZMQ.zmq_disconnect @pointer, endpoint
67
73
  ZMQ.error_check true if rc==-1
68
74
  end
69
75
 
@@ -77,7 +83,7 @@ module ZMQ
77
83
  rc = LibZMQ.zmq_msg_init_data @msgptr, @msgbuf, size, LibC::Free, nil
78
84
  ZMQ.error_check true if rc==-1
79
85
 
80
- rc = LibZMQ.zmq_sendmsg @ptr, @msgptr, flags
86
+ rc = LibZMQ.zmq_sendmsg @pointer, @msgptr, flags
81
87
  ZMQ.error_check true if rc==-1
82
88
 
83
89
  rc = LibZMQ.zmq_msg_close @msgptr
@@ -89,7 +95,7 @@ module ZMQ
89
95
  rc = LibZMQ.zmq_msg_init @msgptr
90
96
  ZMQ.error_check true if rc==-1
91
97
 
92
- rc = LibZMQ.zmq_recvmsg @ptr, @msgptr, flags
98
+ rc = LibZMQ.zmq_recvmsg @pointer, @msgptr, flags
93
99
  ZMQ.error_check true if rc==-1
94
100
 
95
101
  str = LibZMQ.zmq_msg_data(@msgptr)
@@ -163,7 +169,7 @@ module ZMQ
163
169
  value = valptr
164
170
  end
165
171
 
166
- rc = LibZMQ.zmq_setsockopt @ptr, option, value, value.size
172
+ rc = LibZMQ.zmq_setsockopt @pointer, option, value, value.size
167
173
  ZMQ.error_check true if rc==-1
168
174
 
169
175
  value
@@ -176,7 +182,7 @@ module ZMQ
176
182
 
177
183
  value, size = get_opt_pointers type
178
184
 
179
- rc = LibZMQ.zmq_getsockopt @ptr, option, value, size
185
+ rc = LibZMQ.zmq_getsockopt @pointer, option, value, size
180
186
  ZMQ.error_check true if rc==-1
181
187
 
182
188
  if type == :string
@@ -188,6 +194,11 @@ module ZMQ
188
194
  end
189
195
  end
190
196
 
197
+ # Returns the socket's FFI pointer.
198
+ def to_ptr
199
+ @pointer
200
+ end
201
+
191
202
  private
192
203
 
193
204
  def get_opt_pointers(type)
@@ -0,0 +1,102 @@
1
+
2
+ module ZMQ
3
+
4
+ # Returns a ZMQ::Version object containing the libzmq library version.
5
+ def self.version
6
+ ZMQ::Version
7
+ end
8
+
9
+
10
+ # libzmq library version.
11
+ class Version
12
+
13
+ @version = LibZMQ.version
14
+
15
+ private_class_method :new
16
+
17
+ class << self
18
+
19
+ # :nodoc:
20
+ def major
21
+ @version[:major]
22
+ end
23
+
24
+ # :nodoc:
25
+ def minor
26
+ @version[:minor]
27
+ end
28
+
29
+ # :nodoc:
30
+ def patch
31
+ @version[:patch]
32
+ end
33
+
34
+ # :nodoc:
35
+ def to_s
36
+ "#{major}.#{minor}.#{patch}"
37
+ end
38
+
39
+ # :nodoc:
40
+ def inspect
41
+ "#{super} \"#{to_s}\""
42
+ end
43
+
44
+ # Compare this version to another version.
45
+ # Examples: "3.2.0", "3.2", "3", 3
46
+ def <=>(value)
47
+ expression = /(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?/
48
+
49
+ # Convert both versions into an array of [major, minor, patch].
50
+ this_version = self.to_s
51
+ other_version = value.to_s
52
+
53
+ this_version =~ expression
54
+ this_set = $~.captures.map { |item| item.to_i if item }.select { |item| item }
55
+
56
+ other_version =~ expression
57
+ other_set = $~.captures.map { |item| item.to_i if item }.select { |item| item }
58
+
59
+ # Compare each section (major/minor/patch) of the version number.
60
+ other_set.count.times do |i|
61
+ return 1 if this_set[i] > other_set[i]
62
+ return -1 if this_set[i] < other_set[i]
63
+ end
64
+
65
+ 0 # If the iterator didn't return, the versions are equal.
66
+ end
67
+
68
+ # :nodoc:
69
+ def ==(value)
70
+ (self <=> value) == 0 ? true : false
71
+ end
72
+
73
+ # :nodoc:
74
+ def !=(value)
75
+ (self <=> value) != 0 ? true : false
76
+ end
77
+
78
+ # :nodoc:
79
+ def >(value)
80
+ (self <=> value) == 1 ? true : false
81
+ end
82
+
83
+ # :nodoc:
84
+ def >=(value)
85
+ (self <=> value) != -1 ? true : false
86
+ end
87
+
88
+ # :nodoc:
89
+ def <(value)
90
+ (self <=> value) == -1 ? true : false
91
+ end
92
+
93
+ # :nodoc:
94
+ def <=(value)
95
+ (self <=> value) != 1 ? true : false
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+
102
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 0mq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-04 00:00:00.000000000 Z
12
+ date: 2014-03-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi-rzmq-core
@@ -119,11 +119,13 @@ files:
119
119
  - README.md
120
120
  - lib/0mq.rb
121
121
  - lib/0mq/context.rb
122
+ - lib/0mq/curve.rb
122
123
  - lib/0mq/error_map.rb
123
124
  - lib/0mq/poll.rb
124
125
  - lib/0mq/proxy.rb
125
126
  - lib/0mq/socket.rb
126
127
  - lib/0mq/socket/options.rb
128
+ - lib/0mq/version.rb
127
129
  homepage: https://github.com/jemc/0mq/
128
130
  licenses:
129
131
  - MIT