protocol-zmtp 0.6.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe0884f347da68db2bbd04949c944108a997d67f545e511e5a74973a84c1d359
4
- data.tar.gz: ff1542dd2feffb84db290fc1dacb8e06d10da80282619c342a59d8d239388125
3
+ metadata.gz: c147d32b0109fa000aadcd519b73c1e808996aee42b0565e4fd1840af28c984d
4
+ data.tar.gz: 83ec8f366229b893b6347f5cb62a2651980d1408da473e2c629a9a01098feeeb
5
5
  SHA512:
6
- metadata.gz: 41b15de98c2e4f0ed6db44f9cf9d9524e4dac42c1f01bf75652a363c9afbedc1af755b7531e113e32abea1a3fd64f164446190c81e036a172989868b5bd712a0
7
- data.tar.gz: 7325e3b59a72b14776128de68361f0507ebfca31d52646aadd1688b6b022e8b04fa9308c3b8a2da7ddccccaaa1d5ed81d58f9f8a0f15a308fd0e196f8b45ceb9
6
+ metadata.gz: 96984a2b7e2a30b792ca73b066fdcaf79a1661b65397d139e97bf6e92f4ad9b234357e0610bd7025dff29812fad88753b0875f2b7f3be8c3bffffe4ae042274c
7
+ data.tar.gz: a320a61ed574017490604a1fd80959a11655292135e3f370321c07eefdbf00e2b1f21bd0e3df712d3d3d3158399c8128c7515eb91641c53bca543874fa0467ca
@@ -70,17 +70,21 @@ module Protocol
70
70
  end
71
71
 
72
72
 
73
- # Builds a READY command with Socket-Type, Identity, and optional X-QoS properties.
73
+ # Builds a READY command with Socket-Type, Identity, optional X-QoS,
74
+ # and any extra properties supplied by upper layers (e.g. an
75
+ # extension that injects an `X-Compression` property).
74
76
  #
75
77
  # @param qos [Integer] QoS level (0 = omitted)
76
78
  # @param qos_hash [String] supported hash algorithms in preference order (e.g. "xXsS")
79
+ # @param metadata [Hash{String => String}] additional READY properties
77
80
  # @return [Command]
78
- def self.ready(socket_type:, identity: "", qos: 0, qos_hash: "")
81
+ def self.ready(socket_type:, identity: "", qos: 0, qos_hash: "", metadata: nil)
79
82
  props = { "Socket-Type" => socket_type, "Identity" => identity }
80
83
  if qos > 0
81
84
  props["X-QoS"] = qos.to_s
82
85
  props["X-QoS-Hash"] = qos_hash unless qos_hash.empty?
83
86
  end
87
+ props.merge!(metadata) if metadata && !metadata.empty?
84
88
  new("READY", encode_properties(props))
85
89
  end
86
90
 
@@ -24,6 +24,10 @@ module Protocol
24
24
  # @return [String] peer's supported hash algorithms in preference order
25
25
  attr_reader :peer_qos_hash
26
26
 
27
+ # @return [Hash{String => String}, nil] full peer READY property hash
28
+ # (set after a successful handshake; nil before)
29
+ attr_reader :peer_properties
30
+
27
31
  # @return [Object] transport IO (#read_exactly, #write, #flush, #close)
28
32
  attr_reader :io
29
33
 
@@ -47,6 +51,7 @@ module Protocol
47
51
  @peer_identity = nil
48
52
  @peer_qos = nil
49
53
  @peer_qos_hash = nil
54
+ @peer_properties = nil
50
55
  @qos = qos
51
56
  @qos_hash = qos_hash
52
57
  @mutex = Mutex.new
@@ -78,6 +83,7 @@ module Protocol
78
83
  @peer_identity = result[:peer_identity]
79
84
  @peer_qos = result[:peer_qos] || 0
80
85
  @peer_qos_hash = result[:peer_qos_hash] || ""
86
+ @peer_properties = result[:peer_properties]
81
87
 
82
88
  unless @peer_socket_type
83
89
  raise Error, "peer READY missing Socket-Type"
@@ -23,6 +23,10 @@ module Protocol
23
23
  class Curve
24
24
  MECHANISM_NAME = "CURVE"
25
25
 
26
+ # Extra READY/INITIATE properties merged in by extensions
27
+ # (e.g. ZMTP-Zstd's X-Compression). nil = none.
28
+ attr_accessor :metadata
29
+
26
30
 
27
31
  # Nonce prefixes.
