cztop 1.0.0 → 1.1.0.pre1

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/coverage.yml +20 -0
  3. data/.github/workflows/draft_api.yml +27 -0
  4. data/.github/workflows/{main.yml → stable_api.yml} +6 -6
  5. data/.rubocop.yml +175 -0
  6. data/CHANGES.md +8 -1
  7. data/Gemfile +5 -0
  8. data/README.md +3 -1
  9. data/ci/install-libczmq +22 -0
  10. data/ci/install-libzmq +22 -0
  11. data/cztop.gemspec +3 -2
  12. data/lib/cztop/actor.rb +55 -26
  13. data/lib/cztop/authenticator.rb +18 -9
  14. data/lib/cztop/beacon.rb +22 -10
  15. data/lib/cztop/cert_store.rb +8 -2
  16. data/lib/cztop/certificate.rb +47 -18
  17. data/lib/cztop/config/comments.rb +14 -3
  18. data/lib/cztop/config/serialization.rb +25 -5
  19. data/lib/cztop/config/traversing.rb +44 -13
  20. data/lib/cztop/config.rb +23 -9
  21. data/lib/cztop/frame.rb +23 -10
  22. data/lib/cztop/has_ffi_delegate.rb +11 -1
  23. data/lib/cztop/message/frames.rb +16 -2
  24. data/lib/cztop/message.rb +36 -22
  25. data/lib/cztop/metadata.rb +35 -24
  26. data/lib/cztop/monitor.rb +14 -5
  27. data/lib/cztop/poller/aggregated.rb +31 -15
  28. data/lib/cztop/poller/zmq.rb +25 -22
  29. data/lib/cztop/poller/zpoller.rb +18 -6
  30. data/lib/cztop/poller.rb +43 -18
  31. data/lib/cztop/polymorphic_zsock_methods.rb +6 -1
  32. data/lib/cztop/proxy.rb +34 -19
  33. data/lib/cztop/send_receive_methods.rb +5 -1
  34. data/lib/cztop/socket/types.rb +128 -22
  35. data/lib/cztop/socket.rb +23 -18
  36. data/lib/cztop/version.rb +5 -1
  37. data/lib/cztop/z85/padded.rb +12 -3
  38. data/lib/cztop/z85/pipe.rb +40 -17
  39. data/lib/cztop/z85.rb +17 -6
  40. data/lib/cztop/zap.rb +57 -32
  41. data/lib/cztop/zsock_options.rb +155 -122
  42. data/lib/cztop.rb +2 -1
  43. metadata +28 -10
  44. data/.ruby-version +0 -1
@@ -1,29 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  class Socket
5
+
3
6
  # Socket types. Each constant in this namespace holds the type code used
4
7
  # for the zsock_new() function.
5
8
  module Types
6
- PAIR = 0
7
- PUB = 1
8
- SUB = 2
9
- REQ = 3
10
- REP = 4
9
+
10
+ PAIR = 0
11
+ PUB = 1
12
+ SUB = 2
13
+ REQ = 3
14
+ REP = 4
11
15
  DEALER = 5
12
16
  ROUTER = 6
13
- PULL = 7
14
- PUSH = 8
15
- XPUB = 9
16
- XSUB = 10
17
+ PULL = 7
18
+ PUSH = 8
19
+ XPUB = 9
20
+ XSUB = 10
17
21
  STREAM = 11
18
22
  SERVER = 12
19
23
  CLIENT = 13
24
+
20
25
  end
21
26
 
27
+
22
28
  # All the available type codes, mapped to their Symbol equivalent.
23
29
  # @return [Hash<Integer, Symbol>]
24
- TypeNames = Hash[
25
- Types.constants.map { |name| i = Types.const_get(name); [ i, name ] }
26
- ].freeze
30
+ TypeNames = Types.constants.to_h do |name|
31
+ i = Types.const_get(name)
32
+ [i, name]
33
+ end.freeze
34
+
27
35
 
