protocol-http2 0.3.0 → 0.4.1
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/lib/protocol/http2/client.rb +4 -0
- data/lib/protocol/http2/connection.rb +56 -39
- data/lib/protocol/http2/continuation_frame.rb +19 -2
- data/lib/protocol/http2/error.rb +6 -0
- data/lib/protocol/http2/flow_control.rb +10 -2
- data/lib/protocol/http2/frame.rb +14 -2
- data/lib/protocol/http2/framer.rb +3 -2
- data/lib/protocol/http2/ping_frame.rb +2 -2
- data/lib/protocol/http2/server.rb +4 -0
- data/lib/protocol/http2/settings_frame.rb +5 -3
- data/lib/protocol/http2/stream.rb +22 -14
- data/lib/protocol/http2/version.rb +1 -1
- data/lib/protocol/http2/window_update_frame.rb +5 -3
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 59f70b2d8905a24deb2b5f6400347631c226dea2814f23a0701d64ca343c8e7e
         | 
| 4 | 
            +
              data.tar.gz: b6370e82f47701f4eb7ad21049524cf559d7c1303a839a802a88dfc8f2808c16
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f2c32cb5174ed643a415b836a2faa53a325a5e3252e1db55be9fafbc117fd78beb3768b467879f27b146da001caf3a92c74137924e5cf4c9eb86006b7d5a4a42
         | 
| 7 | 
            +
              data.tar.gz: 05a417ab4821acb8e0db930440f8a7583ae265f1dd14363eea42963cc4fb313e413aa91d3c81ca4453a413f5db42ef6934e6c4d76cef5f9ac7b757f5f7c6a67e
         | 
| @@ -50,6 +50,7 @@ module Protocol | |
| 50 50 | 
             
            				0
         | 
| 51 51 | 
             
            			end
         | 
| 52 52 |  | 
| 53 | 
            +
            			# The size of a frame payload is limited by the maximum size that a receiver advertises in the SETTINGS_MAX_FRAME_SIZE setting.
         | 
| 53 54 | 
             
            			def maximum_frame_size
         | 
| 54 55 | 
             
            				@remote_settings.maximum_frame_size
         | 
| 55 56 | 
             
            			end
         | 
| @@ -78,11 +79,15 @@ module Protocol | |
| 78 79 | 
             
            				@state == :closed
         | 
| 79 80 | 
             
            			end
         | 
| 80 81 |  | 
| 81 | 
            -
            			def  | 
| 82 | 
            +
            			def connection_error!(error, message)
         | 
| 82 83 | 
             
            				return if @framer.closed?
         | 
| 83 84 |  | 
| 84 | 
            -
            				send_goaway  | 
| 85 | 
            +
            				send_goaway(error, message)
         | 
| 85 86 |  | 
| 87 | 
            +
            				self.close
         | 
| 88 | 
            +
            			end
         | 
| 89 | 
            +
            			
         | 
| 90 | 
            +
            			def close
         | 
| 86 91 | 
             
            				@framer.close
         | 
| 87 92 | 
             
            			end
         | 
| 88 93 |  | 
| @@ -117,16 +122,21 @@ module Protocol | |
| 117 122 | 
             
            				frame.apply(self)
         | 
| 118 123 |  | 
| 119 124 | 
             
            				return frame
         | 
| 125 | 
            +
            			rescue GoawayError
         | 
| 126 | 
            +
            				# This is not a connection error. We are done.
         | 
| 127 | 
            +
            				self.close
         | 
| 128 | 
            +
            				
         | 
| 129 | 
            +
            				raise
         | 
| 120 130 | 
             
            			rescue ProtocolError => error
         | 
| 121 | 
            -
            				 | 
| 131 | 
            +
            				connection_error!(error.code || PROTOCOL_ERROR, error.message)
         | 
| 122 132 |  | 
| 123 133 | 
             
            				raise
         | 
| 124 134 | 
             
            			rescue HPACK::CompressionError => error
         | 
| 125 | 
            -
            				 | 
