KancolleSniffer流FiddlerCoreの使い方

FiddlerCoreFiddlerというHTTPデバッグプロキシの、プロキシ実装部分を取り出したライブラリである。アプリケーションに組み込むと、通信内容の取得や書き換えを目的としたHTTPプロキシを簡単に実装できる。

FiddlerCoreはブラウザゲームの支援ツールの作成に便利なライブラリである。Googleの検索結果も上から二つは、艦これの専ブラの作者のページとなっている。

専ブラの実装にFiddlerCoreを使う場合の説明は、上の検索結果のトップのページが詳しい。専ブラの場合の通信の流れは、コンポーネントブラウザ⇔専ブラ⇔艦これサーバーとなる。

KancolleSnifferはFiddlerCoreでシステムプロキシを乗っ取っている。そのため通信の流れは、任意のHTTPクライアント⇔KancolleSniffer⇔インターネットとなる。HTTPが全部KancolleSnifferを経由する。それでも、特にHTTPのレスポンスが悪くなったり、CPUの負荷が上がったりはしない。

FiddlerCoreでシステムプロキシを乗っ取るときは、スタートアップで以下のようにフラグを指定する。

FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.RegisterAsSystemProxy);

乗っ取ったHTTPの内容は、クライアントにレスポンスを返し終わってから呼ばれる、AfterSessionCompleteのイベントハンドラで取得できる。たいていの場合はこれで問題ないはずだ。KancolleSnifferもバージョン1.11まではそうしていた。

Fiddler.FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete

次期バージョンでは戦闘開始のタイミングをプレイ画面と同期する必要があるため、クライアントにレスポンスを返す前に呼ばれる、BeforeResponseのハンドラを使うようにした。

FiddlerApplication.BeforeResponse += FiddlerApplication_BeforeResponse;

これには一つわながあって、FiddlerCoreはストリーミングモードで動いているので、BeforeResponseのハンドラを呼ぶと同時にクライアントへのレスポンスの送出を始めてしまう。これでは同期しない。

そこでリクエストを送る前に呼ばれるBeforeRequestのハンドラで、戦闘のAPIだけはFiddlerCoreがバッファリングモードで動くようにしている。ついでに、艦これ以外でBeforeResponseが呼ばれないように、SessionオブジェクトのIgnoreメソッドを呼んでいる。

private void FiddlerApplication_BeforeRequest(Session oSession)
{
    var path = oSession.PathAndQuery;
    if (!path.StartsWith("/kcsapi/api_")) // 艦これのAPI以外は無視する
    {
	oSession.Ignore();
	return;
    }
    // 戦闘開始のタイミングのずれを防ぐためにバッファする
    if (path.EndsWith("api_req_sortie/battle") || path.EndsWith("api_req_practice/battle"))
	oSession.bBufferResponse = true;
}

交戦形を表示しようと思っただけなのに死ぬほど面倒なことになって、何度ぶん投げようと思ったかわからないけど、これでようやく表示が意図通りのタイミングになった。