28
36
  # @param type [Symbol, Integer] type from {Types} or like +:PUB+
29
37
  # @return [REQ, REP, PUSH, PULL, ... ] the new socket
@@ -33,75 +41,108 @@ module CZTop
33
41
  def self.new_by_type(type)
34
42
  case type
35
43
  when Integer
36
- type_code = type
37
- type_name = TypeNames[type_code] or
38
- raise ArgumentError, "invalid type %p" % type
44
+ type_code = type
45
+ type_name = TypeNames[type_code] or
46
+ raise ArgumentError, format('invalid type %p', type)
39
47
  type_class = Socket.const_get(type_name)
40
48
  when Symbol
41
- type_code = Types.const_get(type)
49
+ type_code = Types.const_get(type)
42
50
  type_class = Socket.const_get(type)
43
51
  else
44
- raise ArgumentError, "invalid socket type: %p" % type
52
+ raise ArgumentError, format('invalid socket type: %p', type)
45
53
  end
46
54
  ffi_delegate = Zsock.new(type_code)
47
- sock = type_class.allocate
55
+ sock = type_class.allocate
48
56
  sock.attach_ffi_delegate(ffi_delegate)
49
57
  sock
50
58
  end
51
59
 
60
+
61
+ def initialize(endpoints = nil); end
62
+
63
+
52
64
  # Client socket for the ZeroMQ Client-Server Pattern.
53
65
  # @see http://rfc.zeromq.org/spec:41
54
66
  class CLIENT < Socket
67
+
55
68
  # @param endpoints [String] endpoints to connect to
56
69
  def initialize(endpoints = nil)
70
+ super
71
+
57
72
  attach_ffi_delegate(Zsock.new_client(endpoints))
58
73
  end
74
+
59
75
  end
60
76
 
77
+
61
78
  # Server socket for the ZeroMQ Client-Server Pattern.
62
79
  # @see http://rfc.zeromq.org/spec:41
63
80
  class SERVER < Socket
81
+
64
82
  # @param endpoints [String] endpoints to bind to
65
83
  def initialize(endpoints = nil)
84
+ super
85
+
66
86
  attach_ffi_delegate(Zsock.new_server(endpoints))
67
87
  end
88
+
68
89
  end
69
90
 
91
+
70
92
  # Request socket for the ZeroMQ Request-Reply Pattern.
71
93
  # @see http://rfc.zeromq.org/spec:28
72
94
  class REQ < Socket
95
+
73
96
  # @param endpoints [String] endpoints to connect to
74
97
  def initialize(endpoints = nil)
98
+ super
99
+
75
100
  attach_ffi_delegate(Zsock.new_req(endpoints))
76
101
  end
102
+
77
103
  end
78
104
 
105
+
79
106
  # Reply socket for the ZeroMQ Request-Reply Pattern.
80
107
  # @see http://rfc.zeromq.org/spec:28
81
108
  class REP < Socket
109
+
82
110
  # @param endpoints [String] endpoints to bind to
83
111
  def initialize(endpoints = nil)
112
+ super
113
+
84
114
  attach_ffi_delegate(Zsock.new_rep(endpoints))
85
115
  end
116
+
86
117
  end
87
118
 
119
+
88
120
  # Dealer socket for the ZeroMQ Request-Reply Pattern.
89
121
  # @see http://rfc.zeromq.org/spec:28
90
122
  class DEALER < Socket
123
+
91
124
  # @param endpoints [String] endpoints to connect to
92
125
  def initialize(endpoints = nil)
126
+ super
127
+
93
128
  attach_ffi_delegate(Zsock.new_dealer(endpoints))
94
129
  end
130
+
95
131
  end
96
132
 
133
+
97
134
  # Router socket for the ZeroMQ Request-Reply Pattern.
98
135
  # @see http://rfc.zeromq.org/spec:28
99
136
  class ROUTER < Socket
137
+
100
138
  # @param endpoints [String] endpoints to bind to
101
139
  def initialize(endpoints = nil)