| 135 | 
            +
            				connection_error!(COMPRESSION_ERROR, error.message)
         | 
| 126 136 |  | 
| 127 137 | 
             
            				raise
         | 
| 128 138 | 
             
            			rescue
         | 
| 129 | 
            -
            				 | 
| 139 | 
            +
            				connection_error!(PROTOCOL_ERROR, $!.message)
         | 
| 130 140 |  | 
| 131 141 | 
             
            				raise
         | 
| 132 142 | 
             
            			end
         | 
| @@ -236,6 +246,10 @@ module Protocol | |
| 236 246 |  | 
| 237 247 | 
             
            			def receive_ping(frame)
         | 
| 238 248 | 
             
            				if @state != :closed
         | 
| 249 | 
            +
            					if frame.stream_id != 0
         | 
| 250 | 
            +
            						raise ProtocolError, "Ping received for non-zero stream!"
         | 
| 251 | 
            +
            					end
         | 
| 252 | 
            +
            					
         | 
| 239 253 | 
             
            					unless frame.acknowledgement?
         | 
| 240 254 | 
             
            						reply = frame.acknowledge
         | 
| 241 255 |  | 
| @@ -251,17 +265,32 @@ module Protocol | |
| 251 265 |  | 
| 252 266 | 
             
            				if stream = @streams[frame.stream_id]
         | 
| 253 267 | 
             
            					stream.receive_data(frame)
         | 
| 254 | 
            -
            					
         | 
| 255 | 
            -
            					if stream.closed?
         | 
| 256 | 
            -
            						@streams.delete(stream.id)
         | 
| 257 | 
            -
            					end
         | 
| 258 268 | 
             
            				else
         | 
| 259 | 
            -
            					raise ProtocolError, " | 
| 269 | 
            +
            					raise ProtocolError, "Cannot receive data for idle stream #{frame.stream_id}"
         | 
| 260 270 | 
             
            				end
         | 
| 261 271 | 
             
            			end
         | 
| 262 272 |  | 
| 273 | 
            +
            			def valid_remote_stream_id?
         | 
| 274 | 
            +
            				false
         | 
| 275 | 
            +
            			end
         | 
| 276 | 
            +
            			
         | 
| 277 | 
            +
            			# Accept a stream from the other side of the connnection.
         | 
| 278 | 
            +
            			def accept_stream(stream_id)
         | 
| 279 | 
            +
            				unless valid_remote_stream_id?(stream_id)
         | 
| 280 | 
            +
            					raise ProtocolError, "Invalid remote stream id: #{stream_id}"
         | 
| 281 | 
            +
            				end
         | 
| 282 | 
            +
            				
         | 
| 283 | 
            +
            				if stream_id <= @remote_stream_id
         | 
| 284 | 
            +
            					raise ProtocolError, "Invalid stream id: #{stream_id} <= #{@remote_stream_id}!"
         | 
| 285 | 
            +
            				end
         | 
| 286 | 
            +
            				
         | 
| 287 | 
            +
            				@remote_stream_id = stream_id
         | 
| 288 | 
            +
            				create_stream(stream_id)
         | 
| 289 | 
            +
            			end
         | 
| 290 | 
            +
            			
         | 
| 291 | 
            +
            			# Create a stream on this side of the connection.
         | 
| 263 292 | 
             
            			def create_stream(stream_id = next_stream_id)
         | 
| 264 | 
            -
            				Stream.new(self, stream_id)
         | 
| 293 | 
            +
            				@streams[stream_id] = Stream.new(self, stream_id)
         | 
| 265 294 | 
             
            			end
         | 
| 266 295 |  | 
| 267 296 | 
             
            			def receive_headers(frame)
         | 
| @@ -271,49 +300,30 @@ module Protocol | |
| 271 300 |  | 
| 272 301 | 
             
            				if stream = @streams[frame.stream_id]
         | 
| 273 302 | 
             
            					stream.receive_headers(frame)
         | 
| 274 | 
            -
             | 
| 275 | 
            -
            					if stream.closed?
         | 
| 276 | 
            -
            						@streams.delete(stream.id)
         | 
| 277 | 
            -
            					end
         | 
| 278 | 
            -
            				elsif frame.stream_id > @remote_stream_id
         | 
| 303 | 
            +
            				else
         | 
| 279 304 | 
             
            					if @streams.count < self.maximum_concurrent_streams
         | 
| 280 | 
            -
            						stream =  | 
| 305 | 
            +
            						stream = accept_stream(frame.stream_id)
         | 
| 281 306 | 
             
            						stream.receive_headers(frame)
         | 
| 282 | 
            -
            						
         | 
| 283 | 
            -
            						@remote_stream_id = stream.id
         | 
| 284 | 
            -
            						@streams[stream.id] = stream
         | 
| 285 307 | 
             
            					else
         | 
| 286 308 | 
             
            						raise ProtocolError, "Exceeded maximum concurrent streams"
         | 
| 287 309 | 
             
            					end
         | 
| 288 310 | 
             
            				end
         | 
| 289 311 | 
             
            			end
         | 
| 290 312 |  | 
| 291 | 
            -
            			def deleted_stream? frame
         | 
| 292 | 
            -
            				frame.stream_id <= @local_stream_id or frame.stream_id <= @remote_stream_id
         | 
| 293 | 
            -
            			end
         | 
| 294 | 
            -
            			
         | 
| 295 313 | 
             
            			def receive_priority(frame)
         | 
| 296 314 | 
             
            				if stream = @streams[frame.stream_id]
         | 
| 297 315 | 
             
            					stream.receive_priority(frame)
         | 
| 298 | 
            -
            				elsif deleted_stream? frame
         | 
| 299 | 
            -
            					# ignore
         | 
| 300 316 | 
             
            				else
         | 
| 301 | 
            -
            					stream =  | 
| 317 | 
            +
            					stream = accept_stream(frame.stream_id)
         | 
| 302 318 | 
             
            					stream.receive_priority(frame)
         | 
| 303 | 
            -
            					
         | 
| 304 | 
            -
            					@streams[frame.stream_id] = stream
         | 
| 305 319 | 
             
            				end
         | 
| 306 320 | 
             
            			end
         | 
| 307 321 |  | 
| 308 322 | 
             
            			def receive_reset_stream(frame)
         | 
| 309 323 | 
             
            				if stream = @streams[frame.stream_id]
         | 
| 310 324 | 
             
            					stream.receive_reset_stream(frame)
         | 
| 311 | 
            -
            					
         | 
| 312 | 
            -
            					@streams.delete(stream.id)
         | 
| 313 | 
            -
            				elsif deleted_stream? frame
         | 
| 314 | 
            -
            					# ignore
         | 
| 315 325 | 
             
            				else
         | 
| 316 | 
            -
            					raise  | 
| 326 | 
            +
            					raise StreamClosed, "Cannot reset stream #{frame.stream_id}"
         | 
| 317 327 | 
             
            				end
         | 
| 318 328 | 
             
            			end
         | 
| 319 329 |  | 
| @@ -321,11 +331,14 @@ module Protocol | |
| 321 331 | 
             
            				if frame.connection?
         | 
| 322 332 | 
             
            					super
         | 
| 323 333 | 
             
            				elsif stream = @streams[frame.stream_id]
         | 
| 324 | 
            -
            					 | 
| 325 | 
            -
             | 
| 326 | 
            -
            					 | 
| 334 | 
            +
            					begin
         | 
| 335 | 
            +
            						stream.receive_window_update(frame)
         | 
| 336 | 
            +
            					rescue ProtocolError => error
         | 
| 337 | 
            +
            						stream.send_reset_stream(error.code)
         | 
| 338 | 
            +
            					end
         | 
| 327 339 | 
             
            				else
         | 
| 328 | 
            -
            					 | 
| 340 | 
            +
            					# Receiving any frame other than HEADERS or PRIORITY on a stream in this state MUST be treated as a connection error of type PROTOCOL_ERROR.
         | 
