読者です 読者をやめる 読者になる 読者になる

ポジローぽけっと

昨日より今日、今日より明日を信じて、トライトライ

第三十三回スパルタンプログラミング

出向先会社の2014年度振り返り会後、

懇親会->クラブ花園->乱->雷神ラーメン->ヒロ宅ざこね->いっしー宅腹痛

を経てプログラム開始。牛乳は体に合わん!

やりたいこと

nghttp2のHPACK部分コードの読み解き

やったこと

コード読んだ

どっかの.c

  • nghttp2_nv:name/value pair, which mainly used to represent header fields.
    • header nameは":"ではじまるex. :scheme, :authority, :pathなど
    • header valueはheader nameに続くその値、nameが:schemeならvalueはhttps, nameがaccept-encodingならvalueはgzip, deflate
  • nghttp2_hd_deflater

deflate.c

  • nghttp2_hd_deflate_new call
    • nghttp2_hd_deflate_new2 call
      • nghttp2_mem_default()、nghttp2_mem型(malloc, free, calloc, reallocの関数ポインタを保持する構造体)にdefaultの関数ポインタを代入。
      • nghttp2_mem_malloc、nghttp2_hd_deflater型のdeflaterの領域確保
      • nghttp2_mem_deflate_init2、deflaterの初期化
  • nghttp2_hd_inflate_newは多分同じようなことやってそうだから割愛
  • deflate call
    • -nghttp2_hd_deflate_bound call below and return buflen(上限長さ)
    • -nghttp2_hd_deflate_hd call below and return buflen(圧縮後の長さ)
      • -- nghttp2_hd_deflate_hd_bufs call below and return rv
        • --- emit_table_size
        • --- deflate_nv(ヘッダー圧縮のコア) call below and return rv
          • ---- search_hd_table(動的テーブル、静的テーブルからヘッダに対応するindexをsearch)
          • ---- emit_indexed_block(テーブルにあれば)
            • ----- count_encoded_length, encode_length, nghttp2_bufs_add
          • ---- hd_deflate_should_indexing(テーブルになければ)
            • ----- entry_room
          • ---- nghttp2_hd_table_get(テーブルからindexに対応するname取得)
          • ---- add_hd_table_incremental
          • ---- nghttp2_hd_entry_free
          • ---- nghttp2_mem_free
          • ---- emit_newname_block(テーブルにidxなければ) or emit_indname_block(テーブルにidxあれば)
      • -- nghttp2_bufs_len
      • -- nghttp2_bufs_wrap_free
      • inflate_header_block repeats below
        • -- nghttp2_hd_inflate_hd(stateで圧縮後バイナリの最終ポインタに達するまで動作)
          • --- hd_inflate_read_len(for HPACK 5.1.のInteger Representation)
            • ---- decode_length(HPACK 5.1.のdecode I from the next N bits)
        • -- nghttp2_hd_inflate_end_headers just call hd_inflate_keep_free

hd, hdって最初何を指してるか分からなかったけど、headerのことか。。

nghttp2_hd_inflate_hfのstateを理解しよ

typedef enum {
  NGHTTP2_HD_STATE_OPCODE,//初期
  NGHTTP2_HD_STATE_READ_TABLE_SIZE,//HPACK6.3
  NGHTTP2_HD_STATE_READ_INDEX,//HPACK6.1. and HPACK6.2のindexed
  NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,//HPACK6.2のnewname
  NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,//
  NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF,//hd_inflate_read_huff->nghttp2_hd_huff_decodeで復号
  NGHTTP2_HD_STATE_NEWNAME_READ_NAME,//hd_inflate_readでbufにつめるだけ
  NGHTTP2_HD_STATE_CHECK_VALUELEN,//
  NGHTTP2_HD_STATE_READ_VALUELEN,//
  NGHTTP2_HD_STATE_READ_VALUEHUFF,//hd_inflate_read_huff->nghttp2_hd_huff_decodeで復号
  NGHTTP2_HD_STATE_READ_VALUE//hd_inflate_readでbufにつめるだけ
} nghttp2_hd_inflate_state;

そもそも

HPACK:http2のヘッダ圧縮方式

基礎勉強

関数ポインタ

宣言は

double (*func)(double)

1番目のdoubleが戻り値、*funcが関数ポインタ、2番目doubleが引数。 使い方は

func=sin;//sin関数のエントリアドレスをポインタ変数へ代入 val=(*func)(0.0);//関数呼び出し

引数にとる例

int main(void){
  calc(sin);
  calc(cos);
  return 0;
}
void calc(double (*func)(double)){
  printf("%f\n",(*func)(0.0));
}

typedefで関数型定義

typedef void (nghttp2_malloc)(size_t size, void *mem_user_data);

  • void *を返し、
  • size_t size, void *mem_user_dataを引数にもつ、
  • 関数へのポインタとしてnghttp2_malloc を定義

ちょい技

  • windowsのalt+tabはmacのcommand+tab
  • vimでclipboard共有するには -- vimrcにset clipboard=unnamed
  • vimrcの再読み込み -- :source ~/.vimrc

参考

HPACK 05 の実装と解析

パフォーマンスの基礎とこれから よくわかんないけど読んでて面白かった。センス◎

Reference Set とは何だったのか

HTTP2のヘッダ圧縮 Huffman Encode の原理とメリット・デメリット