140
+ super
141
+
102
142
  attach_ffi_delegate(Zsock.new_router(endpoints))
103
143
  end
104
144
 
145
+
105
146
  # Send a message to a specific receiver. This is a shorthand for when
106
147
  # you send a message to a specific receiver with no hops in between.
107
148
  # @param receiver [String] receiving peer's socket identity
@@ -110,32 +151,42 @@ module CZTop
110
151
  # destroyed.
111
152
  def send_to(receiver, message)
112
153
  message = Message.coerce(message)
113
- message.prepend "" # separator frame
154
+ message.prepend '' # separator frame
114
155
  message.prepend receiver # receiver envelope
115
156
  self << message
116
157
  end
158
+
117
159
  end
118
160
 
161
+
119
162
  # Publish socket for the ZeroMQ Publish-Subscribe Pattern.
120
163
  # @see http://rfc.zeromq.org/spec:29
121
164
  class PUB < Socket
165
+
122
166
  # @param endpoints [String] endpoints to bind to
123
167
  def initialize(endpoints = nil)
168
+ super
169
+
124
170
  attach_ffi_delegate(Zsock.new_pub(endpoints))
125
171
  end
172
+
126
173
  end
127
174
 
175
+
128
176
  # Subscribe socket for the ZeroMQ Publish-Subscribe Pattern.
129
177
  # @see http://rfc.zeromq.org/spec:29
130
178
  class SUB < Socket
179
+
131
180
  # @param endpoints [String] endpoints to connect to
132
181
  # @param subscription [String] what to subscribe to
133
182
  def initialize(endpoints = nil, subscription = nil)
183
+ super(endpoints)
184
+
134
185
  attach_ffi_delegate(Zsock.new_sub(endpoints, subscription))
135
186
  end
136
187
 
137
188
  # @return [String] subscription prefix to subscribe to everything
138
- EVERYTHING = ""
189
+ EVERYTHING = ''
139
190
 
140
191
  # Subscribes to the given prefix string.
141
192
  # @param prefix [String] prefix string to subscribe to
@@ -144,86 +195,128 @@ module CZTop
144
195
  ffi_delegate.set_subscribe(prefix)
145
196
  end
146
197
 
198
+
147
199
  # Unsubscribes from the given prefix.
148
200
  # @param prefix [String] prefix string to unsubscribe from
149
201
  # @return [void]
150
202
  def unsubscribe(prefix)
151
203
  ffi_delegate.set_unsubscribe(prefix)
152
204
  end
205
+
153
206
  end
154
207
 
208
+
155
209
  # Extended publish socket for the ZeroMQ Publish-Subscribe Pattern.
156
210
  # @see http://rfc.zeromq.org/spec:29
157
211
  class XPUB < Socket
212
+
158
213
  # @param endpoints [String] endpoints to bind to
159
214
  def initialize(endpoints = nil)
215
+ super
216
+
160
217
  attach_ffi_delegate(Zsock.new_xpub(endpoints))
161
218
  end
219
+
162
220
  end
163
221
 
222
+
164
223
  # Extended subscribe socket for the ZeroMQ Publish-Subscribe Pattern.
165
224
  # @see http://rfc.zeromq.org/spec:29
166
225
  class XSUB < Socket
226
+
167
227
  # @param endpoints [String] endpoints to connect to
168
228
  def initialize(endpoints = nil)
229
+ super
230
+
169
231
  attach_ffi_delegate(Zsock.new_xsub(endpoints))
170
232
  end
233
+
171
234
  end
172
235
 
236
+
173
237
  # Push socket for the ZeroMQ Pipeline Pattern.
174
238
  # @see http://rfc.zeromq.org/spec:30
175
239
  class PUSH < Socket
240
+
176
241
  # @param endpoints [String] endpoints to connect to
177
242
  def initialize(endpoints = nil)
243
+ super
244
+
178
245
  attach_ffi_delegate(Zsock.new_push(endpoints))
179
246
  end
247
+
180
248
  end
