protocol-http2 0.5.2 → 0.6.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: 868932fdb503f3fb6cc3fed243af7019b56e24bb1ac56a42e69132e0dad1af41
4
- data.tar.gz: fb965bc65c34b0ad14f10985c0f21676e1b9a9ceab1052d7482635d5542f461b
3
+ metadata.gz: b5f71a68091b631d1c6a776ae1730539cf753ee6ec24d27dc3b1d739dd971426
4
+ data.tar.gz: ea202fecbfe30bfbe0b9facf5d507f09344a2a959822be6f22d2d082cf273477
5
5
  SHA512:
6
- metadata.gz: d3f8197a22080d609c376e48fd4019aa751b9cf2b845c7d5c9d5f3917e349a09a3ea14d256cac36e815d7126ad72c95a268f754884db200eed006e2f6400d450
7
- data.tar.gz: a9cf712bc5eee80c7d77f3628e7df163b3c253a5910358534d52910f13064b5c197ca815eb248483be429544f2cff0af0ce8a540172143eb44bea2f53223a6f3
6
+ metadata.gz: 9d1a0a6e6a8461e985fcb9dc83e64c622743cb3d05e52d3b72f1b8a0f48d8190ac01417070807ada1d4ee0434dd7daa775d054ca89d54ba2010d6c153d9fad91
7
+ data.tar.gz: a17e3d970e3a2539361f518aff2ccc5ec40ca77f9b639a0b6bd69aabab1d0ade8a2e1f7049c08f5a001acfa9eb2fca4c5f2e785475d09e0c21c8088cec050d97
@@ -31,7 +31,6 @@ module Protocol
31
31
  def initialize(framer, local_stream_id)
32
32
  @state = :new
33
33
  @streams = {}
34
- @closed = 0
35
34
 
36
35
  @framer = framer
37
36
  @local_stream_id = local_stream_id
@@ -76,28 +75,22 @@ module Protocol
76
75
  # Our window for sending data. When we send data, it reduces this window.
77
76
  attr :remote_window
78
77
 
78
+ # The highest stream_id that has been successfully accepted by this connection.
79
+ attr :remote_stream_id
80
+
79
81
  def closed?
80
82
  @state == :closed
81
83
  end
82
84
 
83
- def stream_closed(stream)
84
- @closed += 1
85
- end
86
-
87
- def active_stream_count
88
- @streams.size - @closed
85
+ def active_streams
86
+ @streams.each_value.select(&:active?)
89
87
  end
90
88
 
91
- def connection_error!(error, message)
92
- return if @framer.closed?
93
-
94
- send_goaway(error, message)
95
-
96
- self.close
97
- end
98
-
99
- def close
89
+ # Close the underlying framer and all streams.
90
+ def close(error = nil)
100
91
  @framer.close
92
+
93
+ @streams.each_value{|stream| stream.close(error)}
101
94
  end
102
95
 
103
96
  def encode_headers(headers, buffer = String.new.b)
@@ -121,31 +114,45 @@ module Protocol
121
114
 
122
115
  attr :streams
123
116
 
117
+ # 6.8. GOAWAY
118
+ # There is an inherent race condition between an endpoint starting new streams and the remote sending a GOAWAY frame. To deal with this case, the GOAWAY contains the stream identifier of the last peer-initiated stream that was or might be processed on the sending endpoint in this connection. For instance, if the server sends a GOAWAY frame, the identified stream is the highest-numbered stream initiated by the client.
119
+ # Once sent, the sender will ignore frames sent on streams initiated by the receiver if the stream has an identifier higher than the included last stream identifier. Receivers of a GOAWAY frame MUST NOT open additional streams on the connection, although a new connection can be established for new streams.
120
+ def ignore_frame?(frame)
121
+ if self.closed?
122
+ puts "ignore_frame? #{frame.stream_id} -> #{valid_remote_stream_id?(frame.stream_id)} > #{@remote_stream_id}"
123
+ if valid_remote_stream_id?(frame.stream_id)
124
+ return frame.stream_id > @remote_stream_id
125
+ end
126
+ end
127
+ end
128
+
129
+ # Reads one frame from the network and processes. Processing the frame updates the state of the connection and related streams. If the frame triggers an error, e.g. a protocol error, the connection will typically emit a goaway frame and re-raise the exception. You should continue processing frames until the underlying connection is closed.
124
130
  def read_frame
125
131
  frame = @framer.read_frame(@local_settings.maximum_frame_size)