| 341 | 
            +
            					raise ProtocolError, "Cannot update window of idle stream #{frame.stream_id}"
         | 
| 329 342 | 
             
            				end
         | 
| 330 343 | 
             
            			end
         | 
| 331 344 |  | 
| @@ -336,8 +349,12 @@ module Protocol | |
| 336 349 | 
             
            				end
         | 
| 337 350 | 
             
            			end
         | 
| 338 351 |  | 
| 352 | 
            +
            			def receive_continuation(frame)
         | 
| 353 | 
            +
            				raise ProtocolError, "Received unexpected continuation: #{frame.class}"
         | 
| 354 | 
            +
            			end
         | 
| 355 | 
            +
            			
         | 
| 339 356 | 
             
            			def receive_frame(frame)
         | 
| 340 | 
            -
            				 | 
| 357 | 
            +
            				# ignore.
         | 
| 341 358 | 
             
            			end
         | 
| 342 359 | 
             
            		end
         | 
| 343 360 | 
             
            	end
         | 
| @@ -37,9 +37,21 @@ module Protocol | |
| 37 37 | 
             
            				super
         | 
| 38 38 |  | 
| 39 39 | 
             
            				unless end_headers?
         | 
| 40 | 
            -
            					 | 
| 40 | 
            +
            					continuation = ContinuationFrame.new
         | 
| 41 | 
            +
            					continuation.read_header(stream)
         | 
| 42 | 
            +
            					
         | 
| 43 | 
            +
            					# We validate the frame type here:
         | 
| 44 | 
            +
            					unless continuation.valid_type?
         | 
| 45 | 
            +
            						raise ProtocolError, "Invalid frame type: #{@type}!"
         | 
| 46 | 
            +
            					end
         | 
| 47 | 
            +
            					
         | 
| 48 | 
            +
            					if continuation.stream_id != @stream_id
         | 
| 49 | 
            +
            						raise ProtocolError, "Invalid stream id: #{continuation.stream_id} for continuation of stream id: #{@stream_id}!"
         | 
| 50 | 
            +
            					end
         | 
| 41 51 |  | 
| 42 | 
            -
            					 | 
| 52 | 
            +
            					continuation.read(stream, maximum_frame_size)
         | 
| 53 | 
            +
            					
         | 
| 54 | 
            +
            					@continuation = continuation
         | 
| 43 55 | 
             
            				end
         | 
| 44 56 | 
             
            			end
         | 
| 45 57 |  | 
| @@ -93,6 +105,11 @@ module Protocol | |
| 93 105 | 
             
            			include Continued
         | 
| 94 106 |  | 
| 95 107 | 
             
            			TYPE = 0x9
         | 
| 108 | 
            +
            			
         | 
| 109 | 
            +
            			# This is only invoked if the continuation is received out of the normal flow.
         | 
| 110 | 
            +
            			def apply(connection)
         | 
| 111 | 
            +
            				connection.receive_continuation(self)
         | 
| 112 | 
            +
            			end
         | 
| 96 113 | 
             
            		end
         | 
| 97 114 | 
             
            	end
         | 
| 98 115 | 
             
            end
         | 
    
        data/lib/protocol/http2/error.rb
    CHANGED
    
    
| @@ -27,6 +27,8 @@ module Protocol | |
| 27 27 | 
             
            				maximum_frame_size = self.maximum_frame_size
         | 
| 28 28 | 
             
            				available_size = @remote_window.available
         | 
| 29 29 |  | 
| 30 | 
            +
            				# puts "available_size=#{available_size} maximum_frame_size=#{maximum_frame_size}"
         | 
| 31 | 
            +
            				
         | 
| 30 32 | 
             
            				if available_size < maximum_frame_size
         | 
| 31 33 | 
             
            					return available_size
         | 
| 32 34 | 
             
            				else
         | 
| @@ -71,8 +73,14 @@ module Protocol | |
| 71 73 | 
             
            			def receive_window_update(frame)
         | 
| 72 74 | 
             
            				was_full = @remote_window.full?
         | 
