http://http2.github.io/http2-spec/
Section 3.5によると Connection Headerは以下の文字列で識別する。
CONNECTION_HEADER = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
このクラスは接続を管理するクラスでStreamではなくTCP上の接続を管理する。 priorityは低いほど優先度が低い。
接続状態を保持。new or close
接続に最後あったエラー
flow control window(デフォルトは無限らしいけど、接続同士で更新できる模様)
接続によって許容される最大連続Stream数(接続同士によって自動的に更新される)
現在有効なStream一覧
新しいStreamを作成してそのstreamを返す。 [#TODO]なぜstream_idを2個足すのか。 active_streamでstreamを追加する。
hash_keyにidがないかチェック。 Streamを新しく作成しStreamリストに\追加。 streamリスナーにactive,close,promise(Serverの時のみtokinomi),frameを定義する。
もしframeタイプがdataだった場合、send_dataでデータを送る。
8byteのデータを送る。 socketに書き込むとこはクライアントでリスナーを追加しないけない。 要はframe受け取ったときネットワークバイトオーダはしてやっから後は好きにしなよというスタンスらしい。 終わった後pongリクエストの受付までやる。
conn.on(:frame) do |bytes|
puts "Sending bytes: #{bytes.inspect}"
sock.print bytes
sock.flush
end
これもframe経由で送信。終わったらTCP接続ごと終了とするみたい。
接続のStream値とWindowサイズの変更を行うリクエスト。
ここが受け取り口全般を担当する。 まず@stateがnewの場合、受け取るFrameは接続HeaderかSettingリクエストなのでそれを解析している。 それ以外はHandShakeErrorを発火する。
ネットワーク直近のFrameの扱いを行う。 こいつがいるからクライアントからは人間が読めるレベルでのメッセージのやり取りができる。
はじめの8byteをアンパックしてflag, length, type, streamを取得する。 細かいところは後で仕様書を確認。