ZMODEM送信の相互運用性およびパフォーマンス
解析と指摘ありがとうございます。私はZMODEMの仕様を把握しておらず、使用もしていないので助かります。
互換性オプションを提案されているということは、提案された新仕様を実装すると、従来の実装で動作していた対向のZMODEM実装では扱えないことがありそう、ということですか?
新仕様での実装を試しておられるようですが、BSDライセンスでパッチとして提供して頂くことは可能ですか?
返答が遅くなり申し訳ありません。
まずはウィンドウサイズについてですが、あれからいろいろ考えてみたところ、先の提案では不十分だったと理解しました。 よって変更の提案自体は取り下げたいとおもいます。 問題点および改善策については今後考えてみたいとおもいます。
本質的には、Teraterm が数えている winsize は、ペイロードを数えていて、 受け側(対向)の許容受信サイズの指定が困難です。ヘッダ, CRC, そしてエスケープを加味しなくてはなりません。 対向が充足する受信バッファの大きさを決定するのは容易ではありません。 現に、対向の受信バッファを 32767 octets にしてみたのですが、対向の処理が間に合わないケースでは容易にオーバーランします。 オーバーランの結果、再送が生じ、パフォーマンスロスとなります。
ZCRC* の件につきましては、先の提案でおおむね快調に動いていますが、ZDATA において ZCRCW を選択するのは ベターではなく、すべて ZCRCQ を用いる方が動作に一貫性が出てきます。 半二重なシーケンスがなくなるため、転送レートもややアップします。
旧仕様を選択可能にする件につきましては、Teraterm依存のクライアントを組んでしまっている人がいるのではないかという 危惧によるものです。旧仕様を残すべきか、旧版を利用することで回避してもらうかは、私からなんとも申し上げられません。
パッチ作成についてはぜひと申し上げたいところですが、職場で試していたもので、それを持ち出すのは大げさな話に なりそうなので、自宅でビルド環境および再現環境を構築してからの話になりそうです。少々お時間をいただくことになりそうです。 もし他の方が実装して追試していただけるのであれば歓迎です。 (参考までに、私はTeraterm全体をビルドせず、CMake+cygwin-mingw で ttpfile.dll だけを作成しリリースバイナリと差し替えて実験してました)
余談になりますが、いろいろ評価していて、teratermのオーバーヘッドが無視できない程度に大きく、 実効値が理論値に届いていないのでは? という疑念を持っています。 ZMODEM送信のケースですと 921600 noflow において転送レートが 56KB/s 程度です。 気が向いたら自宅でループバック(USBシリアルどうしのクロス接続)組んで計測してみます。
対向の組み込みOSに対しZMODEM受信を試みています。 Teraterm ZMODEM 送信の思わしくない挙動・実装を見出したので報告します。 主に利用しているのは 4.103 ですが trunk でも同様です。 使用レートは 115200~921600bps, 8N1 noflow です。
ウィンドウサイズ
現実装ではウィンドウサイズを超過した送信を試みるような実装になっているようです。 対向の受信バッファサイズをTeratermウィンドウサイズ(デフォ 32767)と同じにした場合、この送信は受信側でオーバーランすることがあります。 オーバーランした場合、(ZCRCQを投げているにもかかわらず)ZACKが返ってくることはまずありません。
zmodem.c:625
これは送信動作後に実施されていますが、チェックは zv->WinSize を拠り所とするのではなく (zv->WinSize - zv->MaxDataLen) にした方が安全ではないでしょうか?
ZDATA 時の ZCRC* 選定
現実装では、ウィンドウサイズに収まっている場合に ZCRCG, ウィンドウサイズを超過したときにZCRCQを投げるようになっています。 対向は ZCRCG に対して ZACK を返送しないのがふつうなので、以下のようなシーケンスが発生します。
短くまとめると、Teraterm はスライディングウィンドウ動作ではなく、ウィンドウサイズ単位の半二重通信をしてしまっています。
ホスト側が USB Serial を利用しているような場合だと、USB起因の遅延も加味され、半二重通信のレイテンシ(ZCRCQ->ZACK->ZDATA)は顕著に増大します。
ZMODEM プロトコル仕様書を斜め読みしたうえで Teraterm 現実装の問題を以下にまとめます。
改善案を以下に挙げます。
以上の変更を 1.103 の ttpfile/zmodem.c に施したうえで試してみましたが、結果は良好です。対向のCPU時間に余裕があるケースでは ZCRCW を投げることはなくなり、対向が間に合わない場合でも ZCRCW により再送を発生させず待つことができるようになりました。
Teraterm 自体、歴史のあるものなので、互換オプションを設けるのはいかがでしょうか。
以上、提案します。ご検討ください。