Class: Protocol::HTTP2::Connection
- Inherits:
-
Object
- Object
- Protocol::HTTP2::Connection
- Includes:
- FlowControlled
- Defined in:
- lib/protocol/http2/connection.rb
Overview
This is the core connection class that handles HTTP/2 protocol semantics including stream management, settings negotiation, and frame processing.
Instance Attribute Summary collapse
-
#dependencies ⇒ Object
readonly
Returns the value of attribute dependencies.
-
#dependency ⇒ Object
readonly
Returns the value of attribute dependency.
-
#framer ⇒ Object
readonly
Returns the value of attribute framer.
-
#local_settings ⇒ Object
Current settings value for local and peer.
-
#local_window ⇒ Object
readonly
Our window for receiving data.
-
#remote_settings ⇒ Object
Returns the value of attribute remote_settings.
-
#remote_stream_id ⇒ Object
readonly
The highest stream_id that has been successfully accepted by this connection.
-
#remote_window ⇒ Object
readonly
Our window for sending data.
-
#state ⇒ Object
Connection state (:new, :open, :closed).
-
#streams ⇒ Object
readonly
Returns the value of attribute streams.
Instance Method Summary collapse
-
#[](id) ⇒ Object
Access streams by ID, with 0 returning the connection itself.
-
#accept_push_promise_stream(stream_id, &block) ⇒ Object
Accept an incoming push promise from the other side of the connection.
-
#accept_stream(stream_id, &block) ⇒ Object
Accept an incoming stream from the other side of the connnection.
-
#client_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents a client-initiated stream.
-
#close(error = nil) ⇒ Object
Close the underlying framer and all streams.
-
#close! ⇒ Object
Transition the connection into the closed state.
-
#closed? ⇒ Boolean
Whether the connection is effectively or actually closed.
-
#closed_stream_id?(id) ⇒ Boolean
This is only valid if the stream doesn’t exist in ‘@streams`.
-
#consume_window(size = self.available_size) ⇒ Object
Traverse active streams and allow them to consume the available flow-control window.
-
#create_push_promise_stream(&block) ⇒ Object
Create a push promise stream.
-
#create_stream(id = next_stream_id, &block) ⇒ Stream
Create a stream, defaults to an outgoing stream.
-
#decode_headers(data) ⇒ Object
Decode headers using HPACK decompression.
-
#delete(id) ⇒ Object
Remove a stream from the active streams collection.
-
#encode_headers(headers, buffer = String.new.b) ⇒ Object
Encode headers using HPACK compression.
-
#id ⇒ Object
The connection stream ID (always 0 for connection-level operations).
-
#idle_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents an idle stream.
-
#ignore_frame?(frame) ⇒ Boolean
6.8.
-
#initialize(framer, local_stream_id) ⇒ Connection
constructor
Initialize a new HTTP/2 connection.
-
#maximum_concurrent_streams ⇒ Object
The maximum number of concurrent streams that this connection can initiate.
-
#maximum_frame_size ⇒ Object
The size of a frame payload is limited by the maximum size that a receiver advertises in the SETTINGS_MAX_FRAME_SIZE setting.
-
#next_stream_id ⇒ Object
Streams are identified with an unsigned 31-bit integer.
-
#open! ⇒ Object
Transition the connection to the open state.
-
#process_settings(frame) ⇒ Boolean
In addition to changing the flow-control window for streams that are not yet active, a SETTINGS frame can alter the initial flow-control window size for streams with active flow-control windows (that is, streams in the “open” or “half-closed (remote)” state).
-
#read_frame ⇒ Object
Reads one frame from the network and processes.
-
#receive_continuation(frame) ⇒ Object
Receive and process a CONTINUATION frame.
-
#receive_data(frame) ⇒ Object
Process a DATA frame from the remote peer.
-
#receive_frame(frame) ⇒ Object
Receive and process a generic frame (default handler).
-
#receive_goaway(frame) ⇒ Object
Process a GOAWAY frame from the remote peer.
-
#receive_headers(frame) ⇒ Object
On the server side, starts a new request.
-
#receive_ping(frame) ⇒ Object
Process a PING frame from the remote peer.
-
#receive_priority_update(frame) ⇒ Object
Receive and process a PRIORITY_UPDATE frame.
-
#receive_push_promise(frame) ⇒ Object
Receive and process a PUSH_PROMISE frame.
-
#receive_reset_stream(frame) ⇒ Object
Receive and process a RST_STREAM frame.
-
#receive_settings(frame) ⇒ Object
Receive and process a SETTINGS frame from the remote peer.
-
#receive_window_update(frame) ⇒ Object
Receive and process a WINDOW_UPDATE frame.
-
#send_goaway(error_code = 0, message = "") ⇒ Object
Tell the remote end that the connection is being shut down.
-
#send_ping(data) ⇒ Object
Send a PING frame to the remote peer.
-
#send_settings(changes) ⇒ Object
Send updated settings to the remote peer.
-
#server_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents a server-initiated stream.
-
#synchronize ⇒ Object
Execute a block within a synchronized context.
-
#update_local_settings(changes) ⇒ Object
Update local settings and adjust stream window capacities.
-
#update_remote_settings(changes) ⇒ Object
Update remote settings and adjust stream window capacities.
-
#valid_remote_stream_id?(stream_id) ⇒ Boolean
Check if the given stream ID is valid for remote initiation.
-
#write_frame(frame) ⇒ Object
Write a single frame to the connection.
-
#write_frames ⇒ Object
Write multiple frames within a synchronized block.
Methods included from FlowControlled
#available_frame_size, #available_size, #consume_local_window, #consume_remote_window, #request_window_update, #send_window_update, #update_local_window, #window_updated
Constructor Details
#initialize(framer, local_stream_id) ⇒ Connection
Initialize a new HTTP/2 connection.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/protocol/http2/connection.rb', line 23 def initialize(framer, local_stream_id) super() @state = :new # Hash(Integer, Stream) @streams = {} @framer = framer # The next stream id to use: @local_stream_id = local_stream_id # The biggest remote stream id seen thus far: @remote_stream_id = 0 @local_settings = PendingSettings.new @remote_settings = Settings.new @decoder = HPACK::Context.new @encoder = HPACK::Context.new @local_window = LocalWindow.new @remote_window = Window.new end |
Instance Attribute Details
#dependencies ⇒ Object (readonly)
Returns the value of attribute dependencies.
148 149 150 |
# File 'lib/protocol/http2/connection.rb', line 148 def dependencies @dependencies end |
#dependency ⇒ Object (readonly)
Returns the value of attribute dependency.
150 151 152 |
# File 'lib/protocol/http2/connection.rb', line 150 def dependency @dependency end |
#framer ⇒ Object (readonly)
Returns the value of attribute framer.
78 79 80 |
# File 'lib/protocol/http2/connection.rb', line 78 def framer @framer end |
#local_settings ⇒ Object
Current settings value for local and peer
84 85 86 |
# File 'lib/protocol/http2/connection.rb', line 84 def local_settings @local_settings end |
#local_window ⇒ Object (readonly)
Our window for receiving data. When we receive data, it reduces this window. If the window gets too small, we must send a window update.
89 90 91 |
# File 'lib/protocol/http2/connection.rb', line 89 def local_window @local_window end |
#remote_settings ⇒ Object
Returns the value of attribute remote_settings.
85 86 87 |
# File 'lib/protocol/http2/connection.rb', line 85 def remote_settings @remote_settings end |
#remote_stream_id ⇒ Object (readonly)
The highest stream_id that has been successfully accepted by this connection.
95 96 97 |
# File 'lib/protocol/http2/connection.rb', line 95 def remote_stream_id @remote_stream_id end |
#remote_window ⇒ Object (readonly)
Our window for sending data. When we send data, it reduces this window.
92 93 94 |
# File 'lib/protocol/http2/connection.rb', line 92 def remote_window @remote_window end |
#state ⇒ Object
Connection state (:new, :open, :closed).
81 82 83 |
# File 'lib/protocol/http2/connection.rb', line 81 def state @state end |
#streams ⇒ Object (readonly)
Returns the value of attribute streams.
146 147 148 |
# File 'lib/protocol/http2/connection.rb', line 146 def streams @streams end |
Instance Method Details
#[](id) ⇒ Object
Access streams by ID, with 0 returning the connection itself.
58 59 60 61 62 63 64 |
# File 'lib/protocol/http2/connection.rb', line 58 def [] id if id.zero? self else @streams[id] end end |
#accept_push_promise_stream(stream_id, &block) ⇒ Object
Accept an incoming push promise from the other side of the connection. On the client side, we accept push promise streams. On the server side, existing streams create push promise streams.
405 406 407 |
# File 'lib/protocol/http2/connection.rb', line 405 def accept_push_promise_stream(stream_id, &block) accept_stream(stream_id, &block) end |
#accept_stream(stream_id, &block) ⇒ Object
Accept an incoming stream from the other side of the connnection. On the server side, we accept requests.
394 395 396 397 398 399 400 |
# File 'lib/protocol/http2/connection.rb', line 394 def accept_stream(stream_id, &block) unless valid_remote_stream_id?(stream_id) raise ProtocolError, "Invalid stream id: #{stream_id}" end create_stream(stream_id, &block) end |
#client_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents a client-initiated stream. Client streams always have odd numbered IDs.
486 487 488 |
# File 'lib/protocol/http2/connection.rb', line 486 def client_stream_id?(id) id.odd? end |
#close(error = nil) ⇒ Object
Close the underlying framer and all streams.
110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/protocol/http2/connection.rb', line 110 def close(error = nil) # The underlying socket may already be closed by this point. @streams.each_value{|stream| stream.close(error)} @streams.clear ensure if @framer @framer.close @framer = nil end end |
#close! ⇒ Object
Transition the connection into the closed state.
209 210 211 212 213 |
# File 'lib/protocol/http2/connection.rb', line 209 def close! @state = :closed return self end |
#closed? ⇒ Boolean
Whether the connection is effectively or actually closed.
98 99 100 |
# File 'lib/protocol/http2/connection.rb', line 98 def closed? @state == :closed || @framer.nil? end |
#closed_stream_id?(id) ⇒ Boolean
This is only valid if the stream doesn’t exist in ‘@streams`.
520 521 522 523 524 525 526 527 |
# File 'lib/protocol/http2/connection.rb', line 520 def closed_stream_id?(id) if id.zero? # The connection "stream id" can never be closed: false else !idle_stream_id?(id) end end |
#consume_window(size = self.available_size) ⇒ Object
Traverse active streams and allow them to consume the available flow-control window.
546 547 548 549 550 551 552 553 554 555 |
# File 'lib/protocol/http2/connection.rb', line 546 def consume_window(size = self.available_size) # Return if there is no window to consume: return unless size > 0 @streams.each_value do |stream| if stream.active? stream.window_updated(size) end end end |
#create_push_promise_stream(&block) ⇒ Object
Create a push promise stream. This method should be overridden by client/server implementations.
428 429 430 |
# File 'lib/protocol/http2/connection.rb', line 428 def create_push_promise_stream(&block) create_stream(&block) end |
#create_stream(id = next_stream_id, &block) ⇒ Stream
Create a stream, defaults to an outgoing stream. On the client side, we create requests.
412 413 414 415 416 417 418 419 420 421 422 |
# File 'lib/protocol/http2/connection.rb', line 412 def create_stream(id = next_stream_id, &block) if @streams.key?(id) raise ProtocolError, "Cannot create stream with id #{id}, already exists!" end if block_given? return yield(self, id) else return Stream.create(self, id) end end |
#decode_headers(data) ⇒ Object
Decode headers using HPACK decompression.
133 134 135 |
# File 'lib/protocol/http2/connection.rb', line 133 def decode_headers(data) HPACK::Decompressor.new(data, @decoder, table_size_limit: @local_settings.header_table_size).decode end |
#delete(id) ⇒ Object
Remove a stream from the active streams collection.
105 106 107 |
# File 'lib/protocol/http2/connection.rb', line 105 def delete(id) @streams.delete(id) end |
#encode_headers(headers, buffer = String.new.b) ⇒ Object
Encode headers using HPACK compression.
126 127 128 |
# File 'lib/protocol/http2/connection.rb', line 126 def encode_headers(headers, buffer = String.new.b) HPACK::Compressor.new(buffer, @encoder, table_size_limit: @remote_settings.header_table_size).encode(headers) end |
#id ⇒ Object
The connection stream ID (always 0 for connection-level operations).
51 52 53 |
# File 'lib/protocol/http2/connection.rb', line 51 def id 0 end |
#idle_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents an idle stream.
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'lib/protocol/http2/connection.rb', line 501 def idle_stream_id?(id) if id.even? # Server-initiated streams are even. if @local_stream_id.even? id >= @local_stream_id else id > @remote_stream_id end elsif id.odd? # Client-initiated streams are odd. if @local_stream_id.odd? id >= @local_stream_id else id > @remote_stream_id end end end |
#ignore_frame?(frame) ⇒ Boolean
6.8. GOAWAY 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. 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.
155 156 157 158 159 160 161 162 |
# File 'lib/protocol/http2/connection.rb', line 155 def ignore_frame?(frame) if self.closed? # puts "ignore_frame? #{frame.stream_id} -> #{valid_remote_stream_id?(frame.stream_id)} > #{@remote_stream_id}" if valid_remote_stream_id?(frame.stream_id) return frame.stream_id > @remote_stream_id end end end |
#maximum_concurrent_streams ⇒ Object
The maximum number of concurrent streams that this connection can initiate. This is a setting that can be changed by the remote peer.
It is not the same as the number of streams that can be accepted by the connection. The number of streams that can be accepted is determined by the local settings, and the number of streams that can be initiated is determined by the remote settings.
74 75 76 |
# File 'lib/protocol/http2/connection.rb', line 74 def maximum_concurrent_streams @remote_settings.maximum_concurrent_streams end |
#maximum_frame_size ⇒ Object
The size of a frame payload is limited by the maximum size that a receiver advertises in the SETTINGS_MAX_FRAME_SIZE setting.
67 68 69 |
# File 'lib/protocol/http2/connection.rb', line 67 def maximum_frame_size @remote_settings.maximum_frame_size end |
#next_stream_id ⇒ Object
Streams are identified with an unsigned 31-bit integer. Streams initiated by a client MUST use odd-numbered stream identifiers; those initiated by the server MUST use even-numbered stream identifiers. A stream identifier of zero (0x0) is used for connection control messages; the stream identifier of zero cannot be used to establish a new stream.
138 139 140 141 142 143 144 |
# File 'lib/protocol/http2/connection.rb', line 138 def next_stream_id id = @local_stream_id @local_stream_id += 2 return id end |
#open! ⇒ Object
Transition the connection to the open state.
316 317 318 319 320 |
# File 'lib/protocol/http2/connection.rb', line 316 def open! @state = :open return self end |
#process_settings(frame) ⇒ Boolean
In addition to changing the flow-control window for streams that are not yet active, a SETTINGS frame can alter the initial flow-control window size for streams with active flow-control windows (that is, streams in the “open” or “half-closed (remote)” state). When the value of SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST adjust the size of all stream flow-control windows that it maintains by the difference between the new value and the old value.
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/protocol/http2/connection.rb', line 291 def process_settings(frame) if frame.acknowledgement? # The remote end has confirmed the settings have been received: changes = @local_settings.acknowledge update_local_settings(changes) return true else # The remote end is updating the settings, we reply with acknowledgement: reply = frame.acknowledge write_frame(reply) changes = frame.unpack @remote_settings.update(changes) update_remote_settings(changes) return false end end |
#read_frame ⇒ Object
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.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/protocol/http2/connection.rb', line 172 def read_frame frame = @framer.read_frame(@local_settings.maximum_frame_size) # 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})" # puts "Windows: local_window=#{@local_window.inspect}; remote_window=#{@remote_window.inspect}" return if ignore_frame?(frame) yield frame if block_given? frame.apply(self) return frame rescue GoawayError => error # Go directly to jail. Do not pass go, do not collect $200. raise rescue ProtocolError => error send_goaway(error.code || PROTOCOL_ERROR, error.) raise rescue HPACK::Error => error send_goaway(COMPRESSION_ERROR, error.) raise end |
#receive_continuation(frame) ⇒ Object
Receive and process a CONTINUATION frame.
581 582 583 |
# File 'lib/protocol/http2/connection.rb', line 581 def receive_continuation(frame) raise ProtocolError, "Received unexpected continuation: #{frame.class}" end |
#receive_data(frame) ⇒ Object
Process a DATA frame from the remote peer.
372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/protocol/http2/connection.rb', line 372 def receive_data(frame) update_local_window(frame) if stream = @streams[frame.stream_id] stream.receive_data(frame) elsif closed_stream_id?(frame.stream_id) # This can occur if one end sent a stream reset, while the other end was sending a data frame. It's mostly harmless. else raise ProtocolError, "Cannot receive data for stream id #{frame.stream_id}" end end |
#receive_frame(frame) ⇒ Object
Receive and process a generic frame (default handler).
587 588 589 |
# File 'lib/protocol/http2/connection.rb', line 587 def receive_frame(frame) # ignore. end |
#receive_goaway(frame) ⇒ Object
Process a GOAWAY frame from the remote peer.
228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/protocol/http2/connection.rb', line 228 def receive_goaway(frame) # We capture the last stream that was processed. @remote_stream_id, error_code, = frame.unpack self.close! if error_code != 0 # Shut down immediately. raise GoawayError.new(, error_code) end end |
#receive_headers(frame) ⇒ Object
On the server side, starts a new request.
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'lib/protocol/http2/connection.rb', line 433 def receive_headers(frame) stream_id = frame.stream_id if stream_id.zero? raise ProtocolError, "Cannot receive headers for stream 0!" end if stream = @streams[stream_id] stream.receive_headers(frame) else if stream_id <= @remote_stream_id raise ProtocolError, "Invalid stream id: #{stream_id} <= #{@remote_stream_id}!" end # We need to validate that we have less streams than the specified maximum: if @streams.size < @local_settings.maximum_concurrent_streams stream = accept_stream(stream_id) @remote_stream_id = stream_id stream.receive_headers(frame) else raise ProtocolError, "Exceeded maximum concurrent streams" end end end |
#receive_ping(frame) ⇒ Object
Process a PING frame from the remote peer.
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/protocol/http2/connection.rb', line 352 def receive_ping(frame) if @state != :closed # This is handled in `read_payload`: # if frame.stream_id != 0 # raise ProtocolError, "Ping received for non-zero stream!" # end unless frame.acknowledgement? reply = frame.acknowledge write_frame(reply) end else raise ProtocolError, "Cannot receive ping in state #{@state}" end end |
#receive_priority_update(frame) ⇒ Object
Receive and process a PRIORITY_UPDATE frame.
469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/protocol/http2/connection.rb', line 469 def receive_priority_update(frame) if frame.stream_id != 0 raise ProtocolError, "Invalid stream id: #{frame.stream_id}" end stream_id, value = frame.unpack # Apparently you can set the priority of idle streams, but I'm not sure why that makes sense, so for now let's ignore it. if stream = @streams[stream_id] stream.priority = Protocol::HTTP::Header::Priority.new(value) end end |
#receive_push_promise(frame) ⇒ Object
Receive and process a PUSH_PROMISE frame.
462 463 464 |
# File 'lib/protocol/http2/connection.rb', line 462 def receive_push_promise(frame) raise ProtocolError, "Unable to receive push promise!" end |
#receive_reset_stream(frame) ⇒ Object
Receive and process a RST_STREAM frame.
532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/protocol/http2/connection.rb', line 532 def receive_reset_stream(frame) if frame.connection? raise ProtocolError, "Cannot reset connection!" elsif stream = @streams[frame.stream_id] stream.receive_reset_stream(frame) elsif closed_stream_id?(frame.stream_id) # Ignore. else raise StreamClosed, "Cannot reset stream #{frame.stream_id}" end end |
#receive_settings(frame) ⇒ Object
Receive and process a SETTINGS frame from the remote peer.
325 326 327 328 329 330 331 332 333 334 |
# File 'lib/protocol/http2/connection.rb', line 325 def receive_settings(frame) if @state == :new # We transition to :open when we receive acknowledgement of first settings frame: open! if process_settings(frame) elsif @state != :closed process_settings(frame) else raise ProtocolError, "Cannot receive settings in state #{@state}" end end |
#receive_window_update(frame) ⇒ Object
Receive and process a WINDOW_UPDATE frame.
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 |
# File 'lib/protocol/http2/connection.rb', line 559 def receive_window_update(frame) if frame.connection? super self.consume_window elsif stream = @streams[frame.stream_id] begin stream.receive_window_update(frame) rescue ProtocolError => error stream.send_reset_stream(error.code) end elsif closed_stream_id?(frame.stream_id) # Ignore. else # Receiving any frame other than HEADERS or PRIORITY on a stream in this state (idle) MUST be treated as a connection error of type PROTOCOL_ERROR. raise ProtocolError, "Cannot update window of idle stream #{frame.stream_id}" end end |
#send_goaway(error_code = 0, message = "") ⇒ Object
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.
216 217 218 219 220 221 222 223 |
# File 'lib/protocol/http2/connection.rb', line 216 def send_goaway(error_code = 0, = "") frame = GoawayFrame.new frame.pack @remote_stream_id, error_code, write_frame(frame) ensure self.close! end |
#send_ping(data) ⇒ Object
Send a PING frame to the remote peer.
338 339 340 341 342 343 344 345 346 347 |
# File 'lib/protocol/http2/connection.rb', line 338 def send_ping(data) if @state != :closed frame = PingFrame.new frame.pack data write_frame(frame) else raise ProtocolError, "Cannot send ping in state #{@state}" end end |
#send_settings(changes) ⇒ Object
Send updated settings to the remote peer.
199 200 201 202 203 204 205 206 |
# File 'lib/protocol/http2/connection.rb', line 199 def send_settings(changes) @local_settings.append(changes) frame = SettingsFrame.new frame.pack(changes) write_frame(frame) end |
#server_stream_id?(id) ⇒ Boolean
Check if the given stream ID represents a server-initiated stream. Server streams always have even numbered IDs.
494 495 496 |
# File 'lib/protocol/http2/connection.rb', line 494 def server_stream_id?(id) id.even? end |
#synchronize ⇒ Object
Execute a block within a synchronized context. This method provides a synchronization primitive for thread safety.
167 168 169 |
# File 'lib/protocol/http2/connection.rb', line 167 def synchronize yield end |
#update_local_settings(changes) ⇒ Object
Update local settings and adjust stream window capacities.
268 269 270 271 272 273 274 275 276 |
# File 'lib/protocol/http2/connection.rb', line 268 def update_local_settings(changes) capacity = @local_settings.initial_window_size @streams.each_value do |stream| stream.local_window.capacity = capacity end @local_window.desired = capacity end |
#update_remote_settings(changes) ⇒ Object
Update remote settings and adjust stream window capacities.
280 281 282 283 284 285 286 |
# File 'lib/protocol/http2/connection.rb', line 280 def update_remote_settings(changes) capacity = @remote_settings.initial_window_size @streams.each_value do |stream| stream.remote_window.capacity = capacity end end |
#valid_remote_stream_id?(stream_id) ⇒ Boolean
Check if the given stream ID is valid for remote initiation. This method should be overridden by client/server implementations.
388 389 390 |
# File 'lib/protocol/http2/connection.rb', line 388 def valid_remote_stream_id?(stream_id) false end |
#write_frame(frame) ⇒ Object
Write a single frame to the connection.
242 243 244 245 246 247 248 |
# File 'lib/protocol/http2/connection.rb', line 242 def write_frame(frame) synchronize do @framer.write_frame(frame) end @framer.flush end |
#write_frames ⇒ Object
Write multiple frames within a synchronized block.
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/protocol/http2/connection.rb', line 254 def write_frames if @framer synchronize do yield @framer end @framer.flush else raise EOFError, "Connection closed!" end end |