omq 0.1.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 +7 -0
- data/CHANGELOG.md +30 -0
- data/LICENSE +15 -0
- data/README.md +145 -0
- data/lib/omq/pair.rb +13 -0
- data/lib/omq/pub_sub.rb +77 -0
- data/lib/omq/push_pull.rb +21 -0
- data/lib/omq/req_rep.rb +23 -0
- data/lib/omq/router_dealer.rb +36 -0
- data/lib/omq/socket.rb +178 -0
- data/lib/omq/version.rb +5 -0
- data/lib/omq/zmtp/codec/command.rb +207 -0
- data/lib/omq/zmtp/codec/frame.rb +104 -0
- data/lib/omq/zmtp/codec/greeting.rb +96 -0
- data/lib/omq/zmtp/codec.rb +18 -0
- data/lib/omq/zmtp/connection.rb +233 -0
- data/lib/omq/zmtp/engine.rb +339 -0
- data/lib/omq/zmtp/mechanism/null.rb +70 -0
- data/lib/omq/zmtp/options.rb +57 -0
- data/lib/omq/zmtp/reactor.rb +142 -0
- data/lib/omq/zmtp/readable.rb +29 -0
- data/lib/omq/zmtp/routing/dealer.rb +57 -0
- data/lib/omq/zmtp/routing/fan_out.rb +89 -0
- data/lib/omq/zmtp/routing/pair.rb +68 -0
- data/lib/omq/zmtp/routing/pub.rb +62 -0
- data/lib/omq/zmtp/routing/pull.rb +48 -0
- data/lib/omq/zmtp/routing/push.rb +57 -0
- data/lib/omq/zmtp/routing/rep.rb +83 -0
- data/lib/omq/zmtp/routing/req.rb +70 -0
- data/lib/omq/zmtp/routing/round_robin.rb +69 -0
- data/lib/omq/zmtp/routing/router.rb +88 -0
- data/lib/omq/zmtp/routing/sub.rb +80 -0
- data/lib/omq/zmtp/routing/xpub.rb +74 -0
- data/lib/omq/zmtp/routing/xsub.rb +80 -0
- data/lib/omq/zmtp/routing.rb +38 -0
- data/lib/omq/zmtp/transport/inproc.rb +299 -0
- data/lib/omq/zmtp/transport/ipc.rb +114 -0
- data/lib/omq/zmtp/transport/tcp.rb +98 -0
- data/lib/omq/zmtp/valid_peers.rb +21 -0
- data/lib/omq/zmtp/writable.rb +44 -0
- data/lib/omq/zmtp.rb +47 -0
- data/lib/omq.rb +19 -0
- metadata +110 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "uri"
|
|
5
|
+
require "io/stream"
|
|
6
|
+
|
|
7
|
+
module OMQ
|
|
8
|
+
module ZMTP
|
|
9
|
+
module Transport
|
|
10
|
+
# TCP transport using Ruby sockets with Async.
|
|
11
|
+
#
|
|
12
|
+
module TCP
|
|
13
|
+
class << self
|
|
14
|
+
# Binds a TCP server.
|
|
15
|
+
#
|
|
16
|
+
# @param endpoint [String] e.g. "tcp://127.0.0.1:5555" or "tcp://*:0"
|
|
17
|
+
# @param engine [Engine]
|
|
18
|
+
# @return [Listener]
|
|
19
|
+
#
|
|
20
|
+
def bind(endpoint, engine)
|
|
21
|
+
host, port = parse_endpoint(endpoint)
|
|
22
|
+
host = "0.0.0.0" if host == "*"
|
|
23
|
+
server = TCPServer.new(host, port)
|
|
24
|
+
actual_port = server.local_address.ip_port
|
|
25
|
+
host_part = host.include?(":") ? "[#{host}]" : host
|
|
26
|
+
resolved = "tcp://#{host_part}:#{actual_port}"
|
|
27
|
+
|
|
28
|
+
accept_task = Reactor.spawn_pump do
|
|
29
|
+
loop do
|
|
30
|
+
client = server.accept
|
|
31
|
+
Reactor.run do
|
|
32
|
+
engine.handle_accepted(IO::Stream::Buffered.wrap(client, minimum_write_size: 0), endpoint: resolved)
|
|
33
|
+
rescue => e
|
|
34
|
+
client.close rescue nil
|
|
35
|
+
raise if !e.is_a?(ProtocolError) && !e.is_a?(EOFError)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
rescue IOError
|
|
39
|
+
# server closed
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Listener.new(resolved, server, accept_task, actual_port)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Connects to a TCP endpoint.
|
|
46
|
+
#
|
|
47
|
+
# @param endpoint [String] e.g. "tcp://127.0.0.1:5555"
|
|
48
|
+
# @param engine [Engine]
|
|
49
|
+
# @return [void]
|
|
50
|
+
#
|
|
51
|
+
def connect(endpoint, engine)
|
|
52
|
+
host, port = parse_endpoint(endpoint)
|
|
53
|
+
timeout = engine.options.connect_timeout
|
|
54
|
+
sock = if timeout
|
|
55
|
+
::Socket.tcp(host, port, connect_timeout: timeout)
|
|
56
|
+
else
|
|
57
|
+
TCPSocket.new(host, port)
|
|
58
|
+
end
|
|
59
|
+
engine.handle_connected(IO::Stream::Buffered.wrap(sock, minimum_write_size: 0), endpoint: endpoint)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def parse_endpoint(endpoint)
|
|
65
|
+
uri = URI.parse(endpoint)
|
|
66
|
+
[uri.hostname, uri.port]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# A bound TCP listener.
|
|
71
|
+
#
|
|
72
|
+
class Listener
|
|
73
|
+
# @return [String] resolved endpoint with actual port
|
|
74
|
+
#
|
|
75
|
+
attr_reader :endpoint
|
|
76
|
+
|
|
77
|
+
# @return [Integer] bound port
|
|
78
|
+
#
|
|
79
|
+
attr_reader :port
|
|
80
|
+
|
|
81
|
+
def initialize(endpoint, server, accept_task, port)
|
|
82
|
+
@endpoint = endpoint
|
|
83
|
+
@server = server
|
|
84
|
+
@accept_task = accept_task
|
|
85
|
+
@port = port
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Stops the listener.
|
|
89
|
+
#
|
|
90
|
+
def stop
|
|
91
|
+
@accept_task.stop
|
|
92
|
+
@server.close rescue nil
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OMQ
|
|
4
|
+
module ZMTP
|
|
5
|
+
# Valid socket type peer combinations per ZMTP spec.
|
|
6
|
+
#
|
|
7
|
+
VALID_PEERS = {
|
|
8
|
+
PAIR: %i[PAIR].freeze,
|
|
9
|
+
REQ: %i[REP ROUTER].freeze,
|
|
10
|
+
REP: %i[REQ DEALER].freeze,
|
|
11
|
+
DEALER: %i[REP DEALER ROUTER].freeze,
|
|
12
|
+
ROUTER: %i[REQ DEALER ROUTER].freeze,
|
|
13
|
+
PUB: %i[SUB XSUB].freeze,
|
|
14
|
+
SUB: %i[PUB XPUB].freeze,
|
|
15
|
+
XPUB: %i[SUB XSUB].freeze,
|
|
16
|
+
XSUB: %i[PUB XPUB].freeze,
|
|
17
|
+
PUSH: %i[PULL].freeze,
|
|
18
|
+
PULL: %i[PUSH].freeze,
|
|
19
|
+
}.freeze
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "timeout"
|
|
4
|
+
|
|
5
|
+
module OMQ
|
|
6
|
+
module ZMTP
|
|
7
|
+
# Pure Ruby Writable mixin. Enqueues messages to the engine's send path.
|
|
8
|
+
#
|
|
9
|
+
module Writable
|
|
10
|
+
# Sends a message.
|
|
11
|
+
#
|
|
12
|
+
# @param message [String, Array<String>] message parts
|
|
13
|
+
# @return [self]
|
|
14
|
+
# @raise [IO::TimeoutError] if write_timeout exceeded
|
|
15
|
+
#
|
|
16
|
+
def send(message)
|
|
17
|
+
parts = message.is_a?(Array) ? message : [message]
|
|
18
|
+
raise ArgumentError, "message has no parts" if parts.empty?
|
|
19
|
+
parts = parts.map { |p| p.b.freeze }
|
|
20
|
+
|
|
21
|
+
with_timeout(@options.write_timeout) { @engine.enqueue_send(parts) }
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Sends a message (chainable).
|
|
26
|
+
#
|
|
27
|
+
# @param message [String, Array<String>]
|
|
28
|
+
# @return [self]
|
|
29
|
+
#
|
|
30
|
+
def <<(message)
|
|
31
|
+
send(message)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Waits until the socket is writable.
|
|
35
|
+
#
|
|
36
|
+
# @param timeout [Numeric, nil] timeout in seconds
|
|
37
|
+
# @return [true]
|
|
38
|
+
#
|
|
39
|
+
def wait_writable(timeout = @options.write_timeout)
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/omq/zmtp.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OMQ
|
|
4
|
+
# ZMTP 3.1 protocol internals.
|
|
5
|
+
#
|
|
6
|
+
# These classes implement the wire protocol, transports, and routing
|
|
7
|
+
# strategies. They are not part of the public API.
|
|
8
|
+
#
|
|
9
|
+
module ZMTP
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Constants
|
|
14
|
+
require_relative "zmtp/valid_peers"
|
|
15
|
+
|
|
16
|
+
# Codec
|
|
17
|
+
require_relative "zmtp/codec"
|
|
18
|
+
|
|
19
|
+
# Transport
|
|
20
|
+
require_relative "zmtp/transport/inproc"
|
|
21
|
+
require_relative "zmtp/transport/tcp"
|
|
22
|
+
require_relative "zmtp/transport/ipc"
|
|
23
|
+
|
|
24
|
+
# Mechanisms
|
|
25
|
+
require_relative "zmtp/mechanism/null"
|
|
26
|
+
|
|
27
|
+
# Core
|
|
28
|
+
require_relative "zmtp/reactor"
|
|
29
|
+
require_relative "zmtp/options"
|
|
30
|
+
require_relative "zmtp/connection"
|
|
31
|
+
require_relative "zmtp/routing"
|
|
32
|
+
require_relative "zmtp/routing/round_robin"
|
|
33
|
+
require_relative "zmtp/routing/fan_out"
|
|
34
|
+
require_relative "zmtp/routing/pair"
|
|
35
|
+
require_relative "zmtp/routing/req"
|
|
36
|
+
require_relative "zmtp/routing/rep"
|
|
37
|
+
require_relative "zmtp/routing/dealer"
|
|
38
|
+
require_relative "zmtp/routing/router"
|
|
39
|
+
require_relative "zmtp/routing/pub"
|
|
40
|
+
require_relative "zmtp/routing/sub"
|
|
41
|
+
require_relative "zmtp/routing/xpub"
|
|
42
|
+
require_relative "zmtp/routing/xsub"
|
|
43
|
+
require_relative "zmtp/routing/push"
|
|
44
|
+
require_relative "zmtp/routing/pull"
|
|
45
|
+
require_relative "zmtp/engine"
|
|
46
|
+
require_relative "zmtp/readable"
|
|
47
|
+
require_relative "zmtp/writable"
|
data/lib/omq.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# OMQ — pure Ruby ZeroMQ (ZMTP 3.1).
|
|
4
|
+
#
|
|
5
|
+
# Socket types live directly under OMQ:: for a clean API:
|
|
6
|
+
# OMQ::PUSH, OMQ::PULL, OMQ::PUB, OMQ::SUB, etc.
|
|
7
|
+
#
|
|
8
|
+
# Protocol internals live under OMQ::ZMTP:: and are not part
|
|
9
|
+
# of the public API.
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require_relative "omq/version"
|
|
13
|
+
require_relative "omq/zmtp"
|
|
14
|
+
require_relative "omq/socket"
|
|
15
|
+
require_relative "omq/req_rep"
|
|
16
|
+
require_relative "omq/router_dealer"
|
|
17
|
+
require_relative "omq/pub_sub"
|
|
18
|
+
require_relative "omq/push_pull"
|
|
19
|
+
require_relative "omq/pair"
|
metadata
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: omq
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Patrik Wenger
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: async
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: io-stream
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.11'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.11'
|
|
40
|
+
description: Pure Ruby implementation of the ZMTP 3.1 wire protocol (ZeroMQ) using
|
|
41
|
+
the Async gem. No native libraries required.
|
|
42
|
+
email:
|
|
43
|
+
- paddor@gmail.com
|
|
44
|
+
executables: []
|
|
45
|
+
extensions: []
|
|
46
|
+
extra_rdoc_files: []
|
|
47
|
+
files:
|
|
48
|
+
- CHANGELOG.md
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- lib/omq.rb
|
|
52
|
+
- lib/omq/pair.rb
|
|
53
|
+
- lib/omq/pub_sub.rb
|
|
54
|
+
- lib/omq/push_pull.rb
|
|
55
|
+
- lib/omq/req_rep.rb
|
|
56
|
+
- lib/omq/router_dealer.rb
|
|
57
|
+
- lib/omq/socket.rb
|
|
58
|
+
- lib/omq/version.rb
|
|
59
|
+
- lib/omq/zmtp.rb
|
|
60
|
+
- lib/omq/zmtp/codec.rb
|
|
61
|
+
- lib/omq/zmtp/codec/command.rb
|
|
62
|
+
- lib/omq/zmtp/codec/frame.rb
|
|
63
|
+
- lib/omq/zmtp/codec/greeting.rb
|
|
64
|
+
- lib/omq/zmtp/connection.rb
|
|
65
|
+
- lib/omq/zmtp/engine.rb
|
|
66
|
+
- lib/omq/zmtp/mechanism/null.rb
|
|
67
|
+
- lib/omq/zmtp/options.rb
|
|
68
|
+
- lib/omq/zmtp/reactor.rb
|
|
69
|
+
- lib/omq/zmtp/readable.rb
|
|
70
|
+
- lib/omq/zmtp/routing.rb
|
|
71
|
+
- lib/omq/zmtp/routing/dealer.rb
|
|
72
|
+
- lib/omq/zmtp/routing/fan_out.rb
|
|
73
|
+
- lib/omq/zmtp/routing/pair.rb
|
|
74
|
+
- lib/omq/zmtp/routing/pub.rb
|
|
75
|
+
- lib/omq/zmtp/routing/pull.rb
|
|
76
|
+
- lib/omq/zmtp/routing/push.rb
|
|
77
|
+
- lib/omq/zmtp/routing/rep.rb
|
|
78
|
+
- lib/omq/zmtp/routing/req.rb
|
|
79
|
+
- lib/omq/zmtp/routing/round_robin.rb
|
|
80
|
+
- lib/omq/zmtp/routing/router.rb
|
|
81
|
+
- lib/omq/zmtp/routing/sub.rb
|
|
82
|
+
- lib/omq/zmtp/routing/xpub.rb
|
|
83
|
+
- lib/omq/zmtp/routing/xsub.rb
|
|
84
|
+
- lib/omq/zmtp/transport/inproc.rb
|
|
85
|
+
- lib/omq/zmtp/transport/ipc.rb
|
|
86
|
+
- lib/omq/zmtp/transport/tcp.rb
|
|
87
|
+
- lib/omq/zmtp/valid_peers.rb
|
|
88
|
+
- lib/omq/zmtp/writable.rb
|
|
89
|
+
homepage: https://github.com/paddor/omq
|
|
90
|
+
licenses:
|
|
91
|
+
- ISC
|
|
92
|
+
metadata: {}
|
|
93
|
+
rdoc_options: []
|
|
94
|
+
require_paths:
|
|
95
|
+
- lib
|
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
|
+
requirements:
|
|
98
|
+
- - ">="
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '3.3'
|
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
|
+
requirements:
|
|
103
|
+
- - ">="
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: '0'
|
|
106
|
+
requirements: []
|
|
107
|
+
rubygems_version: 4.0.6
|
|
108
|
+
specification_version: 4
|
|
109
|
+
summary: OMQ — pure Ruby ZeroMQ (ZMTP 3.1)
|
|
110
|
+
test_files: []
|