181
249
 
250
+
182
251
  # Pull socket for the ZeroMQ Pipeline Pattern.
183
252
  # @see http://rfc.zeromq.org/spec:30
184
253
  class PULL < Socket
254
+
185
255
  # @param endpoints [String] endpoints to bind to
186
256
  def initialize(endpoints = nil)
257
+ super
258
+
187
259
  attach_ffi_delegate(Zsock.new_pull(endpoints))
188
260
  end
261
+
189
262
  end
190
263
 
264
+
191
265
  # Pair socket for inter-thread communication.
192
266
  # @see http://rfc.zeromq.org/spec:31
193
267
  class PAIR < Socket
268
+
194
269
  # @param endpoints [String] endpoints to connect to
195
270
  def initialize(endpoints = nil)
271
+ super
272
+
196
273
  attach_ffi_delegate(Zsock.new_pair(endpoints))
197
274
  end
275
+
198
276
  end
199
277
 
278
+
200
279
  # Stream socket for the native pattern. This is useful when
201
280
  # communicating with a non-ZMQ peer over TCP.
202
281
  # @see http://api.zeromq.org/4-2:zmq-socket#toc16
203
282
  class STREAM < Socket
283
+
204
284
  # @param endpoints [String] endpoints to connect to
205
285
  def initialize(endpoints = nil)
286
+ super
287
+
206
288
  attach_ffi_delegate(Zsock.new_stream(endpoints))
207
289
  end
290
+
208
291
  end
209
292
 
293
+
210
294
  # Group-based pub/sub (vs topic-based). This is the publisher socket.
211
295
  # @see https://github.com/zeromq/libzmq/pull/1727
212
296
  class RADIO < Socket
297
+
213
298
  # @param endpoints [String] endpoints to connect to
214
299
  def initialize(endpoints = nil)
300
+ super
301
+
215
302
  attach_ffi_delegate(Zsock.new_radio(endpoints))
216
303
  end
304
+
217
305
  end
218
306
 
307
+
219
308
  # Group-based pub/sub (vs topic-based). This is the subscriber socket.
220
309
  # @see https://github.com/zeromq/libzmq/pull/1727
221
310
  class DISH < Socket
311
+
222
312
  # @param endpoints [String] endpoints to connect to
223
313
  def initialize(endpoints = nil)
314
+ super
315
+
224
316
  attach_ffi_delegate(Zsock.new_dish(endpoints))
225
317
  end
226
318
 
319
+
227
320
  # Joins the given group.
228
321
  # @param group [String] group to join, up to 15 characters
229
322
  # @return [void]
@@ -232,9 +325,10 @@ module CZTop
232
325
  # @raise [SystemCallError] in case of failure
233
326
  def join(group)
234
327
  rc = ffi_delegate.join(group)
235
- raise_zmq_err("unable to join group %p" % group) if rc == -1
328
+ raise_zmq_err(format('unable to join group %p', group)) if rc == -1
236
329
  end
237
330
 
331
+
238
332
  # Leaves the given group.
239
333
  # @param group [String] group to leave
240
334
  # @return [void]
@@ -242,26 +336,38 @@ module CZTop
242
336
  # @raise [SystemCallError] in case of another failure
243
337
  def leave(group)
244
338
  rc = ffi_delegate.leave(group)
245
- raise_zmq_err("unable to leave group %p" % group) if rc == -1
339
+ raise_zmq_err(format('unable to leave group %p', group)) if rc == -1
246
340
  end
341
+
247
342
  end
248
343
 
344
+
249
345
  # Scatter/gather pattern.
250
346
  # @see https://github.com/zeromq/libzmq/pull/1909
251
347
  class SCATTER < Socket
348
+
252
349
  # @param endpoints [String] endpoints to connect to
253
350
  def initialize(endpoints = nil)
351
+ super
352
+
254
353
  attach_ffi_delegate(Zsock.new_scatter(endpoints))
255
354
  end
355
+
256
356
  end
257
357
 
