protocol-zmtp 0.4.0 → 0.5.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: f6f3ddb84f7c69bf776e615da15797cb815eaf663f357cf16cff60c744153bc8
4
- data.tar.gz: fd410e2dc417e623254be530230e88fc3e428f62413d6465ee88465c82444b10
3
+ metadata.gz: 0f82192f566af0256273b9dd794ad7032c5b1f3d1b2f8a58c37235847715f6fc
4
+ data.tar.gz: b74e78954d38be3f239d96cbcac676dc564b9ab56dff16f1beff8fbcedb77b8b
5
5
  SHA512:
6
- metadata.gz: 0c84020c35c81c9b9609541019cb7433956bfed7a2bf8fd4ea615ad7560b9aecec5086efbab733576309ff7cb2febb4f5c98bef2388f55a056bcf38c78a0633d
7
- data.tar.gz: 7251f30d057e56f97e6ffa3eb95af5727d7763a04829b3c93580e36998b1aa2591cdc0152ff4d53e7764ea80f75113585513d537147c3de238b498d50f25d15c
6
+ metadata.gz: 985cc52f11cc1ad7d24bdbec3916ee5485bda72a396413b3735254ae97430117b40ae3fd6331107e953c0b99bc3c05a997c368eeae642e64b023dd3d744381eb
7
+ data.tar.gz: 100df0f00b447bbc6799c4468b040f15e8fe633bf25d736b44931683772d5f52a50fa2646e8ce3f4768f6076d47482a9a004944f55f42a3d35720ca3f6ede27e
@@ -95,9 +95,11 @@ module Protocol
95
95
  # @param parts [Array<String>] message frames
96
96
  # @return [void]
97
97
  def send_message(parts)
98
- @mutex.synchronize do
99
- write_frames(parts)
100
- @io.flush
98
+ with_deferred_cancel do
99
+ @mutex.synchronize do
100
+ write_frames(parts)
101
+ @io.flush
102
+ end
101
103
  end
102
104
  end
103
105
 
@@ -108,8 +110,10 @@ module Protocol
108
110
  # @param parts [Array<String>] message frames
109
111
  # @return [void]
110
112
  def write_message(parts)
111
- @mutex.synchronize do
112
- write_frames(parts)
113
+ with_deferred_cancel do
114
+ @mutex.synchronize do
115
+ write_frames(parts)
116
+ end
113
117
  end
114
118
  end
115
119
 
@@ -124,12 +128,14 @@ module Protocol
124
128
  # multi-frame message
125
129
  # @return [void]
126
130
  def write_messages(messages)
127
- @mutex.synchronize do
128
- i = 0
129
- n = messages.size
130
- while i < n
131
- write_frames(messages[i])
132
- i += 1
131
+ with_deferred_cancel do
132
+ @mutex.synchronize do
133
+ i = 0
134
+ n = messages.size
135
+ while i < n
136
+ write_frames(messages[i])
137
+ i += 1
138
+ end
133
139
  end
134
140
  end
135
141
  end
@@ -141,8 +147,10 @@ module Protocol
141
147
  # @param wire_bytes [String] ZMTP wire-format bytes
142
148
  # @return [void]
143
149
  def write_wire(wire_bytes)
144
- @mutex.synchronize do
145
- @io.write(wire_bytes)
150
+ with_deferred_cancel do
151
+ @mutex.synchronize do
152
+ @io.write(wire_bytes)
153
+ end
146
154
  end
147
155
  end
148
156
 
@@ -191,13 +199,15 @@ module Protocol
191
199
  # @param command [Codec::Command]
192
200
  # @return [void]
193
201
  def send_command(command)
194
- @mutex.synchronize do
195
- if @mechanism.encrypted?
196
- @io.write(@mechanism.encrypt(command.to_body, command: true))
197
- else
198
- @io.write(command.to_frame.to_wire)
202
+ with_deferred_cancel do
203
+ @mutex.synchronize do
204
+ if @mechanism.encrypted?
205
+ @io.write(@mechanism.encrypt(command.to_body, command: true))
206
+ else
207
+ @io.write(command.to_frame.to_wire)
208
+ end
209
+ @io.flush
199
210
  end
200
- @io.flush
201
211
  end
202
212
  end
203
213
 
@@ -266,6 +276,26 @@ module Protocol
266
276
 
267
277
  private
268
278
 
279
+ # Defers task cancellation around a block of wire writes so the
280
+ # peer never sees a half-written frame. Without this, an
281
+ # +Async::Cancel+ arriving between the header write and the body
282
+ # write (the unencrypted path issues two separate +@io.write+
283
+ # calls per frame) would desync the peer's framer
284
+ # unrecoverably.
285
+ #
286
+ # When called outside an Async task (test fixtures, blocking
287
+ # callers), the block runs directly -- there is no task to defer
288
+ # on. Cancellation arriving from inside the block (peer
289
+ # disconnect raising +EPIPE+/+EOFError+) propagates normally.
290
+ def with_deferred_cancel
291
+ if defined?(Async::Task) && (task = Async::Task.current?)
292
+ task.defer_cancel { yield }
293
+ else
294
+ yield
295
+ end
296
+ end
297
+
298
+
269
299
  # Writes message parts as ZMTP frames, encrypting if needed.
270
300
  #
271
301
  # For the unencrypted path, writes the frame header and body
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Protocol
4
4
  module ZMTP
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.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.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger