BitTorrent の Extension Protocol は、BitTorrent のダウンロードプロトコルの機能を拡張および強化するためのメカニズムです。このプロトコルでは、クライアントは標準のプロトコルとは異なるメッセージを送信および応答することで通信を行うことができます。これらのメッセージによって、DHT(分散ハッシュテーブル)の交換、PEX(ピア交換)などの新しい機能を実現することができます。
Extension Protocol は、BitTorrent プロトコルにおいて非常に重要な役割を果たしています。これにより、クライアントはより効率的かつ信頼性の高いデータ交換が可能となり、より良いプライバシーとセキュリティが提供されます。たとえば、DHT はトラッカーなしでネットワークに接続されている他のピアを検索することができます。PEX はクライアントが直接他のクライアントと通信することを可能にし、データ交換をより安定させることができます。
プロトコルの概要#
このプロトコルの目的は、BitTorrent プロトコルの拡張に対してシンプルで軽量な転送方法を提供することです。このプロトコルをサポートすることで、他のクライアントに影響を与えることなく、標準の BitTorrent プロトコルを妨げることなく、および追加したい拡張機能をサポートしていないクライアントをサポートすることが容易になります。つまり、このプロトコルは柔軟で拡張可能なメカニズムを提供し、開発者が BitTorrent プロトコルを個別に拡張およびカスタマイズすることができるようにします。
BitTorrent プロトコルでは、自分自身を他のサポートされているクライアントに広めるために、予約されたバイトの中の 1 バイトを使用します。その中で、拡張プロトコルに使用されるバイトは、右から数えて 20 番目のバイトです(0 から数えます)。したがって、式(reserved_byte [5] & 0x10)を使用して、クライアントが拡張メッセージの送信をサポートしているかどうかを確認することができます。この式の意味は、予約されたバイトの 5 番目のバイトと 0x10 をビットごとの論理積演算を行い、結果が 0 でない場合、クライアントが拡張メッセージをサポートしていることを示します。
プロトコルのサポートを確立した後、クライアントは 1 つの新しいメッセージをサポートする必要があります:
name | id |
---|---|
extended | 20 |
このメッセージは他の BitTorrent メッセージと同様に、4 バイトの長さプレフィックスと 1 バイトの識別子(この場合は 20)で送信されます。ペイロードの先頭には、1 バイトのメッセージ識別子があります。この識別子は異なる拡張メッセージを参照することができますが、ID は 1 つだけ指定されます(つまり、0)。ID が 0 の場合、このメッセージはハンドシェイクメッセージであり、後述します。一般的な拡張メッセージのレイアウトは次のようになります(BitTorrent プロトコルで使用されるメッセージヘッダも含まれます):
size | description |
---|---|
uint32_t | 長さプレフィックス。メッセージ全体のバイト数を指定します。(ビッグエンディアン 1) |
uint8_t | bittorrent メッセージ ID、= 20 |
uint8_t | 拡張メッセージ ID。0 = ハンドシェイク、> 0 = ハンドシェイクで指定された拡張メッセージ。 |
ハンドシェイクメッセージ#
ハンドシェイクメッセージのペイロードは、bencoded 辞書です。辞書内のすべての項目はオプションです。クライアントは、辞書内の未知の名前を無視する必要があります。辞書のすべての部分は大文字と小文字を区別します。辞書では、次の項目が定義されています:
name | description |
---|---|
m | サポートされている拡張メッセージの辞書は、各拡張メッセージの名前を拡張メッセージ ID にマッピングします。これらの ID には、2 つの拡張メッセージが同じ ID を共有することはできないという唯一の要件があります。拡張番号を 0 に設定すると、その拡張がサポートされていない / 無効になります。クライアントは、認識できない拡張名を無視する必要があります。拡張メッセージ ID は、このハンドシェイクを送信するピアに拡張メッセージを送信するための ID です。つまり、これらの ID はこの特定のピアのローカル ID です。 |
以下に、実装がサポートする可能性のあるいくつかの項目を示します:
name | description |
---|---|
p | ローカル TCP リスニングポート。各パーティは他方の TCP ポート番号を知ることができます。ただし、接続を受け入れる側はこの拡張メッセージを送信する必要はありません。なぜなら、そのポート番号は既知だからです。 |
v | クライアントの名前とバージョン(UTF-8 文字列として)。これはピア ID エンコードに依存するよりも信頼性の高いクライアントの識別方法です。 |
yourip | このノードがあなたの IP アドレスを見るために使用する、IP アドレスのコンパクトな表現を含む文字列です。つまり、これは受信側の外部 IP アドレス(ポートを含まない)です。IPv4(4 バイト)または IPv6(16 バイト)アドレスのいずれかです。 |
ipv6 | このノードが IPv6 インターフェースを持っている場合、そのアドレスのコンパクトな表現(16 バイト)です。クライアントは IPv6 アドレスを使用して接続することを好む場合があります。 |
ipv4 | このノードが IPv4 インターフェースを持っている場合、そのアドレスのコンパクトな表現(4 バイト)です。クライアントは IPv4 アドレスを使用して接続することを好む場合があります。 |
reqq | 未完了のリクエストメッセージの数を表す整数で、メッセージの損失はありません。libtorrent では、デフォルト値は 250 です。 |
ハンドシェイク辞書には、サポートされている拡張のハンドシェイク情報など、他の拡張も含めることができます。
以下は、ハンドシェイクメッセージのペイロードの例です:
Dictionary | |
---|---|
m | Dictionary / LT_metadata······1 / ut_pex··················2 |
p | 6881 |
v | “µTorrent 1.2” |
エンコード形式では次のようになります:
d1:md11:LT_metadatai1e6:µT_PEXi2ee1:pi6881e1:v13:\xc2\xb5Torrent 1.2e
拡張名が誤って衝突するのを避けるために、拡張名の前に拡張を導入したクライアントを識別するための 1〜2 文字のコードを追加する必要があります。これは、拡張メッセージの名前だけでなく、トップレベルの辞書に含まれる他の情報にも適用されます。この仕様で定義されていない限り、すべての 1 バイトおよび 2 バイトの識別子は無効です。
このメッセージは、この拡張プロトコルをサポートするノードに対して、標準の BitTorrent ハンドシェイクの直後に即座に送信する必要があります。接続の全体のサイクル中に複数回ハンドシェイクメッセージを送信することができ、送信側は接続を切断すべきではありません。実装は、後続のハンドシェイクメッセージ(またはその一部)を無視することを選択することができます。
その後のハンドシェイクメッセージは、接続を再起動せずに拡張を有効化 / 無効化するために使用できます。拡張を変更する場合は、m 辞書が累積されることに注意する必要があります。実際の変更が拡張リストをカバーしていれば十分です。LT_metadata のサポートを実行時に無効にするが、他の拡張には影響を与えない場合は、このメッセージを送信する必要があります:d11 。前述のように、値 0 は拡張を無効にするために使用されます。
各ノードは拡張 ID を保存する必要があります。なぜなら、同じ拡張を持つノードでも異なる ID を持つ可能性があるからです。
この仕様では、ノード交換やメタデータ交換などの特定の拡張を指定していません。このプロトコルは、実際の BitTorrent プロトコルの拡張のための転送方法であり、上記の例で名前が付けられた拡張(例:p)は単なる例です。