module Plum::FlowControl

Attributes

recv_remaining_window[R]
send_remaining_window[R]

Public Instance Methods

send(frame) click to toggle source

Sends frame respecting inner-stream flow control. @param frame [Frame] The frame to be sent.

# File lib/plum/flow_control.rb, line 9
def send(frame)
  if frame.type == :data
    @send_buffer << frame
    if @send_remaining_window < frame.length
      if Stream === self
        connection.callback(:send_deferred, self, frame)
      else
        callback(:send_deferred, self, frame)
      end
    else
      consume_send_buffer
    end
  else
    send_immediately frame
  end
end
window_update(wsi) click to toggle source

Increases receiving window size. Sends WINDOW_UPDATE frame to the peer. @param wsi [Integer] The amount to increase receiving window size. The legal range is 1 to 2^32-1.

# File lib/plum/flow_control.rb, line 28
def window_update(wsi)
  @recv_remaining_window += wsi
  payload = String.new.push_uint32(wsi)
  sid = (Stream === self) ? self.id : 0
  send_immediately Frame.new(type: :window_update, stream_id: sid, payload: payload)
end

Protected Instance Methods

update_recv_initial_window_size(diff) click to toggle source
# File lib/plum/flow_control.rb, line 47
def update_recv_initial_window_size(diff)
  @recv_remaining_window += diff
  if Connection === self
    @streams.values.each do |stream|
      stream.update_recv_initial_window_size(diff)
    end
  end
end
update_send_initial_window_size(diff) click to toggle source
# File lib/plum/flow_control.rb, line 36
def update_send_initial_window_size(diff)
  @send_remaining_window += diff
  consume_send_buffer

  if Connection === self
    @streams.values.each do |stream|
      stream.update_send_initial_window_size(diff)
    end
  end
end

Private Instance Methods

consume_recv_window(frame) click to toggle source
# File lib/plum/flow_control.rb, line 63
def consume_recv_window(frame)
  if frame.type == :data
    @recv_remaining_window -= frame.length
    if @recv_remaining_window < 0
      local_error = (Connection === self) ? RemoteConnectionError : RemoteStreamError
      raise local_error.new(:flow_control_error)
    end
  end
end
consume_send_buffer() click to toggle source
# File lib/plum/flow_control.rb, line 73
def consume_send_buffer
  while frame = @send_buffer.first
    break if frame.length > @send_remaining_window
    @send_buffer.shift
    @send_remaining_window -= frame.length
    send_immediately frame
  end
end
initialize_flow_control(send:, recv:) click to toggle source
# File lib/plum/flow_control.rb, line 57
def initialize_flow_control(send:, recv:)
  @send_buffer = []
  @send_remaining_window = send
  @recv_remaining_window = recv
end
receive_window_update(frame) click to toggle source
# File lib/plum/flow_control.rb, line 82
def receive_window_update(frame)
  if frame.length != 4
    raise Plum::RemoteConnectionError.new(:frame_size_error)
  end

  r_wsi = frame.payload.uint32
  # r = r_wsi >> 31 # currently not used
  wsi = r_wsi # & ~(1 << 31)

  if wsi == 0
    local_error = (Connection === self) ? RemoteConnectionError : RemoteStreamError
    raise local_error.new(:protocol_error)
  end

  if Stream === self
    connection.callback(:window_update, self, wsi)
  else
    callback(:window_update, self, wsi)
  end

  @send_remaining_window += wsi
  consume_send_buffer
end