言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

WikiPhone 仕様

2006年7月17日現在の WikiPhone (WikiPhone-Client-tak.9, WikiPhone-Morphoc-tak.9, WikiPhone-Server-tak.9) http://www.squeaksource.com/WikiPhone.html について書きます。

WikiPhone プロトコルの目的

WikiPhone は、設定無しで利用出来る匿名のボイスチャットとして設計されました。ファイアウォール設定やログイン等の設定が不要である事、応用アプリケーションの作成が容易である事を優先的な目標としました。音質やセキュリティ等の付加的な要素については可能な限り低優先としました。サーバの高負荷が予想される事から極力サーバ側はシンプルになっています。

WikiPhone プロトコルの概要

システムのトポロジはクライアントサーバ方式となっています。通常、クライアントからサーバへ HTTP/1.1 に則って二本の経路で接続します。それぞれ受信専用、送信専用に使います。受信、送信とも転送方式に chunked を利用します。送受信とも、構成は次のようになっています。

  • HTTP ヘッダ
    • HTTP メソッドとして受信に GET, 送信に PUT を使います。
    • URL (現在 host: を見てません。パス名のみで識別します)。
  • HTTP 本体
    • chunked メッセージ
      • chunked ヘッダ
        • chunked ボディの長さが記録されます。
        • key=value; の形で任意のデータを付加出来ます。
        • キーとして、最低限 from (送信者を識別するランダムな文字列) が必要です。
      • chunked ボディ
        • アプリケーション依存の内容です。
    • chunked メッセージの繰り返し(多分 100回くらい)
  • HTTP ヘッダと本体は 100 回程度送られてから切断されます。

クライアントはサーバに、あて先 URL を含めてデータを送信します。通信は chunked 単位で行います。サーバは送られてきた URL を見て、その URL を要求するクライアント全てにヘッダ含めて chunk 全体を転送します。データの種類(コンテンツタイプ、音声圧縮方法など)はすべてクライアント側が責任を負います。ミキシングもクライアントで行います。クライアントは自分の送信したデータも受け取ります。データ本体以外に最低以下の情報を含みます。

  • URL : サーバは同一 URL に情報を配信します。
  • from : chunked ヘッダに送信者がランダムな文字列を記述します。これを元にエコーバックを取り去ります。今はサーバ側では使っていません。

WikiPhone プロトコル GET

クライアントはある URL から情報を受け取る際に GET 要求を行います。通常の HTTP と異なり、GET 後すぐにサーバが応答を返すとは限りません。その URL に送信するクライアントが居ない場合、ある一定時間待って何も無い応答を行います。クライアントは応答があるとすぐに再度 GET 要求を行います。接続は規定の回数もしくは秒数が経過するまで維持されます。

  • 通常の HTTP : GET 要求 -> 応答 -> 待ち(終了) -> GET 要求 -> 応答
  • WikiPhone : GET 要求 -> 待ち -> 応答 -> GET 要求 -> 待ち(終了)

WikiPhone 付属のテキストチャットでの通信例を以下に記します。コンテンツヘッダが text/html なのはブラウザでデバッグする為で、将来変更の可能性があります(変更するべきです)。

(クライアント)
GET /chat HTTP/1.1
Host: languagegame.org

(サーバ)
HTTP/1.1 200 OK
Keep-Alive: timeout=100, max=100
Date: Thu, 18 Jan 2007 06:35:15 GMT
Server: Comanche/6.2 (unix)
Connection: Keep-Alive
Content-type: text/html
Transfer-Encoding: chunked

15;from=8gqc2i3g258g69i68aklqx
tamamushi: contents1

15;from=8gqc2i3g258g69i68aklqx
tamamushi: contents2

WikiPhone プロトコル PUT

クライアントは、PUT を使って URL と共にデータを送信します。サーバはそのデータを chunk 単位で URL に待機しているクライアントに配信します。通信例を以下に記します。

(クライアント)
PUT /chat HTTP/1.1
Host: languagegame.org
Transfer-Encoding: chunked

15;from=8gqc2i3g258g69i68aklqx
tamamushi: contents1

15;from=8gqc2i3g258g69i68aklqx
tamamushi: contents2

(サーバ)
HTTP/1.1 201 Created
Keep-Alive: timeout=100, max=100
Date: Thu, 18 Jan 2007 06:37:00 GMT
Server: Comanche/6.2 (unix)
Connection: Keep-Alive
Content-type: text/html
Content-length: 0

WikiPhone ソフトウェア

WikiPhone の実装は、現在 Squeak 3.8 ベースで公開されています。配布物は以下のモジュールを含みます。

  • WPClient : WikiPhone クライアントの実装です。
  • WPServer : WikiPhone サーバの実装です。
  • WPPhone : ボイスチャットの実装です。
  • WPTextChatClient : テキストチャットの実装です。
  • WPPhoneMorph : ボイスチャットの UI です。

以下にテスト用のスクリプトを示します。

url := 'http://languagegame.org:9090/'.

"一回パケットを往復させる。"
Transcript cr; show: (WPClient pingSimple: (url, 'ping') asUrl) asString, ' ms'.

"10 回パケットを往復させてトランスクリプトに成功回数と平均所要時間を出力"
WPClient showPing: (url, 'ping') asUrl.

"showPing: のペルパメソッド"
WPClient ping: (url, 'ping') asUrl count: 3 size: 10 wait: 50 timeout: 500.

"テキストチャットを開く。UI を閉じると終了"
(WPTextChatClient url: url, 'chat') openAsMorph openInHand.

"ボイスチャットを開いてインスペクト"
(WPPhone connectUrl: url, 'phone') inspect.
"ボイスチャットを終了"
(WPPhone disconnectUrl: url, 'phone').

"録音と再生のエコー(ネットワーク抜きの遅延を計測)"
WPSoundRecorder example1.

WikiPhone ボイスチャット

WikiPhone プロトコルの主な用途がボイスチャットです。特徴を挙げます。

  • 圧縮方式: GSM
  • サンプリング周波数: 22050 Hz (Squeak の SoundPlayer の都合)
  • ビットレート: 45kbit / s (4,547 bytes/s = 11025 * 33 / 160)
  • バッファサイズ 1600 bytes (36 ms = 1600 / 2 / 11025)
  • 遅延 490 ms (国内) - 890 ms (海外)
    • 録音遅延 300 ms (Squeak VM の問題)
    • 送信バッファ遅延 36 ms
    • 通信遅延(RTT) 100 ms (国内) - 500 ms (大阪 - ロサンゼルス)
    • 受信バッファ遅延 36 ms
    • ミキシング/再生遅延 20 ms

他の VoIP プロトコルとの比較

一般的な VoIP として H.323 と比較します。プロトコルの特徴は、様々な方式を組み合わせて利用する H.323 に比べて、WikiPhone がほとんど HTTP の機能をそのまま流用している所にあります。他のメジャーな方式である SIP と比較しても、動作形態は単純です。

  • 端末の登録 RAS (WikiPhone では該当機能なし)
  • アドレス解釈 RAS (WikiPhone では HTTP を流用)
  • セッション確立 Q.931 H.425 (WikiPhone では HTTP を流用)
  • 通信 RTP (WikiPhone では HTTP を流用)
  • セッション終了 H.245 Q.931 RAS (WikiPhone では HTTP を流用)

しかし最大の違いは、他のプロトコルと異なり音声通信に TCP を利用している所です。TCP は遅延が大きいため、一般に VoIP に不適切であるとされています。WikiPhone の遅延のうち、通信遅延以外の録音やバッファの要因についてはすぐにでも改善可能ですが、TCP の速度はソフトウェアで解決出来ない問題です。

今後 TCP の遅延がどう変化するかは、TCP の使われ方に左右されます。TCP はその性質上、スループットと遅延に大きな相関性があり、遅延が短ければ短いほど大容量のスループットを得る事が出来ます。と言う事は、大きな TCP アクセスの需要があれば必然的に全体的な遅延も低下するという事です。例えば G.114 勧告にある 150 ms 以下の遅延に対応する為に、次のような条件を考えています(id:io_oi 氏の指摘により変更)。

  • 遅延 150 ms
    • 録音遅延 8 ms (176 bytes : 88 frames)
    • 通信遅延(RTT) 133 ms
    • ミキシング/再生遅延 8 ms

と言う事は将来海外への TCP の遅延が 133 ms に収まれば、WikiPhone の方式でも十分な音声品質が実現できると期待しています。

TCPスループットと遅延の理論値

一般に、TCP の理論的なスループットはウインドウサイズ / RTT(Round Trip Time) で表されます。Windows XP の標準ウインドウサイズが 16KB である事から、例えば 1.8 Mbit/s のスループットを得るには 70ms (1872686 bit/s = 16386 byte * 8 / 0.07s ) の RTT が必要です。逆に言うと、将来日米間で 1.8 Mbit/s ものスループットの需要が生まれればアメリカまで十分な遅延で通話出来る可能性があるという事です。

http://www.macnica.net/lanch/lanch62/np01.html

id:io_oi 氏に光速の限界についてご指摘を受けましたので再度条件を見直してみました。地球の直径が 40,000,000 m で、光速が 300,000,000 m/s として、裏側までの往復に 0.133 s (40 Mm /300 Mm) かかります。と言う事は条件である 150 ms を満たす為には残り 17 ms しか残されていないという事です。

現状では、色々無駄に遅延がありますがどうしても譲れないのが録音と再生に関わるバッファ遅延で、どれくらいの頻度で音声データを取り込むかというのを表しています。17 ms のうち 8 ms ずつバッファに使えるとします。残りの 1 ms はコピーにかける為にとっておきます(1GHz のパソコンで百万サイクル分)。サンプルレートとして 11,025 frames / s を使うとすると 176 bytes (11,025 * 2 * 0.008) をバッファに使えばよいという事です。176 bytes (88 frames) というのはスクイークでやるには厳しいですが、現実的な値です。

これを UDP でやるとどれくらい速くなるかと言うと、着信確認を待つ時間を省略できるので倍以上の速さになります。というか、150 ms は厳しいにしても 500 ms の遅延なら今でも可能なので、それくらい待ってゆっくりしゃべれば良いじゃないかと思います。

改訂

2007-01-21

  • サンプリングレートはよく見たら 11025 では無くて 22050 にしていました。
  • PUT プロトコルにおいて、サーバが HTTP/1.1 201 Created を返すのはクライアントデータを送信し終わる瞬間でした。