358
+
258
359
  # Scatter/gather pattern.
259
360
  # @see https://github.com/zeromq/libzmq/pull/1909
260
361
  class GATHER < Socket
362
+
261
363
  # @param endpoints [String] endpoints to connect to
262
364
  def initialize(endpoints = nil)
365
+ super
366
+
263
367
  attach_ffi_delegate(Zsock.new_gather(endpoints))
264
368
  end
369
+
265
370
  end
371
+
266
372
  end
267
373
  end
data/lib/cztop/socket.rb CHANGED
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # Represents a CZMQ::FFI::Zsock.
3
5
  class Socket
6
+
4
7
  include HasFFIDelegate
5
8
  extend CZTop::HasFFIDelegate::ClassMethods
6
9
  include ZsockOptions
@@ -21,6 +24,7 @@ module CZTop
21
24
  cert.apply(self) # NOTE: desired: raises if no secret key in cert
22
25
  end
23
26
 
27
+
24
28
  # Enables CURVE security and makes this socket a CURVE client.
25
29
  # @param client_cert [Certificate] client's certificate, to secure
26
30
  # communication (and be authenticated by the server)
@@ -31,9 +35,7 @@ module CZTop
31
35
  # which means it's not secret anymore
32
36
  # @raise [SystemCallError] if there's no secret key in client_cert
33
37
  def CURVE_client!(client_cert, server_cert)
34
- if server_cert.secret_key
35
- raise SecurityError, "server's secret key not secret"
36
- end
38
+ raise SecurityError, "server's secret key not secret" if server_cert.secret_key
37
39
 
38
40
  client_cert.apply(self) # NOTE: desired: raises if no secret key in cert
39
41
  options.CURVE_serverkey = server_cert.public_key
@@ -41,30 +43,34 @@ module CZTop
41
43
 
42
44
  # @!endgroup
43
45
 
46
+
44
47
  # @return [String] last bound endpoint, if any
45
48
  # @return [nil] if not bound
46
49
  def last_endpoint
47
50
  ffi_delegate.endpoint
48
51
  end
49
52
 
53
+
50
54
  # Connects to an endpoint.
51
55
  # @param endpoint [String]
52
56
  # @return [void]
53
57
  # @raise [ArgumentError] if the endpoint is incorrect
54
58
  def connect(endpoint)
55
- rc = ffi_delegate.connect("%s", :string, endpoint)
56
- raise ArgumentError, "incorrect endpoint: %p" % endpoint if rc == -1
59
+ rc = ffi_delegate.connect('%s', :string, endpoint)
60
+ raise ArgumentError, format('incorrect endpoint: %p', endpoint) if rc == -1
57
61
  end
58
62
 
63
+
59
64
  # Disconnects from an endpoint.
60
65
  # @param endpoint [String]
61
66
  # @return [void]
62
67
  # @raise [ArgumentError] if the endpoint is incorrect
63
68
  def disconnect(endpoint)
64
- rc = ffi_delegate.disconnect("%s", :string, endpoint)
65
- raise ArgumentError, "incorrect endpoint: %p" % endpoint if rc == -1
69
+ rc = ffi_delegate.disconnect('%s', :string, endpoint)
70
+ raise ArgumentError, format('incorrect endpoint: %p', endpoint) if rc == -1
66
71
  end
67
72
 
73
+
68
74
  # Closes and destroys the native socket.
69
75
  # @return [void]
70
76
  # @note Don't try to use it anymore afterwards.
@@ -83,30 +89,29 @@ module CZTop
83
89
  # @return [void]
84
90
  # @raise [SystemCallError] in case of failure
85
91
  def bind(endpoint)
86
- rc = ffi_delegate.bind("%s", :string, endpoint)
87
- raise_zmq_err("unable to bind to %p" % endpoint) if rc == -1
88
- @last_tcp_port = rc if rc > 0
92
+ rc = ffi_delegate.bind('%s', :string, endpoint)
93
+ raise_zmq_err(format('unable to bind to %p', endpoint)) if rc == -1
94
+ @last_tcp_port = rc if rc.positive?
89
95
  end