126
- # puts "#{self.class} #{@state} read_frame: class=#{frame.class} flags=#{frame.flags} length=#{frame.length}"
132
+ # puts "#{self.class} #{@state} read_frame: class=#{frame.class} stream_id=#{frame.stream_id} flags=#{frame.flags} length=#{frame.length} (remote_stream_id=#{@remote_stream_id})"
127
133
  # puts "Windows: local_window=#{@local_window.inspect}; remote_window=#{@remote_window.inspect}"
128
134
 
129
- yield frame if block_given?
135
+ return if ignore_frame?(frame)
130
136
 
137
+ yield frame if block_given?
131
138
  frame.apply(self)
132
139
 
133
140
  return frame
134
- rescue GoawayError
135
- # This is not a connection error. We are done.
136
- self.close
141
+ rescue GoawayError => error
142
+ # Go directly to jail. Do not pass go, do not collect $200.
143
+ self.close(error)
137
144
 
138
145
  raise
139
146
  rescue ProtocolError => error
140
- connection_error!(error.code || PROTOCOL_ERROR, error.message)
147
+ send_goaway(error.code || PROTOCOL_ERROR, error.message)
141
148
 
142
149
  raise
143
150
  rescue HPACK::CompressionError => error
144
- connection_error!(COMPRESSION_ERROR, error.message)
151
+ send_goaway(COMPRESSION_ERROR, error.message)
145
152
 
146
153
  raise
147
154
  rescue
148
- connection_error!(PROTOCOL_ERROR, $!.message)
155
+ send_goaway(PROTOCOL_ERROR, $!.message)
149
156
 
150
157
  raise
151
158
  end
@@ -159,21 +166,31 @@ module Protocol
159
166
  write_frame(frame)
160
167
  end
161
168
 
169
+ # Transition the connection into the closed state.
170
+ def close!
171
+ @state = :closed
172
+
173
+ return self
174
+ end
175
+
176
+ # Tell the remote end that the connection is being shut down. If the `error_code` is 0, this is a graceful shutdown. The other end of the connection should not make any new streams, but existing streams may be completed.
162
177
  def send_goaway(error_code = 0, message = "")
163
178
  frame = GoawayFrame.new
164
179
  frame.pack @remote_stream_id, error_code, message
165
180
 
166
181
  write_frame(frame)
167
182
 
168
- @state = :closed
183
+ self.close!
169
184
  end
170
185
 
171
186
  def receive_goaway(frame)
172
- @state = :closed
187
+ # We capture the last stream that was processed.
188
+ @remote_stream_id, error_code, message = frame.unpack
173
189
 
174
- last_stream_id, error_code, message = frame.unpack
190
+ self.close!
175
191
 
176
192
  if error_code != 0
193
+ # Shut down immediately.
177
194
  raise GoawayError.new(message, error_code)
178
195
  end
179
196
  end
@@ -336,7 +353,7 @@ module Protocol
336
353
  if stream = @streams[frame.stream_id]
337
354
  stream.receive_headers(frame)
338
355
  else
339
- if self.active_stream_count < self.maximum_concurrent_streams
356
+ if self.active_streams.count < self.maximum_concurrent_streams
340
357
  stream = accept_stream(frame.stream_id)
341
358
  stream.receive_headers(frame)
342
359
  else
@@ -90,6 +90,10 @@ module Protocol
90
90
  @connection.streams[@id] = self
91
91
  end
92
92
 
93
+ # The stream is being closed because the connection is being closed.
94
+ def close(error = nil)
95
+ end
96
+
93
97
  # Stream ID (odd for client initiated streams, even otherwise).
94
98
  attr :id
95
99
 
@@ -118,6 +122,10 @@ module Protocol
118
122
  @connection.write_frame(frame)
119
123
  end
120
124
 
125
+ def active?
126
+ @state != :closed && @state != :idle
127
+ end
128
+
121
129
  def closed?
122
130
  @state == :closed
123
131
  end
@@ -217,11 +225,11 @@ module Protocol
217
225
  end
218
226
  end
219
227
 
220
- # This is not the same as a `close` method. If you are looking for that, use `send_stream_reset`.
228
+ # Transition the stream into the closed state.
221
229
  def close!
222
230
  @state = :closed
223
231
 
224
- @connection.stream_closed(self)
232
+ self.close
225
233
  end
226
234
 
227
235
  def send_reset_stream(error_code = 0)
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Protocol
22
22
  module HTTP2
23
- VERSION = "0.5.2"
23
+ VERSION = "0.6.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-http2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams