NetworkStream.DataAvailable は HTTP レスポンスの終端を示さない
終了条件として NetworkStream.DataAvailable ではなくメッセージフレーミングを使い、切り詰められた HTTP ダウンロードを防ぐ。
NetworkStream.DataAvailable == false は、すぐに読めるバイトが無いことを意味する。HTTP レスポンスが完了したことを意味するわけではない。そこで止まるループは、パケット間の間隙でごく普通の SOCKS ダウンロードを切り詰めかねない。
SOCKS が TCP 接続を確立した後も、完了規則を与えるのは HTTP のフレーミングである:
- Content-Length のボディは、宣言されたコンテンツバイトの後に終わる。
- chunked レスポンスには終端チャンクと該当する trailer が必要である。
- 接続で区切られたレスポンスは接続とともに終わる。
- 一部のステータスと HEAD へのレスポンスにはボディが無い。
適用される規則を決めるにはステータスとヘッダーを読む。閉鎖だけを待つのは一般的な解決策ではない。完全な HTTP レスポンスでも接続が開いたままになることがあるからだ。1 つのバッファーの容量もレスポンスの長さとは無関係である。
選択したプロキシ転送を HTTP クライアントのフレーミング実装が支える場合はそれを使う。互換性のある現代の .NET ランタイムでは HttpClient のネイティブ SOCKS サポートを検討する。生の実装では、部分的なヘッダー読み取りとボディ読み取りの間で解析状態を保ち、正常な完了をキャンセル、タイムアウト、予期しない EOF と区別しなければならない。空でない読み取り要求では、0 バイトの読み取りはストリームの終了を意味する。これは今キューにバイトが無いこととは異なる。
プロキシはタイミングの間隙を目立たせることがあるが、空の受信キューをメッセージ終端の印に変えるわけではない。