90
96
 
97
+
91
98
  # Unbinds from an endpoint.
92
99
  # @param endpoint [String]
93
100
  # @return [void]
94
101
  # @raise [ArgumentError] if the endpoint is incorrect
95
102
  def unbind(endpoint)
96
- rc = ffi_delegate.unbind("%s", :string, endpoint)
97
- raise ArgumentError, "incorrect endpoint: %p" % endpoint if rc == -1
103
+ rc = ffi_delegate.unbind('%s', :string, endpoint)
104
+ raise ArgumentError, format('incorrect endpoint: %p', endpoint) if rc == -1
98
105
  end
99
106
 
107
+
100
108
  # Inspects this {Socket}.
101
109
  # @return [String] shows class, native address, and {#last_endpoint}
102
110
  def inspect
103
- "#<%s:0x%x last_endpoint=%p>" % [
104
- self.class,
105
- to_ptr.address,
106
- last_endpoint
107
- ]
111
+ format('#<%s:0x%x last_endpoint=%p>', self.class, to_ptr.address, last_endpoint)
108
112
  rescue Zsock::DestroyedError
109
- "#<%s: invalid>" % self.class
113
+ format('#<%s: invalid>', self.class)
110
114
  end
115
+
111
116
  end
112
117
  end
data/lib/cztop/version.rb CHANGED
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
- VERSION = "1.0.0"
4
+
5
+ VERSION = '1.1.0.pre1'
6
+
3
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Z85 with simple padding. This allows you to {#encode} input of any
2
4
  # length.
3
5
  #
@@ -29,7 +31,9 @@
29
31
  #
30
32
  # @see https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7
31
33
  class CZTop::Z85::Padded < CZTop::Z85
34
+
32
35
  class << self
36
+
33
37
  # Same as {Z85::Padded#encode}, but without the need to create an
34
38
  # instance first.
35
39
  #
@@ -41,6 +45,7 @@ class CZTop::Z85::Padded < CZTop::Z85
41
45
  default.encode(input)
42
46
  end
43
47
 
48
+
44
49
  # Same as {Z85::Padded#decode}, but without the need to create an
45
50
  # instance first.
46
51
  #
@@ -59,6 +64,7 @@ class CZTop::Z85::Padded < CZTop::Z85
59
64
  def default
60
65
  @default ||= CZTop::Z85::Padded.new
61
66
  end
67
+
62
68
  end
63
69
 
64
70
  # Encododes to Z85, with padding if needed.
@@ -72,14 +78,15 @@ class CZTop::Z85::Padded < CZTop::Z85
72
78
  padding_bytes = 4 - (input.bytesize % 4)
73
79
 
74
80
  # if 0, make it 4. we MUST append padding.
75
- padding_bytes = 4 if padding_bytes == 0
81
+ padding_bytes = 4 if padding_bytes.zero?
76
82
 
77
83
  # generate and append padding
78
- padding = [padding_bytes].pack("C") * padding_bytes
84
+ padding = [padding_bytes].pack('C') * padding_bytes
79
85
 
80
86
  super("#{input}#{padding}")
81
87
  end
82
88
 
89
+
83
90
  # Decodes from Z85 with padding.
84
91
  #
85
92
  # @param input [String] Z85 encoded data (including padding, or empty
@@ -88,11 +95,13 @@ class CZTop::Z85::Padded < CZTop::Z85
88
95
  # @raise [SystemCallError] if this fails
89
96
  def decode(input)
90
97
  return super if input.empty?
98
+
91
99
  decoded = super
92
100
 
93
101
  # last byte contains number of padding bytes
94
102
  padding_bytes = decoded.byteslice(-1).ord
95
103
 
96
- decoded.byteslice( 0 ... -padding_bytes )
104
+ decoded.byteslice(0...-padding_bytes)
97
105
  end
106
+
98
107
  end