Relay メッセージプロトコル

プロジェクトで UTP または NGO を使用した Relay SDK を使用している場合は、Relay メッセージプロトコルが既にサポートされています。ただし、代替のエンジンやネットワーキングソリューションを使用したい場合は、まず Relay メッセージプロトコルを実装する必要があります。Relay メッセージプロトコルの仕様を使用して、Relay メッセージプロトコルを実装してください。

Relay メッセージプロトコルでは、フィールドの値がビッグエンディアンの順序で表現されることを前提としています。これは “ネットワークオーダー” とも呼ばれ、最も重要なバイトが最初に来ます。

メッセージは認証されません。ただし、HMAC 署名が使用される BIND メッセージ は例外です。

プレイヤー が接続してメッセージをリレーできるは、同じ Unity プロジェクトの同じ環境から参加している他のプレイヤーのみとなります。Unity 環境間をまたいだ通信の試行は Relay によって拒否されます。

すべてのメッセージには、標準のヘッダーと、メッセージ固有の本文があります。標準ヘッダーメッセージ本文 を参照してください。

メッセージの種類

コード名前説明
0BIND メッセージBIND メッセージは、クライアントから Relay サーバーに送信されるバインドリクエストを示します。
1BIND_RECEIVED メッセージBIND_RECEIVED メッセージは、BIND リクエスト の受信後に、Relay サーバーからクライアントへの応答が成功したことを示します。
2PING メッセージPING メッセージは、接続を維持するためにクライアントと Relay サーバー間で送信される PING メッセージ (双方向) を示します。
3CONNECT_REQUEST メッセージCONNECT_REQUEST メッセージは、プレイヤー (リクエスト元クライアント) から別のプレイヤー (ターゲットクライアント) への接続要求を示します。
4予約済み。
5予約済み。
6ACCEPTED メッセージACCEPTED メッセージは、ターゲットクライアントへの接続が成功した後に Relay サーバーからリクエスト元クライアントに送信される確認メッセージを示します。
7予約済み。
8予約済み。
9DISCONNECT メッセージDISCONNECT メッセージは、接続された 2 人のプレイヤーを切断するリクエストを示します。
10RELAY メッセージRELAY メッセージは、2 人のプレイヤー (クライアント) 間でメッセージを送信するリクエストを示します。
11CLOSE メッセージCLOSE メッセージは、Relay サーバーからのバインド解除を求めるクライアントからのリクエストを示します。
12ERROR メッセージERROR メッセージは発生したエラーを示します。

承諾モードの種類

承諾モードは、クライアント からの接続リクエストを Relay サーバー がどのように処理するかを定義するものです。

Relay では、AUTO 承諾モードのみがサポートされています。AUTO モードの接続は、Relay サーバーのキャパシティを超えていなければ (接続数が許容される最大接続数を超えていなければ)、自動的に承諾されます。

コード名前説明
0AcceptModeAutoAcceptModeAuto は、クライアントへの接続が Relay サーバーによって自動的に承諾されることを示します。
1 予約済み。

標準ヘッダー

すべてのメッセージタイプには共有の標準ヘッダーがあり、そのヘッダーには署名、Relay メッセージプロトコルのバージョン、およびパケットの本体に含まれるメッセージが含まれています。

バイト1 ..234
目的SignatureVersionType

以下の表は、標準ヘッダー内にある各フィールドについて説明したものです。

フィールドType説明
Signature[]byteSignature は常に 0xDA72 です。
Versionuint8Version は Relay メッセージプロトコルのバージョンです。

初期リリースの場合、この値は 0 になります。

Typeuint8Type は、本体に含まれるメッセージの種類を表す整数です。メッセージの種類 を参照してください。

メッセージ本文

BIND メッセージ

BIND メッセージは、特定の割り当てに対応するクライアントの IP アドレスとポートのマッピングを作成するために、クライアントから Relay サーバーに送信されます。このメッセージは、クライアントの ID を確認するために認証されます。