28
32
  NONCE_PREFIX_HELLO = "CurveZMQHELLO---"
@@ -96,9 +100,10 @@ module Protocol
96
100
  end
97
101
  end
98
102
 
99
- @session_box = nil
100
- @send_nonce = 0
101
- @recv_nonce = -1
103
+ @session_box = nil
104
+ @send_nonce = 0
105
+ @recv_nonce = -1
106
+ @metadata = nil
102
107
  end
103
108
 
104
109
 
@@ -285,6 +290,7 @@ module Protocol
285
290
  props["X-QoS"] = qos.to_s
286
291
  props["X-QoS-Hash"] = qos_hash unless qos_hash.empty?
287
292
  end
293
+ props.merge!(@metadata) if @metadata
288
294
  metadata = Codec::Command.encode_properties(props)
289
295
 
290
296
  initiate_box_plaintext = "".b
@@ -336,7 +342,13 @@ module Protocol
336
342
  @recv_nonce = 0
337
343
  init_nonce_buffers!
338
344
 
339
- { peer_socket_type: peer_socket_type, peer_identity: peer_identity, peer_qos: peer_qos, peer_qos_hash: peer_qos_hash }
345
+ {
346
+ peer_socket_type: peer_socket_type,
347
+ peer_identity: peer_identity,
348
+ peer_qos: peer_qos,
349
+ peer_qos_hash: peer_qos_hash,
350
+ peer_properties: props,
351
+ }
340
352
  end
341
353
 
342
354
 
@@ -474,6 +486,7 @@ module Protocol
474
486
  ready_props["X-QoS"] = qos.to_s
475
487
  ready_props["X-QoS-Hash"] = qos_hash unless qos_hash.empty?
476
488
  end
489
+ ready_props.merge!(@metadata) if @metadata
477
490
  ready_metadata = Codec::Command.encode_properties(ready_props)
478
491
 
479
492
  r_short_nonce = [1].pack("Q>")
@@ -500,6 +513,7 @@ module Protocol
500
513
  peer_identity: props["Identity"] || "",
501
514
  peer_qos: (props["X-QoS"] || "0").to_i,
502
515
  peer_qos_hash: props["X-QoS-Hash"] || "",
516
+ peer_properties: props,
503
517
  }
504
518
  end
505
519
 
@@ -11,18 +11,28 @@ module Protocol
11
11
  class Null
12
12
  MECHANISM_NAME = "NULL"
13
13
 
14
+ # Extra READY properties an upper layer (e.g. an OMQ extension)
15
+ # wants this side to advertise. Mutated before #handshake!.
16
+ # @return [Hash{String => String}]
17
+ attr_accessor :metadata
18
+
19
+
20
+ def initialize
21
+ @metadata = nil
22
+ end
23
+
14
24
 
15
25
  # Performs the full NULL handshake over +io+.
16
26
  #
17
27
  # 1. Exchange 64-byte greetings
18
28
  # 2. Validate peer greeting (version, mechanism)
19
- # 3. Exchange READY commands (socket type + identity)
29
+ # 3. Exchange READY commands (socket type + identity + any extras)
20
30
  #
21
31
  # @param io [#read_exactly, #write, #flush] transport IO
22
32
  # @param as_server [Boolean]
23
33
  # @param socket_type [String]
24
34
  # @param identity [String]
25
- # @return [Hash] { peer_socket_type:, peer_identity: }
35
+ # @return [Hash] { peer_socket_type:, peer_identity:, peer_qos:, peer_qos_hash:, peer_properties: }
26
36
  # @raise [Error]
27
37
  def handshake!(io, as_server:, socket_type:, identity:, qos: 0, qos_hash: "")
28
38
  io.write(Codec::Greeting.encode(mechanism: MECHANISM_NAME, as_server: as_server))
@@ -35,7 +45,13 @@ module Protocol
35
45
  raise Error, "unsupported mechanism: #{peer_greeting[:mechanism]}"
36
46
  end
37
47
 
38
- ready_cmd = Codec::Command.ready(socket_type: socket_type, identity: identity, qos: qos, qos_hash: qos_hash)
48
+ ready_cmd = Codec::Command.ready(
49
+ socket_type: socket_type,
50
+ identity: identity,
51
+ qos: qos,
52
+ qos_hash: qos_hash,
53
+ metadata: @metadata,
54
+ )
39
55
  io.write(ready_cmd.to_frame.to_wire)
40
56
  io.flush
41
57
 
