omq-backend-rust 0.3.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f12671673afe657015b59cf65873132c88c5cbb15cf34962b54318fb944310c
4
- data.tar.gz: 3b7de77e6e01dc461fa0aa969870472442a2f9b3b4657fa5b35ca1fe90bd8940
3
+ metadata.gz: ed979a32dfef182642cb03dba149e36843c9e37fed1e75032c439b35d769d145
4
+ data.tar.gz: bd80cf78e629a3b4af1bec1ec6646ea9df635be16c096b1a9d597aed05918d79
5
5
  SHA512:
6
- metadata.gz: 77dda34fcf69ef4d048d74276b1ae5cd455b23086de0a826f751862014e0d048dd8f27ccc2042f5332ff91a5410f11243f687450ca0093e58ab19377b64ec9dd
7
- data.tar.gz: 2536562047da85d828e732a03c5a551a85b2b0774821f3ada32f890ba48f4453696c0243ef5e66248cbdee763623d1cf0f9b45bb74ac5e9aedba6aab014558ed
6
+ metadata.gz: fe616024d998eeae83b17b81bfedba2e49bc542a16b8fb6a4f13df4e6a21f768603e497276817c722a5dd1308c54979ad6b615af0d944d692f2faf78c9c77efc
7
+ data.tar.gz: be283792e7d988030b6d13859b206e10c6c8ae355285809a9282ff40c7b14ae4a7b35fa908a24a3e5daa122040c82073c7f022569d163ce451b80ebb8d37faa5
data/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.3.1] - 2026-10-15
6
+
7
+ ### Fixed
8
+
9
+ - Resolve RADIO subscriber readiness on `join_received` monitor events.
10
+ - Reject unsupported security mechanisms instead of silently using NULL.
11
+ - Forward CURVE authenticators on MRI, TruffleRuby, and JRuby, preserving the
12
+ Ruby `PeerInfo` and crypto public-key types.
13
+ - Reject JRuby authenticator configuration when the OMQ.java callback classes
14
+ are missing from the JVM classpath.
15
+
16
+ ### Changed
17
+
18
+ - Require `omq-rs >= 0.2.5` for native authentication callbacks and REQ/REP
19
+ fixes: reject unrelated REQ replies and bodyless REP requests, and preserve
20
+ REP reply destinations across prefetched requests and disconnects.
21
+
5
22
  ## [0.3.0] - 2026-08-26
6
23
 
7
24
  ### Added
data/README.md CHANGED
@@ -12,8 +12,11 @@ MRI and TruffleRuby, or through OMQ.java on JRuby.
12
12
 
13
13
  ## Install
14
14
 
15
- The `omq-rs` dependency compiles OMQ.rs during installation on MRI and
16
- TruffleRuby. JRuby uses OMQ.java on Java 25 or newer. The Java gem selects the
15
+ The `omq-rs >= 0.2.5` dependency compiles OMQ.rs during installation on MRI
16
+ and TruffleRuby. This minimum includes the REQ/REP envelope and reply-routing
17
+ fixes in `omq-tokio` 0.28.1 and `omq-proto` 0.32.1.
18
+
19
+ JRuby uses OMQ.java on Java 25 or newer. The Java gem selects the
17
20
  matching OMQ.java artifact on Linux x86_64, macOS aarch64, macOS x86_64, and
18
21
  Windows x86_64.
19
22
 
@@ -48,8 +51,7 @@ ensure
48
51
  end
49
52
  ```
50
53
 
51
- The `:rust` backend is fully interoperable with the default `:ruby` backend.
52
- Mix backends freely within the same process.
54
+ Select a backend per socket to exchange ZMTP messages with Ruby and other peers.
53
55
 
54
56
  ## Supported socket types
55
57
 
@@ -62,6 +64,23 @@ SCATTER/GATHER, CHANNEL.
62
64
  - **NULL** (default)
63
65
  - **CURVE** (CurveZMQ, via [Nuckle](https://github.com/paddor/nuckle))
64
66
 
67
+ CURVE authenticators receive `Protocol::ZMTP::PeerInfo`, including a public key
68
+ from the configured crypto backend. As with the Ruby engine, the identity is
69
+ empty during authentication.
70
+
71
+ On JRuby, OMQ.java 0.3.0's JNI callback threads require the platform jar on the
72
+ JVM `CLASSPATH`. For example:
73
+
74
+ ```sh
75
+ CLASSPATH="$HOME/.m2/repository/io/github/paddor/omq-java/0.3.0/omq-java-0.3.0-linux-x86_64.jar" jruby app.rb
76
+ ```
77
+
78
+ Without it, configuring a CURVE authenticator raises `ArgumentError` before
79
+ opening a connection. CURVE without an authenticator does not need this workaround.
80
+
81
+ PLAIN and custom mechanisms raise `ArgumentError` before binding, connecting,
82
+ or sending. They are not supported by this adapter.
83
+
65
84
  ## Compressed transports
66
85
 
67
86
  The Rust backend supports `lz4+tcp://` and `zstd+tcp://`. Compression
@@ -246,7 +246,7 @@ module OMQ
246
246
  if @had_peer && @connections.empty? && !@all_peers_gone.resolved?
247
247
  @all_peers_gone.resolve(true)
248
248
  end
249
- when :subscribe_received
249
+ when :subscribe_received, :join_received
250
250
  @subscriber_joined.resolve(true) unless @subscriber_joined.resolved?
251
251
  end
252
252
 
@@ -372,14 +372,12 @@ module OMQ
372
372
 
373
373
  def extract_mechanism(h)
374
374
  mech = @options.mechanism
375
- case mech
376
- when Protocol::ZMTP::Mechanism::Null
375
+ if mech.nil? || mech.instance_of?(Protocol::ZMTP::Mechanism::Null)
377
376
  h["mechanism_type"] = "null"
377
+ elsif defined?(Protocol::ZMTP::Mechanism::Curve) && mech.instance_of?(Protocol::ZMTP::Mechanism::Curve)
378
+ extract_curve_mechanism(h, mech)
378
379
  else
379
- klass = mech.class.name
380
- if klass&.include?("Curve")
381
- extract_curve_mechanism(h, mech)
382
- end
380
+ raise ArgumentError, "Rust backend does not support security mechanism #{mech.class}"
383
381
  end
384
382
  end
385
383
 
@@ -397,6 +395,15 @@ module OMQ
397
395
  srv_key = mech.instance_variable_get(:@server_public)
398
396
  h["mechanism_server_key"] = srv_key.to_s.b if srv_key
399
397
  end
398
+
399
+ if (authenticator = mech.instance_variable_get(:@authenticator))
400
+ require "protocol/zmtp/z85"
401
+ crypto = mech.instance_variable_get(:@crypto)
402
+ h["curve_auth"] = lambda do |peer|
403
+ public_key = crypto::PublicKey.new(Protocol::ZMTP::Z85.decode(peer.public_key))
404
+ authenticator.call(Protocol::ZMTP::PeerInfo.new(public_key: public_key, identity: ""))
405
+ end
406
+ end
400
407
  end
401
408
 
402
409
 
@@ -426,8 +426,11 @@ module OMQ
426
426
 
427
427
  def apply_mechanism(builder)
428
428
  mech = @options.mechanism
429
- klass = mech.class.name
430
- return unless klass&.include?("Curve")
429
+ return if mech.nil? || mech.instance_of?(Protocol::ZMTP::Mechanism::Null)
430
+
431
+ unless defined?(Protocol::ZMTP::Mechanism::Curve) && mech.instance_of?(Protocol::ZMTP::Mechanism::Curve)
432
+ raise ArgumentError, "Rust backend does not support security mechanism #{mech.class}"
433
+ end
431
434
 
432
435
  require "protocol/zmtp/z85"
433
436
 
@@ -437,13 +440,32 @@ module OMQ
437
440
  )
438
441
 
439
442
  if mech.instance_variable_get(:@as_server)
440
- builder.curveServer(keypair)
443
+ if (authenticator = mech.instance_variable_get(:@authenticator))
444
+ validate_authenticator_classpath!
445
+ crypto = mech.instance_variable_get(:@crypto)
446
+ callback = lambda do |peer|
447
+ public_key = crypto::PublicKey.new(Protocol::ZMTP::Z85.decode(peer.publicKey.orElse(nil)))
448
+ !!authenticator.call(Protocol::ZMTP::PeerInfo.new(public_key: public_key, identity: ""))
449
+ end
450
+ builder.curveServer(keypair, callback)
451
+ else
452
+ builder.curveServer(keypair)
453
+ end
441
454
  else
442
455
  builder.curveClient(keypair, z85_key(mech.instance_variable_get(:@server_public), "server key"))
443
456
  end
444
457
  end
445
458
 
446
459
 
460
+ # OMQ.java's JNI callback threads resolve PeerInfo through the JVM
461
+ # system class loader, which cannot see JRuby's dynamically loaded jars.
462
+ def validate_authenticator_classpath!
463
+ ::Java::JavaLang::Class.forName("io.omq.PeerInfo", false, ::Java::JavaLang::ClassLoader.getSystemClassLoader)
464
+ rescue ::Java::JavaLang::ClassNotFoundException
465
+ raise ArgumentError, "JRuby CURVE authenticators require the OMQ.java jar on the JVM CLASSPATH"
466
+ end
467
+
468
+
447
469
  def z85_key(key, label)
448
470
  raw = key&.to_s&.b
449
471
  raise ArgumentError, "#{label} must be exactly 32 bytes" unless raw&.bytesize == 32
@@ -3,7 +3,7 @@
3
3
  module OMQ
4
4
  module Backend
5
5
  module Rust
6
- VERSION = "0.3.0"
6
+ VERSION = "0.3.1"
7
7
  end
8
8
  end
9
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omq-backend-rust
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger
@@ -29,14 +29,20 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '0.1'
32
+ version: '0.2'
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 0.2.5
33
36
  type: :runtime
34
37
  prerelease: false
35
38
  version_requirements: !ruby/object:Gem::Requirement
36
39
  requirements:
37
40
  - - "~>"
38
41
  - !ruby/object:Gem::Version
39
- version: '0.1'
42
+ version: '0.2'
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 0.2.5
40
46
  description: Drop-in Rust backend for OMQ. Same socket API (REQ/REP, PUB/SUB, PUSH/PULL,
41
47
  DEALER/ROUTER, and all draft types), backed by the first-class omq-rs Ruby binding.
42
48
  Fully interoperable with the default Ruby engine.
@@ -73,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
79
  - !ruby/object:Gem::Version
74
80
  version: '0'
75
81
  requirements: []
76
- rubygems_version: 4.0.16
82
+ rubygems_version: 4.0.20
77
83
  specification_version: 4
78
84
  summary: OMQ.rs backend for OMQ.rb
79
85
  test_files: []