| 73 75 |  | 
| 74 | 
            -
            				 | 
| 75 | 
            -
            				@remote_window | 
| 76 | 
            +
            				amount = frame.unpack
         | 
| 77 | 
            +
            				# puts "expand remote_window=#{@remote_window} by #{amount}"
         | 
| 78 | 
            +
            				
         | 
| 79 | 
            +
            				if amount != 0
         | 
| 80 | 
            +
            					@remote_window.expand(amount)
         | 
| 81 | 
            +
            				else
         | 
| 82 | 
            +
            					raise ProtocolError, "Invalid window size increment: #{amount}!"
         | 
| 83 | 
            +
            				end
         | 
| 76 84 |  | 
| 77 85 | 
             
            				self.window_updated if was_full
         | 
| 78 86 | 
             
            			end
         | 
    
        data/lib/protocol/http2/frame.rb
    CHANGED
    
    | @@ -29,6 +29,7 @@ module Protocol | |
| 29 29 | 
             
            		PRIORITY = 0x20
         | 
| 30 30 |  | 
| 31 31 | 
             
            		MAXIMUM_ALLOWED_WINDOW_SIZE = 0x7FFFFFFF
         | 
| 32 | 
            +
            		MINIMUM_ALLOWED_FRAME_SIZE = 0x4000
         | 
| 32 33 | 
             
            		MAXIMUM_ALLOWED_FRAME_SIZE = 0xFFFFFF
         | 
| 33 34 |  | 
| 34 35 | 
             
            		class Frame
         | 
| @@ -46,7 +47,7 @@ module Protocol | |
| 46 47 | 
             
            			LENGTH_LOMASK  = 0xFFFF
         | 
| 47 48 |  | 
| 48 49 | 
             
            			# @param length [Integer] the length of the payload, or nil if the header has not been read yet.
         | 