@@ -59,7 +75,13 @@ module Protocol
59
75
  raise Error, "peer READY missing Socket-Type"
60
76
  end
61
77
 
62
- { peer_socket_type: peer_socket_type, peer_identity: peer_identity, peer_qos: peer_qos, peer_qos_hash: peer_qos_hash }
78
+ {
79
+ peer_socket_type: peer_socket_type,
80
+ peer_identity: peer_identity,
81
+ peer_qos: peer_qos,
82
+ peer_qos_hash: peer_qos_hash,
83
+ peer_properties: props,
84
+ }
63
85
  end
64
86
 
65
87
 
@@ -16,15 +16,22 @@ module Protocol
16
16
  MECHANISM_NAME = "PLAIN"
17
17
 
18
18
 
19
+ # Extra READY/INITIATE properties an upper layer wants this side to
20
+ # advertise. Mutated before #handshake!.
21
+ # @return [Hash{String => String}]
22
+ attr_accessor :metadata
23
+
24
+
19
25
  # @param username [String] client username (max 255 bytes)
20
26
  # @param password [String] client password (max 255 bytes)
21
27
  # @param authenticator [#call, nil] server-side credential verifier;
22
28
  # called as +authenticator.call(username, password)+ and must return
23
29
  # truthy to accept the connection. When +nil+, all credentials pass.
24
30
  def initialize(username: "", password: "", authenticator: nil)
25
- @username = username
26
- @password = password
27
- @authenticator = authenticator
31
+ @username = username
32
+ @password = password
33
+ @authenticator = authenticator
34
+ @metadata = nil
28
35
  end
29
36
 
30
37
 
@@ -48,9 +55,11 @@ module Protocol
48
55
  end
49
56
 
50
57
  if as_server
51
- server_handshake!(io, socket_type: socket_type, identity: identity, qos: qos, qos_hash: qos_hash)
58
+ server_handshake! io, socket_type: socket_type, identity: identity,
59
+ qos: qos, qos_hash: qos_hash
52
60
  else
53
- client_handshake!(io, socket_type: socket_type, identity: identity, qos: qos, qos_hash: qos_hash)
61
+ client_handshake! io, socket_type: socket_type, identity: identity,
62
+ qos: qos, qos_hash: qos_hash
54
63
  end
55
64
  end
56
65
 
@@ -70,11 +79,17 @@ module Protocol
70
79
  cmd = read_command(io)
71
80
  raise Error, "expected WELCOME, got #{cmd.name}" unless cmd.name == "WELCOME"
72
81
 
73
- props = { "Socket-Type" => socket_type, "Identity" => identity }
82
+ props = {
83
+ "Socket-Type" => socket_type,
84
+ "Identity" => identity
85
+ }
86
+
74
87
  if qos > 0
75
88
  props["X-QoS"] = qos.to_s
76
89
  props["X-QoS-Hash"] = qos_hash unless qos_hash.empty?
77
90
  end
91
+
92
+ props.merge!(@metadata) if @metadata && !@metadata.empty?
78
93
  initiate = Codec::Command.new("INITIATE", Codec::Command.encode_properties(props))
79
94
  send_command(io, initiate)
80
95
 
@@ -102,7 +117,9 @@ module Protocol
102
117
 
103
118
  peer_info = extract_peer_info(cmd)
104
119
 
105
- send_command(io, Codec::Command.ready(socket_type: socket_type, identity: identity, qos: qos, qos_hash: qos_hash))
120
+ ready = Codec::Command.ready socket_type: socket_type, identity: identity,
121
+ qos: qos, qos_hash: qos_hash, metadata: @metadata
122
+ send_command io, ready
106
123
 
107
124
  peer_info
108
125
  end
@@ -146,7 +163,13 @@ module Protocol
146
163
 
147
164
  raise Error, "peer command missing Socket-Type" unless peer_socket_type
148
165
 
149
- { peer_socket_type: peer_socket_type, peer_identity: props["Identity"] || "", peer_qos: (props["X-QoS"] || "0").to_i, peer_qos_hash: props["X-QoS-Hash"] || "" }
166
+ {
167
+ peer_socket_type: peer_socket_type,
168
+ peer_identity: props["Identity"] || "",
169
+ peer_qos: (props["X-QoS"] || "0").to_i,
170
+ peer_qos_hash: props["X-QoS-Hash"] || "",
171
+ peer_properties: props
172
+ }
150
173
  end
151
174
 
152
175
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Protocol
4
4
  module ZMTP
5
- VERSION = "0.6.0"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-zmtp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger