omq-backend-rust 0.1.7 → 0.3.0
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 +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +9 -5
- data/lib/omq/backend/rust.rb +14 -7
- data/lib/omq/rust/engine.rb +100 -90
- data/lib/omq/rust/fd_watcher.rb +184 -0
- data/lib/omq/rust/java/engine.rb +642 -0
- data/lib/omq/rust/java/platform.rb +95 -0
- data/lib/omq/rust/version.rb +13 -1
- metadata +11 -19
- data/Cargo.toml +0 -3
- data/ext/omq_backend_rust/Cargo.toml +0 -34
- data/ext/omq_backend_rust/extconf.rb +0 -8
- data/ext/omq_backend_rust/src/error.rs +0 -15
- data/ext/omq_backend_rust/src/lib.rs +0 -26
- data/ext/omq_backend_rust/src/notify.rs +0 -69
- data/ext/omq_backend_rust/src/options.rs +0 -207
- data/ext/omq_backend_rust/src/runtime.rs +0 -493
- data/ext/omq_backend_rust/src/socket.rs +0 -478
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rbconfig"
|
|
4
|
+
|
|
5
|
+
require_relative "../version"
|
|
6
|
+
|
|
7
|
+
module OMQ
|
|
8
|
+
module Rust
|
|
9
|
+
module Java
|
|
10
|
+
class UnsupportedPlatformError < LoadError; end
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def classifier
|
|
14
|
+
override = ENV.fetch("OMQ_JAVA_CLASSIFIER", "").strip
|
|
15
|
+
return validate_classifier(override) unless override.empty?
|
|
16
|
+
|
|
17
|
+
classifier_for(os_name: host_os_name, os_arch: host_os_arch)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def classifier_for(os_name:, os_arch:)
|
|
22
|
+
os = normalize_os(os_name)
|
|
23
|
+
arch = normalize_arch(os_arch)
|
|
24
|
+
|
|
25
|
+
classifier = "#{os}-#{arch}" if os && arch
|
|
26
|
+
return classifier if OMQ::Rust::OMQ_JAVA_CLASSIFIERS.include?(classifier)
|
|
27
|
+
|
|
28
|
+
raise UnsupportedPlatformError,
|
|
29
|
+
"unsupported OMQ.java platform: #{os_name.inspect}/#{os_arch.inspect} " \
|
|
30
|
+
"(supported: #{OMQ::Rust::OMQ_JAVA_CLASSIFIERS.join(", ")})"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def validate_classifier(classifier)
|
|
38
|
+
return classifier if OMQ::Rust::OMQ_JAVA_CLASSIFIERS.include?(classifier)
|
|
39
|
+
|
|
40
|
+
raise UnsupportedPlatformError,
|
|
41
|
+
"unsupported OMQ.java classifier: #{classifier.inspect} " \
|
|
42
|
+
"(supported: #{OMQ::Rust::OMQ_JAVA_CLASSIFIERS.join(", ")})"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def host_os_name
|
|
47
|
+
java_system_property("os.name") ||
|
|
48
|
+
RbConfig::CONFIG["host_os"] ||
|
|
49
|
+
RbConfig::CONFIG["target_os"] ||
|
|
50
|
+
RUBY_PLATFORM
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def host_os_arch
|
|
55
|
+
java_system_property("os.arch") ||
|
|
56
|
+
RbConfig::CONFIG["host_cpu"] ||
|
|
57
|
+
RbConfig::CONFIG["target_cpu"] ||
|
|
58
|
+
RUBY_PLATFORM
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def java_system_property(name)
|
|
63
|
+
return unless RUBY_ENGINE == "jruby"
|
|
64
|
+
|
|
65
|
+
require "java"
|
|
66
|
+
::Java::JavaLang::System.get_property(name)
|
|
67
|
+
rescue LoadError, NameError
|
|
68
|
+
nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def normalize_os(value)
|
|
73
|
+
case value.to_s.downcase
|
|
74
|
+
when /linux/
|
|
75
|
+
"linux"
|
|
76
|
+
when /darwin|mac\s*os|macos/
|
|
77
|
+
"macos"
|
|
78
|
+
when /windows|mswin|mingw|cygwin/
|
|
79
|
+
"windows"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def normalize_arch(value)
|
|
85
|
+
case value.to_s.downcase
|
|
86
|
+
when "amd64", "x64", "x86-64", "x86_64"
|
|
87
|
+
"x86_64"
|
|
88
|
+
when "aarch64", "arm64"
|
|
89
|
+
"aarch64"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
data/lib/omq/rust/version.rb
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module OMQ
|
|
4
|
+
module Backend
|
|
5
|
+
module Rust
|
|
6
|
+
VERSION = "0.3.0"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
4
10
|
module Rust
|
|
5
|
-
|
|
11
|
+
OMQ_JAVA_VERSION = "0.3.0"
|
|
12
|
+
OMQ_JAVA_CLASSIFIERS = [
|
|
13
|
+
"linux-x86_64",
|
|
14
|
+
"macos-aarch64",
|
|
15
|
+
"macos-x86_64",
|
|
16
|
+
"windows-x86_64",
|
|
17
|
+
].freeze
|
|
6
18
|
end
|
|
7
19
|
end
|
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.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -24,44 +24,36 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0.28'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: omq-rs
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0.
|
|
32
|
+
version: '0.1'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
39
|
+
version: '0.1'
|
|
40
40
|
description: Drop-in Rust backend for OMQ. Same socket API (REQ/REP, PUB/SUB, PUSH/PULL,
|
|
41
|
-
DEALER/ROUTER, and all draft types),
|
|
42
|
-
|
|
43
|
-
engine.
|
|
41
|
+
DEALER/ROUTER, and all draft types), backed by the first-class omq-rs Ruby binding.
|
|
42
|
+
Fully interoperable with the default Ruby engine.
|
|
44
43
|
email:
|
|
45
44
|
- paddor@gmail.com
|
|
46
45
|
executables: []
|
|
47
|
-
extensions:
|
|
48
|
-
- ext/omq_backend_rust/extconf.rb
|
|
46
|
+
extensions: []
|
|
49
47
|
extra_rdoc_files: []
|
|
50
48
|
files:
|
|
51
49
|
- CHANGELOG.md
|
|
52
|
-
- Cargo.toml
|
|
53
50
|
- LICENSE
|
|
54
51
|
- README.md
|
|
55
|
-
- ext/omq_backend_rust/Cargo.toml
|
|
56
|
-
- ext/omq_backend_rust/extconf.rb
|
|
57
|
-
- ext/omq_backend_rust/src/error.rs
|
|
58
|
-
- ext/omq_backend_rust/src/lib.rs
|
|
59
|
-
- ext/omq_backend_rust/src/notify.rs
|
|
60
|
-
- ext/omq_backend_rust/src/options.rs
|
|
61
|
-
- ext/omq_backend_rust/src/runtime.rs
|
|
62
|
-
- ext/omq_backend_rust/src/socket.rs
|
|
63
52
|
- lib/omq/backend/rust.rb
|
|
64
53
|
- lib/omq/rust/engine.rb
|
|
54
|
+
- lib/omq/rust/fd_watcher.rb
|
|
55
|
+
- lib/omq/rust/java/engine.rb
|
|
56
|
+
- lib/omq/rust/java/platform.rb
|
|
65
57
|
- lib/omq/rust/version.rb
|
|
66
58
|
homepage: https://github.com/zeromq/omq.rb/tree/main/gems/omq-backend-rust
|
|
67
59
|
licenses:
|
|
@@ -83,5 +75,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
83
75
|
requirements: []
|
|
84
76
|
rubygems_version: 4.0.16
|
|
85
77
|
specification_version: 4
|
|
86
|
-
summary:
|
|
78
|
+
summary: OMQ.rs backend for OMQ.rb
|
|
87
79
|
test_files: []
|
data/Cargo.toml
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "omq_backend_rust"
|
|
3
|
-
version = "0.1.0"
|
|
4
|
-
edition = "2024"
|
|
5
|
-
license = "ISC"
|
|
6
|
-
authors = ["Patrik Wenger <paddor@gmail.com>"]
|
|
7
|
-
publish = false
|
|
8
|
-
|
|
9
|
-
[lib]
|
|
10
|
-
name = "omq_backend_rust"
|
|
11
|
-
crate-type = ["cdylib"]
|
|
12
|
-
|
|
13
|
-
[features]
|
|
14
|
-
default = ["plain", "curve", "lz4", "zstd"]
|
|
15
|
-
plain = ["omq-tokio/plain"]
|
|
16
|
-
curve = ["omq-tokio/curve"]
|
|
17
|
-
lz4 = ["omq-tokio/lz4"]
|
|
18
|
-
zstd = ["omq-tokio/zstd"]
|
|
19
|
-
|
|
20
|
-
[dependencies]
|
|
21
|
-
omq-proto = { version = "=0.25.0", default-features = false }
|
|
22
|
-
omq-tokio = { version = "=0.21.0", default-features = false }
|
|
23
|
-
tokio = { version = "1.52.0", features = ["rt", "rt-multi-thread", "time", "sync", "io-util", "net"] }
|
|
24
|
-
yring = { version = "0.3.11", features = ["async"] }
|
|
25
|
-
|
|
26
|
-
bytes = "1.12.0"
|
|
27
|
-
flume = { version = "0.12", default-features = false, features = ["async"] }
|
|
28
|
-
futures = { version = "0.3", default-features = false, features = ["std", "async-await"] }
|
|
29
|
-
magnus = "0.8"
|
|
30
|
-
rb-sys = "0.9"
|
|
31
|
-
libc = "0.2"
|
|
32
|
-
|
|
33
|
-
[build-dependencies]
|
|
34
|
-
rb-sys = "0.9"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
use magnus::{Error, Ruby};
|
|
2
|
-
use omq_proto::error::Error as OmqError;
|
|
3
|
-
|
|
4
|
-
pub fn map_err(ruby: &Ruby, e: OmqError) -> Error {
|
|
5
|
-
match e {
|
|
6
|
-
OmqError::Closed => Error::new(ruby.exception_io_error(), "socket closed"),
|
|
7
|
-
OmqError::Timeout => Error::new(ruby.exception_runtime_error(), "operation timed out"),
|
|
8
|
-
OmqError::Unroutable => Error::new(ruby.exception_runtime_error(), "no route to peer"),
|
|
9
|
-
OmqError::InvalidEndpoint(msg) => Error::new(ruby.exception_arg_error(), msg),
|
|
10
|
-
OmqError::Protocol(msg) => Error::new(ruby.exception_runtime_error(), msg),
|
|
11
|
-
OmqError::Io(e) => Error::new(ruby.exception_runtime_error(), e.to_string()),
|
|
12
|
-
OmqError::HandshakeFailed(msg) => Error::new(ruby.exception_runtime_error(), msg),
|
|
13
|
-
_ => Error::new(ruby.exception_runtime_error(), format!("{e}")),
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
mod error;
|
|
2
|
-
mod notify;
|
|
3
|
-
mod options;
|
|
4
|
-
mod runtime;
|
|
5
|
-
mod socket;
|
|
6
|
-
|
|
7
|
-
use magnus::{Error, Ruby, function, prelude::*};
|
|
8
|
-
|
|
9
|
-
fn set_io_threads(n: usize) {
|
|
10
|
-
socket::set_io_threads(n);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
#[magnus::init]
|
|
14
|
-
fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
15
|
-
unsafe { rb_sys::rb_ext_ractor_safe(true) };
|
|
16
|
-
|
|
17
|
-
let omq = ruby.define_module("OMQ")?;
|
|
18
|
-
let rust = omq.define_module("Rust")?;
|
|
19
|
-
let native = rust.define_module("Native")?;
|
|
20
|
-
|
|
21
|
-
native.define_module_function("io_threads=", function!(set_io_threads, 1))?;
|
|
22
|
-
|
|
23
|
-
socket::register(ruby)?;
|
|
24
|
-
|
|
25
|
-
Ok(())
|
|
26
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
use std::os::fd::RawFd;
|
|
2
|
-
use std::sync::atomic::{AtomicBool, Ordering};
|
|
3
|
-
|
|
4
|
-
pub struct PipeNotify {
|
|
5
|
-
read_fd: RawFd,
|
|
6
|
-
write_fd: RawFd,
|
|
7
|
-
parking: AtomicBool,
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
unsafe impl Send for PipeNotify {}
|
|
11
|
-
unsafe impl Sync for PipeNotify {}
|
|
12
|
-
|
|
13
|
-
impl PipeNotify {
|
|
14
|
-
pub fn new() -> Self {
|
|
15
|
-
let mut fds = [0i32; 2];
|
|
16
|
-
let ret = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC) };
|
|
17
|
-
assert!(
|
|
18
|
-
ret == 0,
|
|
19
|
-
"pipe2 failed: {}",
|
|
20
|
-
std::io::Error::last_os_error()
|
|
21
|
-
);
|
|
22
|
-
Self {
|
|
23
|
-
read_fd: fds[0],
|
|
24
|
-
write_fd: fds[1],
|
|
25
|
-
parking: AtomicBool::new(false),
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
pub fn notify(&self) {
|
|
30
|
-
if self.parking.load(Ordering::Acquire) {
|
|
31
|
-
self.write_byte();
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
pub fn force_wake(&self) {
|
|
36
|
-
self.write_byte();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
pub fn read_fd(&self) -> RawFd {
|
|
40
|
-
self.read_fd
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
pub fn park_begin(&self) {
|
|
44
|
-
self.parking.store(true, Ordering::Release);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
fn write_byte(&self) {
|
|
48
|
-
let val: u8 = 1;
|
|
49
|
-
loop {
|
|
50
|
-
let ret =
|
|
51
|
-
unsafe { libc::write(self.write_fd, &val as *const u8 as *const libc::c_void, 1) };
|
|
52
|
-
if ret >= 0 {
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
if std::io::Error::last_os_error().raw_os_error() != Some(libc::EINTR) {
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
impl Drop for PipeNotify {
|
|
63
|
-
fn drop(&mut self) {
|
|
64
|
-
unsafe {
|
|
65
|
-
libc::close(self.read_fd);
|
|
66
|
-
libc::close(self.write_fd);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
use std::time::Duration;
|
|
2
|
-
|
|
3
|
-
use bytes::Bytes;
|
|
4
|
-
use magnus::{Error, Ruby, TryConvert, r_hash::RHash, value::ReprValue};
|
|
5
|
-
|
|
6
|
-
pub fn build_options(ruby: &Ruby, hash: RHash) -> Result<omq_tokio::Options, Error> {
|
|
7
|
-
let mut opts = omq_tokio::Options::default();
|
|
8
|
-
|
|
9
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "send_hwm")? {
|
|
10
|
-
opts.send_hwm = v.max(0) as u32;
|
|
11
|
-
}
|
|
12
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "recv_hwm")? {
|
|
13
|
-
opts.recv_hwm = v.max(0) as u32;
|
|
14
|
-
}
|
|
15
|
-
if let Some(v) = get_opt::<f64>(ruby, hash, "linger")? {
|
|
16
|
-
opts.linger = if v.is_infinite() {
|
|
17
|
-
None
|
|
18
|
-
} else {
|
|
19
|
-
Some(Duration::from_secs_f64(v))
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
if let Some(v) = get_opt_bytes(ruby, hash, "identity")? {
|
|
23
|
-
if !v.is_empty() {
|
|
24
|
-
opts.identity = Bytes::from(v);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if let Some(v) = get_opt::<bool>(ruby, hash, "router_mandatory")? {
|
|
28
|
-
opts.router_mandatory = v;
|
|
29
|
-
}
|
|
30
|
-
if let Some(v) = get_opt::<bool>(ruby, hash, "conflate")? {
|
|
31
|
-
opts.conflate = v;
|
|
32
|
-
}
|
|
33
|
-
if let Some(v) = get_opt_duration(ruby, hash, "heartbeat_interval")? {
|
|
34
|
-
opts.heartbeat_interval = Some(v);
|
|
35
|
-
}
|
|
36
|
-
if let Some(v) = get_opt_duration(ruby, hash, "heartbeat_ttl")? {
|
|
37
|
-
opts.heartbeat_ttl = Some(v);
|
|
38
|
-
}
|
|
39
|
-
if let Some(v) = get_opt_duration(ruby, hash, "heartbeat_timeout")? {
|
|
40
|
-
opts.heartbeat_timeout = Some(v);
|
|
41
|
-
}
|
|
42
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "max_message_size")? {
|
|
43
|
-
opts.max_message_size = Some(v as usize);
|
|
44
|
-
}
|
|
45
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "sndbuf")? {
|
|
46
|
-
opts.send_buffer_size = Some(v as usize);
|
|
47
|
-
}
|
|
48
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "rcvbuf")? {
|
|
49
|
-
opts.recv_buffer_size = Some(v as usize);
|
|
50
|
-
}
|
|
51
|
-
if let Some(v) = get_opt_bytes(ruby, hash, "compression_dict")? {
|
|
52
|
-
if !v.is_empty() {
|
|
53
|
-
opts.compression_dict = Some(Bytes::from(v));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if let Some(v) = get_opt::<bool>(ruby, hash, "compression_auto_train")? {
|
|
57
|
-
opts.compression_auto_train = v;
|
|
58
|
-
}
|
|
59
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_threshold")? {
|
|
60
|
-
opts.compression_threshold = Some(v as usize);
|
|
61
|
-
}
|
|
62
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_level")? {
|
|
63
|
-
opts.compression_level = Some(v as i32);
|
|
64
|
-
}
|
|
65
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_dict_capacity")? {
|
|
66
|
-
opts.compression_dict_capacity = Some(v as usize);
|
|
67
|
-
}
|
|
68
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "max_recv_dict_size")? {
|
|
69
|
-
opts.max_recv_dict_size = Some(v as usize);
|
|
70
|
-
}
|
|
71
|
-
if let Some(v) = get_opt::<i64>(ruby, hash, "compression_offload_threshold")? {
|
|
72
|
-
opts.compression_offload_threshold = if v < 0 { None } else { Some(v as usize) };
|
|
73
|
-
}
|
|
74
|
-
if let Some(v) = get_opt::<String>(ruby, hash, "on_mute")? {
|
|
75
|
-
opts.on_mute = match v.as_str() {
|
|
76
|
-
"drop_newest" | "drop" => omq_tokio::OnMute::DropNewest,
|
|
77
|
-
_ => omq_tokio::OnMute::Block,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if let Some(v) = get_opt::<f64>(ruby, hash, "reconnect_interval")? {
|
|
82
|
-
opts.reconnect = omq_proto::options::ReconnectPolicy::Fixed(Duration::from_secs_f64(v));
|
|
83
|
-
}
|
|
84
|
-
if let Some(min) = get_opt::<f64>(ruby, hash, "reconnect_interval_min")? {
|
|
85
|
-
let max = get_opt::<f64>(ruby, hash, "reconnect_interval_max")?.unwrap_or(min * 16.0);
|
|
86
|
-
opts.reconnect = omq_proto::options::ReconnectPolicy::Exponential {
|
|
87
|
-
min: Duration::from_secs_f64(min),
|
|
88
|
-
max: Duration::from_secs_f64(max),
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if let Some(mech_type) = get_opt::<String>(ruby, hash, "mechanism_type")? {
|
|
93
|
-
apply_mechanism(ruby, hash, &mech_type, &mut opts)?;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
Ok(opts)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
fn apply_mechanism(
|
|
100
|
-
ruby: &Ruby,
|
|
101
|
-
hash: RHash,
|
|
102
|
-
mech_type: &str,
|
|
103
|
-
opts: &mut omq_tokio::Options,
|
|
104
|
-
) -> Result<(), Error> {
|
|
105
|
-
match mech_type {
|
|
106
|
-
"null" => {}
|
|
107
|
-
|
|
108
|
-
#[cfg(feature = "curve")]
|
|
109
|
-
"curve" => {
|
|
110
|
-
let is_server = get_opt::<bool>(ruby, hash, "mechanism_server")?.unwrap_or(false);
|
|
111
|
-
let pub_key = get_opt_bytes(ruby, hash, "mechanism_public_key")?;
|
|
112
|
-
let sec_key = get_opt_bytes(ruby, hash, "mechanism_secret_key")?;
|
|
113
|
-
|
|
114
|
-
if is_server {
|
|
115
|
-
if let (Some(pk), Some(sk)) = (pub_key, sec_key) {
|
|
116
|
-
let keypair = omq_proto::CurveKeypair {
|
|
117
|
-
public: omq_proto::CurvePublicKey::from_bytes(to_32(
|
|
118
|
-
ruby,
|
|
119
|
-
&pk,
|
|
120
|
-
"public key",
|
|
121
|
-
)?),
|
|
122
|
-
secret: omq_proto::CurveSecretKey::from_bytes(to_32(
|
|
123
|
-
ruby,
|
|
124
|
-
&sk,
|
|
125
|
-
"secret key",
|
|
126
|
-
)?),
|
|
127
|
-
};
|
|
128
|
-
opts.mechanism = omq_proto::MechanismSetup::CurveServer {
|
|
129
|
-
our_keypair: keypair,
|
|
130
|
-
options: omq_proto::CurveServerOptions::default(),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
} else {
|
|
134
|
-
let srv_key = get_opt_bytes(ruby, hash, "mechanism_server_key")?;
|
|
135
|
-
if let (Some(pk), Some(sk), Some(svk)) = (pub_key, sec_key, srv_key) {
|
|
136
|
-
let keypair = omq_proto::CurveKeypair {
|
|
137
|
-
public: omq_proto::CurvePublicKey::from_bytes(to_32(
|
|
138
|
-
ruby,
|
|
139
|
-
&pk,
|
|
140
|
-
"public key",
|
|
141
|
-
)?),
|
|
142
|
-
secret: omq_proto::CurveSecretKey::from_bytes(to_32(
|
|
143
|
-
ruby,
|
|
144
|
-
&sk,
|
|
145
|
-
"secret key",
|
|
146
|
-
)?),
|
|
147
|
-
};
|
|
148
|
-
opts.mechanism = omq_proto::MechanismSetup::CurveClient {
|
|
149
|
-
our_keypair: keypair,
|
|
150
|
-
server_public: omq_proto::CurvePublicKey::from_bytes(to_32(
|
|
151
|
-
ruby,
|
|
152
|
-
&svk,
|
|
153
|
-
"server key",
|
|
154
|
-
)?),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
_ => {}
|
|
161
|
-
}
|
|
162
|
-
Ok(())
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
fn to_32(ruby: &Ruby, bytes: &[u8], label: &str) -> Result<[u8; 32], Error> {
|
|
166
|
-
bytes.try_into().map_err(|_| {
|
|
167
|
-
Error::new(
|
|
168
|
-
ruby.exception_arg_error(),
|
|
169
|
-
format!("{label} must be exactly 32 bytes, got {}", bytes.len()),
|
|
170
|
-
)
|
|
171
|
-
})
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
fn get_opt_bytes(ruby: &Ruby, hash: RHash, key: &str) -> Result<Option<Vec<u8>>, Error> {
|
|
175
|
-
let k = ruby.str_new(key);
|
|
176
|
-
match hash.get(k) {
|
|
177
|
-
Some(v) => {
|
|
178
|
-
if v.is_nil() {
|
|
179
|
-
return Ok(None);
|
|
180
|
-
}
|
|
181
|
-
let s = magnus::r_string::RString::try_convert(v)?;
|
|
182
|
-
Ok(Some(unsafe { s.as_slice() }.to_vec()))
|
|
183
|
-
}
|
|
184
|
-
None => Ok(None),
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
fn get_opt<T: TryConvert>(ruby: &Ruby, hash: RHash, key: &str) -> Result<Option<T>, Error> {
|
|
189
|
-
let k = ruby.str_new(key);
|
|
190
|
-
match hash.get(k) {
|
|
191
|
-
Some(v) => {
|
|
192
|
-
if v.is_nil() {
|
|
193
|
-
Ok(None)
|
|
194
|
-
} else {
|
|
195
|
-
Ok(Some(T::try_convert(v)?))
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
None => Ok(None),
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
fn get_opt_duration(ruby: &Ruby, hash: RHash, key: &str) -> Result<Option<Duration>, Error> {
|
|
203
|
-
match get_opt::<f64>(ruby, hash, key)? {
|
|
204
|
-
Some(v) => Ok(Some(Duration::from_secs_f64(v))),
|
|
205
|
-
None => Ok(None),
|
|
206
|
-
}
|
|
207
|
-
}
|