| 49 | 
            -
            			def initialize(stream_id = 0, flags = 0, type = self.class | 
| 50 | 
            +
            			def initialize(stream_id = 0, flags = 0, type = self.class::TYPE, length = nil, payload = nil)
         | 
| 50 51 | 
             
            				@length = length
         | 
| 51 52 | 
             
            				@type = type
         | 
| 52 53 | 
             
            				@flags = flags
         | 
| @@ -54,6 +55,10 @@ module Protocol | |
| 54 55 | 
             
            				@payload = payload
         | 
| 55 56 | 
             
            			end
         | 
| 56 57 |  | 
| 58 | 
            +
            			def valid_type?
         | 
| 59 | 
            +
            				@type == self.class::TYPE
         | 
| 60 | 
            +
            			end
         | 
| 61 | 
            +
            			
         | 
| 57 62 | 
             
            			def <=> other
         | 
| 58 63 | 
             
            				to_ary <=> other.to_ary
         | 
| 59 64 | 
             
            			end
         | 
| @@ -147,11 +152,18 @@ module Protocol | |
| 147 152 | 
             
            				length = (length_hi << LENGTH_HISHIFT) | length_lo
         | 
| 148 153 | 
             
            				stream_id = stream_id & STREAM_ID_MASK
         | 
| 149 154 |  | 
| 155 | 
            +
            				# puts "parse_header: length=#{length} type=#{type} flags=#{flags} stream_id=#{stream_id}"
         | 
| 156 | 
            +
            				
         | 
| 150 157 | 
             
            				return length, type, flags, stream_id
         | 
| 151 158 | 
             
            			end
         | 
| 152 159 |  | 
| 153 160 | 
             
            			def read_header(stream)
         | 
| 154 | 
            -
            				 | 
| 161 | 
            +
            				if buffer = stream.read(9)
         | 
| 162 | 
            +
            					@length, @type, @flags, @stream_id = Frame.parse_header(buffer)
         | 
| 163 | 
            +
            					# puts "read_header: #{@length} #{@type} #{@flags} #{@stream_id}"
         | 
| 164 | 
            +
            				else
         | 
| 165 | 
            +
            					raise EOFError, "Could not read frame header!"
         | 
| 166 | 
            +
            				end
         | 
| 155 167 | 
             
            			end
         | 
| 156 168 |  | 
| 157 169 | 
             
            			def read_payload(stream)
         | 
| @@ -82,11 +82,12 @@ module Protocol | |
| 82 82 | 
             
            			def read_frame(maximum_frame_size = MAXIMUM_ALLOWED_FRAME_SIZE)
         | 
| 83 83 | 
             
            				# Read the header:
         | 
| 84 84 | 
             
            				length, type, flags, stream_id = read_header
         | 
| 85 | 
            -
            				
         | 
| 86 | 
            -
            				# puts "framer: read_frame #{type} #{length}"
         | 
| 85 | 
            +
            				# puts "read_frame: length=#{length} type=#{type} flags=#{flags} stream_id=#{stream_id} -> klass=#{@frames[type].inspect}"
         | 
| 87 86 |  | 
| 88 87 | 
             
            				# Allocate the frame:
         | 
| 89 88 | 
             
            				klass = @frames[type] || Frame
         | 
| 89 | 
            +
            				# puts "read_frame #{klass} id=#{stream_id} length=#{length} flags=#{flags}"
         | 
| 90 | 
            +
            				
         | 
| 90 91 | 
             
            				frame = klass.new(stream_id, flags, type, length)
         | 
| 91 92 |  | 
| 92 93 | 
             
            				# Read the payload:
         | 
| @@ -68,10 +68,12 @@ module Protocol | |
| 68 68 | 
             
            			attr :maximum_frame_size
         | 
| 69 69 |  | 
| 70 70 | 
             
            			def maximum_frame_size= value
         | 
| 71 | 
            -
            				if value  | 
| 72 | 
            -
            					@maximum_frame_size = value
         | 
| 73 | 
            -
            				else
         | 
| 71 | 
            +
            				if value > MAXIMUM_ALLOWED_FRAME_SIZE
         | 
| 74 72 | 
             
            					raise ProtocolError, "Invalid value for maximum_frame_size: #{value} > #{MAXIMUM_ALLOWED_FRAME_SIZE}"
         | 
| 73 | 
            +
            				elsif value < MINIMUM_ALLOWED_FRAME_SIZE
         | 
| 74 | 
            +
            					raise ProtocolError, "Invalid value for maximum_frame_size: #{value} < #{MINIMUM_ALLOWED_FRAME_SIZE}"
         | 
| 75 | 
            +
            				else
         | 
| 76 | 
            +
            					@maximum_frame_size = value
         | 
| 75 77 | 
             
            				end
         | 
| 76 78 | 
             
            			end
         | 
| 77 79 |  | 
| @@ -77,8 +77,6 @@ module Protocol | |
| 77 77 | 
             
            				@connection = connection
         | 
| 78 78 | 
             
            				@id = id
         | 
| 79 79 |  | 
| 80 | 
            -
            				@connection.streams[@id] = self
         | 
| 81 | 
            -
            				
         | 
| 82 80 | 
             
            				@state = :idle
         | 
| 83 81 |  | 
| 84 82 | 
             
            				@priority = nil
         | 
| @@ -101,6 +99,14 @@ module Protocol | |
| 101 99 | 
             
            			attr :local_window
         | 
| 102 100 | 
             
            			attr :remote_window
         | 
| 103 101 |  | 
| 102 | 
            +
            			def priority= priority
         | 
| 103 | 
            +
            				if priority.stream_id == @id
         | 
| 104 | 
            +
            					raise ProtocolError, "Stream #{@id} cannot depend on itself!"
         | 
| 105 | 
            +
            				end
         | 
| 106 | 
            +
            				
         | 
| 107 | 
            +
            				@priority = priority
         | 
| 108 | 
            +
            			end
         | 
| 109 | 
            +
            			
         | 
| 104 110 | 
             
            			def maximum_frame_size
         | 
| 105 111 | 
             
            				@connection.available_frame_size
         | 
| 106 112 | 
             
            			end
         | 
| @@ -141,7 +147,7 @@ module Protocol | |
| 141 147 | 
             
            				return frame
         | 
| 142 148 | 
             
            			end
         | 
| 143 149 |  | 
| 144 | 
            -
            			#The HEADERS frame is used to open a stream, and additionally carries a header block fragment. | 
| 150 | 
            +
            			# The HEADERS frame is used to open a stream, and additionally carries a header block fragment. HEADERS frames can be sent on a stream in the "idle", "reserved (local)", "open", or "half-closed (remote)" state.
         | 
| 145 151 | 
             
            			def send_headers(*args)
         | 
| 146 152 | 
             
            				if @state == :idle
         | 
| 147 153 | 
             
            					frame = write_headers(*args)
         | 
| @@ -165,7 +171,7 @@ module Protocol | |
| 165 171 | 
             
            					frame = write_headers(*args)
         | 
| 166 172 |  | 
| 167 173 | 
             
            					if frame.end_stream?
         | 
| 168 | 
            -
            						close | 
| 174 | 
            +
            						close
         | 
| 169 175 | 
             
            					end
         | 
| 170 176 | 
             
            				else
         | 
| 171 177 | 
             
            					raise ProtocolError, "Cannot send headers in state: #{@state}"
         | 
| @@ -201,17 +207,15 @@ module Protocol | |
| 201 207 | 
             
            					frame = write_data(*args)
         | 
| 202 208 |  | 
| 203 209 | 
             
            					if frame.end_stream?
         | 
| 204 | 
            -
            						close | 
| 210 | 
            +
            						close
         | 
| 205 211 | 
             
            					end
         | 
| 206 212 | 
             
            				else
         | 
| 207 213 | 
             
            					raise ProtocolError, "Cannot send data in state: #{@state}"
         | 
| 208 214 | 
             
            				end
         | 
| 209 215 | 
             
            			end
         | 
| 210 216 |  | 
| 211 | 
            -
            			def close | 
| 217 | 
            +
            			def close(state = :closed)
         | 
| 212 218 | 
             
            				@state = state
         | 
| 213 | 
            -
            				
         | 
| 214 | 
            -
            				@connection.streams.delete(@id)
         | 
| 215 219 | 
             
            			end
         | 
| 216 220 |  | 
| 217 221 | 
             
            			def send_reset_stream(error_code = 0)
         | 
| @@ -221,7 +225,7 @@ module Protocol | |
| 221 225 |  | 
| 222 226 | 
             
            					write_frame(frame)
         | 
| 223 227 |  | 
| 224 | 
            -
            					close | 
| 228 | 
            +
            					close(:reset)
         | 
| 225 229 | 
             
            				else
         | 
| 226 230 | 
             
            					raise ProtocolError, "Cannot reset stream in state: #{@state}"
         | 
| 227 231 | 
             
            				end
         | 
| @@ -232,7 +236,7 @@ module Protocol | |
| 232 236 | 
             
            				priority, data = frame.unpack
         | 
| 233 237 |  | 
| 234 238 | 
             
            				if priority
         | 
| 235 | 
            -
            					 | 
| 239 | 
            +
            					self.priority = priority
         | 
| 236 240 | 
             
            				end
         | 
| 237 241 |  | 
| 238 242 | 
             
            				@connection.decode_headers(data)
         | 
| @@ -259,7 +263,7 @@ module Protocol | |
| 259 263 | 
             
            					@headers = process_headers(frame)
         | 
| 260 264 | 
             
            				elsif @state == :half_closed_local
         | 
| 261 265 | 
             
            					if frame.end_stream?
         | 
| 262 | 
            -
            						close | 
| 266 | 
            +
            						close
         | 
| 263 267 | 
             
            					end
         | 
| 264 268 |  | 
| 265 269 | 
             
            					@headers = process_headers(frame)
         | 
| @@ -284,7 +288,7 @@ module Protocol | |
| 284 288 | 
             
            					consume_local_window(frame)
         | 
| 285 289 |  | 
| 286 290 | 
             
            					if frame.end_stream?
         | 
| 287 | 
            -
            						close | 
| 291 | 
            +
            						close
         | 
| 288 292 | 
             
            					end
         | 
| 289 293 |  | 
| 290 294 | 
             
            					@data = frame.unpack
         | 
| @@ -296,12 +300,12 @@ module Protocol | |
| 296 300 | 
             
            			end
         | 
| 297 301 |  | 
| 298 302 | 
             
            			def receive_priority(frame)
         | 
| 299 | 
            -
            				 | 
| 303 | 
            +
            				self.priority = frame.unpack
         | 
| 300 304 | 
             
            			end
         | 
| 301 305 |  | 
| 302 306 | 
             
            			def receive_reset_stream(frame)
         | 
| 303 307 | 
             
            				if @state != :idle and @state != :closed
         | 
| 304 | 
            -
            					close | 
| 308 | 
            +
            					close
         | 
| 305 309 |  | 
| 306 310 | 
             
            					return frame.unpack
         | 
| 307 311 | 
             
            				else
         | 
| @@ -367,6 +371,10 @@ module Protocol | |
| 367 371 |  | 
| 368 372 | 
             
            				return stream, headers
         | 
| 369 373 | 
             
            			end
         | 
| 374 | 
            +
            			
         | 
| 375 | 
            +
            			def inspect
         | 
| 376 | 
            +
            				"\#<#{self.class} id=#{@id} state=#{@state}>"
         | 
| 377 | 
            +
            			end
         | 
| 370 378 | 
             
            		end
         | 
| 371 379 | 
             
            	end
         | 
| 372 380 | 
             
            end
         | 
| @@ -31,8 +31,6 @@ module Protocol | |
| 31 31 | 
             
            				# These two fields are primarily used for efficiently sending window updates:
         | 
| 32 32 | 
             
            				@used = 0
         | 
| 33 33 | 
             
            				@capacity = capacity
         | 
| 34 | 
            -
            				
         | 
| 35 | 
            -
            				fail unless capacity
         | 
| 36 34 | 
             
            			end
         | 
| 37 35 |  | 
| 38 36 | 
             
            			def dup
         | 
| @@ -41,7 +39,7 @@ module Protocol | |
| 41 39 |  | 
| 42 40 | 
             
            			# The window is completely full?
         | 
| 43 41 | 
             
            			def full?
         | 
| 44 | 
            -
            				@available | 
| 42 | 
            +
            				@available <= 0
         | 
| 45 43 | 
             
            			end
         | 
| 46 44 |  | 
| 47 45 | 
             
            			attr :used
         | 
| @@ -67,6 +65,10 @@ module Protocol | |
| 67 65 | 
             
            			def expand(amount)
         | 
| 68 66 | 
             
            				@available += amount
         | 
| 69 67 | 
             
            				@used -= amount
         | 
| 68 | 
            +
            				
         | 
| 69 | 
            +
            				if @available > MAXIMUM_ALLOWED_WINDOW_SIZE
         | 
| 70 | 
            +
            					raise FlowControlError, "Expanding window by #{amount} caused overflow: #{@available} > #{MAXIMUM_ALLOWED_WINDOW_SIZE}!"
         | 
| 71 | 
            +
            				end
         | 
| 70 72 | 
             
            			end
         | 
| 71 73 |  | 
| 72 74 | 
             
            			def limited?
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: protocol-http2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Samuel Williams
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019- | 
| 11 | 
            +
            date: 2019-06-12 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: protocol-hpack
         | 
| @@ -150,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 150 150 | 
             
                - !ruby/object:Gem::Version
         | 
| 151 151 | 
             
                  version: '0'
         | 
| 152 152 | 
             
            requirements: []
         | 
| 153 | 
            -
            rubygems_version: 3.0. | 
| 153 | 
            +
            rubygems_version: 3.0.3
         | 
| 154 154 | 
             
            signing_key: 
         | 
| 155 155 | 
             
            specification_version: 4
         | 
| 156 156 | 
             
            summary: A low level implementation of the HTTP/2 protocol.
         |