Class: Plum::Connection

Inherits:
Object
  • Object
show all
Includes:
ConnectionUtils, EventEmitter, FlowControl
Defined in:
lib/plum/connection.rb

Direct Known Subclasses

ClientConnection, ServerConnection

Constant Summary collapse

CLIENT_CONNECTION_PREFACE =
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
DEFAULT_SETTINGS =
{
  header_table_size:      4096,     # octets
  enable_push:            1,        # 1: enabled, 0: disabled
  max_concurrent_streams: 1 << 30,  # (1 << 31) / 2
  initial_window_size:    65535,    # octets; <= 2 ** 31 - 1
  max_frame_size:         16384,    # octets; <= 2 ** 24 - 1
  max_header_list_size:   (1 << 32) - 1 # Fixnum
}.freeze

Instance Attribute Summary collapse

Attributes included from FlowControl

#recv_remaining_window, #send_remaining_window

Instance Method Summary collapse

Methods included from ConnectionUtils

#goaway, #ping, #push_enabled?, #settings

Methods included from FlowControl

#send, #window_update

Methods included from EventEmitter

#callback, #on

Constructor Details

#initialize(writer, local_settings = {}) ⇒ Connection

Returns a new instance of Connection.



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/plum/connection.rb', line 25

def initialize(writer, local_settings = {})
  @state = :open
  @writer = writer
  @local_settings = Hash.new {|hash, key| DEFAULT_SETTINGS[key] }.merge!(local_settings)
  @remote_settings = Hash.new {|hash, key| DEFAULT_SETTINGS[key] }
  @buffer = String.new
  @streams = {}
  @hpack_decoder = HPACK::Decoder.new(@local_settings[:header_table_size])
  @hpack_encoder = HPACK::Encoder.new(@remote_settings[:header_table_size])
  initialize_flow_control(send: @remote_settings[:initial_window_size],
                          recv: @local_settings[:initial_window_size])
  @max_stream_ids = [0, -1] # [even, odd]
end

Instance Attribute Details

#hpack_decoderObject (readonly)

Returns the value of attribute hpack_decoder.



21
22
23
# File 'lib/plum/connection.rb', line 21

def hpack_decoder
  @hpack_decoder
end

#hpack_encoderObject (readonly)

Returns the value of attribute hpack_encoder.



21
22
23
# File 'lib/plum/connection.rb', line 21

def hpack_encoder
  @hpack_encoder
end

#local_settingsObject (readonly)

Returns the value of attribute local_settings.



22
23
24
# File 'lib/plum/connection.rb', line 22

def local_settings
  @local_settings
end

#remote_settingsObject (readonly)

Returns the value of attribute remote_settings.



22
23
24
# File 'lib/plum/connection.rb', line 22

def remote_settings
  @remote_settings
end

#stateObject (readonly)

Returns the value of attribute state.



23
24
25
# File 'lib/plum/connection.rb', line 23

def state
  @state
end

#streamsObject (readonly)

Returns the value of attribute streams.



23
24
25
# File 'lib/plum/connection.rb', line 23

def streams
  @streams
end

Instance Method Details

#closeObject

Emits :close event. Doesn’t actually close socket.



40
41
42
43
44
45
# File 'lib/plum/connection.rb', line 40

def close
  return if @state == :closed
  @state = :closed
  # TODO: server MAY wait streams
  callback(:close)
end

#receive(new_data) ⇒ Object Also known as: <<

Receives the specified data and process.

Parameters:

  • new_data (String)

    The data received from the peer.



49
50
51
52
53
54
55
56
57
58
# File 'lib/plum/connection.rb', line 49

def receive(new_data)
  return if @state == :closed
  return if new_data.empty?
  @buffer << new_data
  consume_buffer
rescue RemoteConnectionError => e
  callback(:connection_error, e)
  goaway(e.http2_error_type)
  close
end

#stream(stream_id, update_max_id = true) ⇒ Stream

Returns a Stream object with the specified ID.

Parameters:

  • stream_id (Integer)

    the stream id

Returns:

Raises:

  • (ArgumentError)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/plum/connection.rb', line 64

def stream(stream_id, update_max_id = true)
  raise ArgumentError, "stream_id can't be 0" if stream_id == 0

  stream = @streams[stream_id]
  if stream
    if stream.state == :idle && stream_id < @max_stream_ids[stream_id % 2]
      stream.set_state(:closed_implicitly)
    end
  elsif stream_id > @max_stream_ids[stream_id % 2]
    @max_stream_ids[stream_id % 2] = stream_id if update_max_id
    stream = Stream.new(self, stream_id, state: :idle)
    callback(:stream, stream)
    @streams[stream_id] = stream
  else
    stream = Stream.new(self, stream_id, state: :closed_implicitly)
    callback(:stream, stream)
  end

  stream
end