割り当てサービス から受信した応答には、クライアントが BIND メッセージを認証するために必要な情報が含まれています。BIND メッセージに対する割り当てサービスからの応答は、バインディングの状態を示します。

クライアントは、クライアントの IP アドレスとポートが変更されていない限り、同じ BIND メッセージを送信できます。例えば、クライアントが IP アドレスまたはポートを変更した後の次の接続で BIND メッセージを送信する場合、Nonce 値は以前に指定された値よりも大きくなければなりません。

バイト1 ..456 ..789 ..NN+1 ..33
目的ヘッダー (タイプ 0)AcceptModeNonceConnectionDataLengthConnectionDataHMAC

以下の表は、BIND メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
AcceptModeuint8AcceptMode は、この割り当ての所有者への接続を試みるクライアントからのリクエストを、Relay サーバーがどのように処理すべきかを定義するものです。

現在、AUTO 承諾モードのみがサポートされています。

承諾モードの種類 を参照してください。

Nonceuint16Nonce は一度だけ使用される暗号学的なノンスです。後続の BIND メッセージごとに、nonce の値を増加させる必要があります。nonce の値は 0 から開始するのが一般的です。
ConnectionDataLengthuint8ConnectionDataLengthConnectionData のバイト長を示します。

許容される最大値は 255 です。

ConnectionData[]byteConnectionData は、接続中のクライアント の暗号化された 接続データ です。

このフィールドの長さは可変です。最大長は 255 バイトです。

HMAC[32]byteHMAC は、既知のキーとメッセージ内の前のバイト (ヘッダーを含む) を使用して生成される、ハッシュベースのメッセージ認証コードです。

認証 を参照してください。

セキュリティ

HMAC には、割り当てサービス から返された秘密鍵で署名する必要があります。HMAC が無効である場合、Relay サーバーは BIND message メッセージを暗黙的に拒否します。

また、Relay サーバーは悪意のある攻撃者によるメッセージリプレイ攻撃を軽減するために、nonce 値を検証します。nonce が無効であると判断した場合、Relay サーバーはメッセージを暗黙的に拒否します。クライアントが BIND message メッセージを使用して初めて Relay サーバーにバインドする場合は、nonce 値を 0 にできます。

BIND_RECEIVED メッセージ

Relay サーバーは、リクエスト元クライアントが BIND message メッセージを通じて自身に正常にバインドされたことを確認するために、そのクライアントに BIND_RECEIVED メッセージを送信します。確認を受信した後、リクエスト元クライアントは CONNECT_REQUEST message メッセージを使用してターゲットクライアントとの通信を開始できます。

ノート: Relay サーバーは、BIND_RECEIVED が正常に処理されるごとに、クライアントに BIND request メッセージを送信します。

バイト1 ..4
目的ヘッダー (タイプ 1)

PING メッセージ

PING メッセージは、クライアントタイムアウト をリセットして、クライアントと Relay サーバー のバインディングを維持するためのシンプルなメッセージです。Relay サーバーは、10 秒間アクティビティがないと自動的にクライアントを切断します。このクライアントに関連して Relay サーバーが受信した (送信者または受信者としての) メッセージがある場合、このタイムアウトはリセットされます。メッセージの頻度が低いゲームでは、PING メッセージを使用してクライアントが切断タイマーをリセットできます。

ヒント: クライアントは、接続がタイムアウトしないように、他のメッセージに加えて PING メッセージを 1 秒または 2 秒ごとに送信する必要があります。NGO を使用した Relay を使用している場合は、ネットワークマネージャーによって接続が自動的に維持されます。ただし、UTP を使用した Relay を使用している場合は、手動で 接続を維持する 必要があります。

PING メッセージには、クライアントの割り当て ID と、メッセージを識別するための任意の番号が含まれています。

Relay サーバーは、クライアントから PING メッセージを受信すると、それを変更せずにパケットをクライアントに送り返します。そのため、PING メッセージは接続状態を確認し、ラウンドトリップ時間を測定するために使用できます。

割り当て ID が期限切れになった場合、Relay サーバーからエラーメッセージは返されません。

警告: クライアントは、PING メッセージを送信する前に、BIND メッセージ を介して Relay サーバーにバインドする必要があります。以下のシナリオでは、Relay サーバーから ErrClientPlayerMismatchERROR メッセージ が返されます。

  • クライアントが BIND メッセージを介して Relay サーバーにバインドする前に PING メッセージを送信した。
  • クライアントが IP アドレスを変更した後、新しい IP アドレスで Relay サーバーに再バインドする前に PING メッセージを送信した。
バイト1 ..45 ..2021 ..22
目的ヘッダー (タイプ 2)AllocationIDNumber

以下の表は、PING メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
AllocationID[16]byteAllocationID は、PING を送信している割り当て済みクライアントを識別する 16 バイトの UUID です。
Numberuint16Number は、Relay サーバーがクライアントにエコーバックする任意の符号なし整数です。クライアントはこれを使用して、送受信される PING メッセージを関連付けることができます。

CONNECT_REQUEST メッセージ

CONNECT_REQUEST メッセージは、ターゲットクライアントへの接続を確立するために、リクエスト元クライアントから Relay サーバーに送信されます。リクエスト元クライアントが接続しようとしているターゲットプレイヤー (またはターゲットクライアント) は ToConnectionData によって表され、Relay サーバーはこれを解読してどのプレイヤーと接続するかを判断します。

警告: ターゲットクライアントとリクエスト元クライアントは、同じ Unity プロジェクト内、および同じ環境内に存在している必要があります。

ノート: Relay サーバーには、プレイヤーグループ (セッション とも呼ばれます) の正式な概念はありません。論理的なゲームセッション内のすべてのプレイヤーは、同じ Relay サーバーにバインドされます。これに基づく考え方として、Relay はゲームセッションに関連するプレイヤーのバインディングと接続の長さについて、一切の仮定を行いません。プレイヤーがセッションの終了時に Relay サーバーからバインドを解除するかどうかや、複数のセッションで同じバインディングを使用するかどうかは、ゲームクライアントによって判断されます。

バイト1 ..45 ..202122 ..
目的ヘッダー (タイプ 3)AllocationIDToConnectionData LengthToConnectionData

以下の表は、CONNECT_REQUEST メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
AllocationID[16]byteAllocationID は、接続をリクエストしている割り当て済みクライアントを識別するための 16 バイトの UUID です。
ToConnectionDataLengthuint8ToConnectionDataLengthToConnectionData のバイト長です。

許容される最大値は 255 です。

ToConnectionData[]byteToConnectionData は、接続先のクライアントを説明する暗号化されたデータブロブです。接続データ を参照してください。

このフィールドの長さは可変です。最大バイト長は 255 バイトです。

ACCEPTED メッセージ

Relay サーバーは、ターゲットクライアントへの接続が成功した後に、リクエスト元クライアントに ACCEPTED メッセージを送信します。

ノート: Relay サーバーがリクエスト元クライアントに ACCEPTED メッセージを返すのは、ターゲットクライアントが指定された最大接続数を超えていない場合です。

バイト1 ..45 ..2021 ..36
目的ヘッダー (タイプ 6)FromAllocationIDToAllocationID

以下の表は、ACCEPTED メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
FromAllocationID[16]byteFromAllocationID は、ターゲットクライアントを識別するための 16 バイトの UUID です。
ToAllocationID[16]byteToAllocationID は、接続をリクエストした割り当て済みクライアント (リクエスト元クライアント) を識別するための 16 バイトの UUID です。

DISCONNECT メッセージ

DISCONNECT メッセージは CONNECT_REQUEST ハンドシェイクの逆で、クライアントが他のクライアントから切断するためのメッセージです。クライアントは、DISCONNECT メッセージを Relay サーバーに送信することで、接続した他のクライアントから 切断 することができます。

Relay サーバーは、このメッセージを受信すると、指定された割り当て ID をリクエスト元クライアントの接続済みプレイヤーリストから削除します。また、Relay サーバーは DISCONNECT リクエストをホストクライアントに転送します。これにより、そのクライアントは接続済みプレイヤーのマップを更新して、リクエスト元クライアントの割り当て ID を削除できるようにします。

その後、Relay サーバーは確認として DISCONNECT メッセージをクライアントに返します。メッセージ本文内の割り当て ID のいずれかが無効である場合、Relay サーバーは代わりに ERROR message メッセージを送信します。

クライアントが切断されると、Relay サーバーはそのクライアントの割り当て ID 宛に送信されたすべての RELAY メッセージ を拒否するようになります。切断されたクライアントは、CONNECT_REQUEST message メッセージを使用して再度接続を確立できます。

ノート: DISCONNECT メッセージは、ホストクライアントと接続元クライアントの両方が送信できます。ただし、ホストクライアントが DISCONNECT メッセージを送信する場合、そのクライアントは参加済みプレイヤーを新しいホストに移行するか、すべてのプレイヤーを切断する必要があります。Relay はホスト移行を処理しません。

バイト1 ..45 ..2021 ..36
目的ヘッダー (タイプ 9)FromAllocationIDToAllocationID

以下の表は、DISCONNECT メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
FromAllocationID[16]byteFromAllocationID は、接続を閉じるようリクエストしている割り当て済みクライアント (リクエスト元クライアント) を識別するための 16 バイトの UUID です。
ToAllocationID[16]byteToAllocationID は、接続が閉じられようとしている割り当て済みクライアント (ターゲットクライアント) を識別するための 16 バイトの UUID です。

RELAY メッセージ

RELAY メッセージを使用すると、クライアントは互いの IP アドレスとポートを意識することなく、任意のバイトのペイロードを含んだメッセージを相互に送信することができます。

Relay サーバーは、クライアント間で RELAY メッセージが送信される前に、パケットの送信元クライアントが以前に BIND message を通じて FromAllocationID として認証されていることを確認します。クライアントが以前にバインドされていない場合、Relay サーバーは ErrClientPlayerMismatch ERROR メッセージ を返します。

Relay サーバーはまた、2 つのクライアントの間に、以前の CONNECT_REQUEST の交換を通じて確立された接続があることを確認します。クライアントが接続されていない場合、Relay サーバーは ErrNotConnectedERROR message を返します。

すべての検証が成功した場合、Relay サーバーはメッセージ全体を ToAllocationID にそのまま送信します。Relay サーバーは FromAllocationID には確認メッセージを送信しません。

バイト1 ..45 ..2021 ..3637 ..3839 ..
目的ヘッダー (タイプ 10)FromAllocationIDToAllocationIDLengthContent

ノート: RELAY メッセージの最大長は、プロトコルレベルでは保証されていません。これは Relay サーバー自体の設定によって定義されます。デフォルトでは、最大コンテンツ長が **1400 **バイトなので、RELAY メッセージの最大サイズは **1438 **バイトになります。

以下の表は、RELAY メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
FromAllocationID[16]byteFromAllocationID は、メッセージを送信している割り当て済みクライアント (リクエスト元クライアント) を識別するための 16 バイトの UUID です。
ToAllocationID[16]byteToAllocateID は、メッセージを受信する割り当て済みクライアント (ターゲットクライアント) を識別するための 16 バイトの UUID です。
Lengthuint16Length は、メッセージコンテンツの長さをバイト単位で指定するものです。

最大値は 1400 です。

Content[]byteContent には、メッセージのコンテンツが含められます。

CLOSE メッセージ

CLOSE メッセージは、クライアントが Relay サーバーからバインドを解除し、割り当てを解除するための冪等性のあるメッセージです。クライアントは、ゲームセッションを終了する際、またはゲームクライアントを閉じる際に、Relay サーバーCLOSE メッセージを送信する必要があります。クライアントは、Relay サーバーに対する自身のバインディングのみを閉じることができます。他のクライアントのバインディングを閉じることはできません。

クライアントは、成功確率を高めるために CLOSE メッセージを複数回送信する必要があります。CLOSE メッセージは冪等性があるため、クライアントがすでに 切断されている 場合でも、Relay サーバーから ERROR メッセージ が送信されるリスクはありません。

CLOSE メッセージは、割り当てを円滑に終了させるためのベストエフォートであり、成功を保証するものではありません。Relay サーバーはタイムアウトでクライアントを割り当て解除できるので、クライアントの割り当てを解除するために必ずしも CLOSE メッセージを必要としません。

CLOSE メッセージを送信するクライアントは、以前の BIND リクエスト を通じて Relay サーバーにバインドされている必要があります。クライアントが Relay サーバーにバインドされていない場合 (またはクライアントの IP アドレスが変更されている場合)、Relay サーバーはメッセージを暗黙的に拒否します。意図しない割り当てタイムアウトを防ぐために、PING メッセージを使用してください。

ノート: バインドされていないクライアントも、タイムアウトで期限切れになります。クライアントタイムアウト を参照してください。

バイト1 ..45 ..20
目的ヘッダー (タイプ 11)AllocationID

以下の表は、CLOSE メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
AllocationID[16]byteAllocationID は、クライアントの割り当てを識別するための 16 バイトの UUID です。

ERROR メッセージ

Relay サーバーは、クライアントにエラーが発生したことを通知するために、ERROR メッセージを厳格に使用します。

バイト1 ..45 ..2021
目的ヘッダー (タイプ 12)AllocationIDErrorCode

以下の表は、ERROR メッセージ内にある各フィールドについて説明したものです。

フィールドType説明
AllocationID[16]byteAllocationID は、クライアントの割り当てを識別するための 16 バイトの UUID です。
ErrorCodeuint8ErrorCode はエラーコードを表します。エラーコード を参照してください。

エラーコード

以下の表は、Relay サーバーがクライアントに送信できるエラーメッセージをそれぞれ説明したものです。

コード名前説明
0無効なプロトコルバージョン (ErrInvalidProtocolVersion)ErrInvalidProtocolVersion は、解析されたメッセージのプロトコルバージョンが予期しないものであった場合に返されます。
1非アクティブを理由にプレイヤーがタイムアウトした (ErrTimeout)ErrTimeout は、Relay サーバーに対するクライアントのバインディングがタイムアウトした場合に返されます。クライアントタイムアウト を参照してください。

クライアントは、このエラーを防ぐために PING メッセージ を使用する必要があります。

2認証されていない (ErrUnauthorized)ErrUnauthorized は、クライアントが許可されていない操作を試みた場合に返されます。
3割り当て ID とクライアントの不一致 (ErrClientPlayerMismatch)ErrClientPlayerMismatch は、クライアントが不明なネットワーク接続を使用してサーバーに RELAY メッセージを送信した場合に返されます。

これは、クライアントが使用している IP アドレスが Relay サーバーで認識済みのものから変更されたことをクライアントに知らせるためのものです。

このエラーメッセージは、クライアントが新しい BIND メッセージ で再バインドする必要があることを示しています。

4割り当て ID が見つからない (ErrAllocationNotFound)ErrAllocationNotFound は、Relay サーバーが指定された割り当て ID に対応する割り当てを見つけられない場合に返されます。
5接続されていない (ErrNotConnected)ErrNotConnected は、クライアントが自身に接続されていないクライアントと通信しようとした場合に返されます。
6自己接続は許可されていない (ErrSelfConnectNotAllowed)ErrSelfConnectNotAllowed は、クライアントが同じ割り当て ID を持つクライアントに CONNECT_REQUEST メッセージ を送信した場合に返されます。