この拡張機能(Peers to Send Metadata Files のための拡張機能)の目的は、クライアントがトレント(.torrent)ファイルを事前にダウンロードすることなく、スワームに参加できるようにすることです。代わりに、この拡張機能ではクライアントが同じ種類のノードからメタデータをダウンロードできるようにします。これにより、マグネットリンクのサポートが可能になり、ウェブページにはスワームに参加するための十分な情報(つまり、info ハッシュ)のみが含まれるようになります。要するに、この拡張機能により、ユーザーはトレント(.torrent)ファイルをダウンロードせずに必要なファイルをダウンロードできるようになります。
メタデータ#
この拡張機能では、メタデータの一部である「info-dictionary」と呼ばれるメタデータのみが転送されます。この部分のデータは、他のクライアントが特定の「スワーム」に参加し、ファイルデータのダウンロードを開始する方法を知るのに十分です。また、メタデータの整合性を確認するために info-hash を使用することで、クライアントが信頼できるソースからメタデータをダウンロードし、悪意のある変更の影響を受けることなくダウンロードできるようになります。
メタデータは、16KiB(16384 バイト)のブロックに分割されて処理されます。これらのメタデータブロックは 0 からインデックスされます。各ブロックのサイズは 16KiB であり、最後のブロックは 16KiB より小さい場合があります。
拡張ヘッダー#
クライアントが他のノードと接続する際、ハンドシェイクメッセージを介して通信を行います。メタデータ拡張は、他のノードに自身の存在を宣言するために、拡張プロトコルで定義された拡張プロトコルを使用します。具体的には、"ut_metadata" エントリを拡張ハンドシェイクメッセージの "m" ディクショナリに追加し、このメッセージで使用されるメッセージコードを識別するために使用します。さらに、ハンドシェイクメッセージに "metadata_size" フィールド("m" ディクショナリには含まれません)を追加し、メタデータのバイト数を指定します。言い換えれば、クライアントと他のノードが接続し、拡張ハンドシェイクを行う際に、メタデータ拡張が利用可能な場合、クライアントは "ut_metadata" と "metadata_size" フィールドを含む拡張ハンドシェイクメッセージを送信し、他のノードにメタデータの取得をサポートしていることを通知します。
拡張ハンドシェイクメッセージの例:
{'m': {'ut_metadata', 3}, 'metadata_size': 31235}
拡張メッセージ#
拡張メッセージはエンコードされています。3 つの異なるタイプのメッセージがあります:
- リクエスト
- データ
- リジェクト
リクエストメッセージ#
リクエストメッセージは、追加のキー(つまり、追加情報)を持たないディクショナリです。ノードがこの拡張をサポートしている場合、リクエストにはリジェクトまたはデータメッセージの応答があり、応答のピースはリクエスト時と同じでなければなりません。具体的には、リクエストと応答の両方が同じデータブロック(ピース)に関連しています。
このネットワークでは、ノードは送信するすべてのデータブロック(ピース)が info-hash の検証を通過していることを確認する必要があります。つまり、ノードは完全なメタデータを取得する前に、SHA-1 アルゴリズムを実行して生成されたハッシュ値が info-hash と一致するかどうかを検証することはできません。ノードに完全なメタデータがない場合、他のノードからメタデータのリクエストを受け取った場合、リクエスト元に対して「リジェクト」メッセージを送信してリクエストを拒否する必要があります。これは、完全なメタデータを持つノードのみが正しく info-hash の検証を行えるためです。したがって、このネットワークはファイル転送の完全性と正確性を確保し、潜在的な悪意のある操作やデータの破損を防ぎます。
例:
{'msg_type': 0, 'piece': 0}
d8:msg_typei0e5:piecei0ee
リクエストメッセージは最初のメタデータピースをリクエストしています。
データメッセージ#
データメッセージは、辞書に新しいエントリである「total_size」を追加します。このキーは、拡張ヘッダーの「metadata_size」と同じ意味を持ち、整数値を持ちます。このキーは、受信側が完全なデータを完全に再構築するために必要なデータブロック全体の合計サイズまたは長さを示します。
メタデータを転送する際には、辞書をバイナリデータにシリアライズし、プロトコルの要件に従って長さのプレフィックスを付ける必要があります。この長さのプレフィックスには、辞書自体の長さだけでなく、メタデータのいくつかの追加情報も含まれます。これらの追加情報はメタデータピースと呼ばれますが、辞書の一部ではなく、メッセージの一部です。メタデータピースがメタデータの最後の部分である場合、そのサイズは 16KB 未満である場合がありますが、最後の部分でない場合は 16KB でなければなりません。
例:
{'msg_type': 1, 'piece': 0, 'total_size': 3425}
d8:msg_typei1e5:piecei0e10:total_sizei34256eexxxxxxxx...
x はバイナリデータ(メタデータ)を表します。
リジェクトメッセージ#
リジェクトメッセージには、追加のキーまたは値は含まれません。このメッセージを受け取った場合、要求されたメタデータが対応するピアに存在しないことを理解する必要があります。これは、対応するピアが必要なデータピースを提供できないことを意味します。クライアントは、一定数のリクエストメッセージをサービスした後にリジェクトメッセージを送信して洪水攻撃を防ぐことができます。この数は通常、要求されたメタデータブロック数に乗算される係数です。
例:
{'msg_type': 2, 'piece': 0}
d8:msg_typei1e5:piecei0ee
Magnet URI の形式#
Magnet URI の形式は次のとおりです:
v1: magnet:?xt=urn:btih:<info-hash>&dn=<name>&tr=<tracker-url>&x.pe=<peer-address>
v2: magnet:?xt=urn:btmh:<tagged-info-hash>&dn=<name>&tr=<tracker-url>&x.pe=<peer-address>
<info-hash>
<tagged-info-hash>
<peer-address>
xt
dn
tr
x.pe
詳細については、こちらの記事をご覧ください。