Relay メッセージプロトコル
プロジェクトで UTP または NGO を使用した Relay SDK を使用している場合は、Relay メッセージプロトコルが既にサポートされています。ただし、代替のエンジンやネットワーキングソリューションを使用したい場合は、まず Relay メッセージプロトコルを実装する必要があります。Relay メッセージプロトコルの仕様を使用して、Relay メッセージプロトコルを実装してください。
Relay メッセージプロトコルでは、フィールドの値がビッグエンディアンの順序で表現されることを前提としています。これは “ネットワークオーダー” とも呼ばれ、最も重要なバイトが最初に来ます。
メッセージは認証されません。ただし、HMAC 署名が使用される BIND
メッセージ は例外です。
プレイヤー が接続してメッセージをリレーできるは、同じ Unity プロジェクトの同じ環境から参加している他のプレイヤーのみとなります。Unity 環境間をまたいだ通信の試行は Relay によって拒否されます。
すべてのメッセージには、標準のヘッダーと、メッセージ固有の本文があります。標準ヘッダー と メッセージ本文 を参照してください。
メッセージの種類
コード | 名前 | 説明 |
0 |
| BIND メッセージは、クライアントから Relay サーバーに送信されるバインドリクエストを示します。 |
1 | BIND_RECEIVED メッセージ | BIND_RECEIVED メッセージは、BIND リクエスト の受信後に、Relay サーバーからクライアントへの応答が成功したことを示します。 |
2 | PING メッセージ | PING メッセージは、接続を維持するためにクライアントと Relay サーバー間で送信される PING メッセージ (双方向) を示します。 |
3 | CONNECT_REQUEST メッセージ | CONNECT_REQUEST メッセージは、プレイヤー (リクエスト元クライアント) から別のプレイヤー (ターゲットクライアント) への接続要求を示します。 |
4 | 予約済み。 | |
5 | 予約済み。 | |
6 | ACCEPTED メッセージ | ACCEPTED メッセージは、ターゲットクライアントへの接続が成功した後に Relay サーバーからリクエスト元クライアントに送信される確認メッセージを示します。 |
7 | 予約済み。 | |
8 | 予約済み。 | |
9 | DISCONNECT メッセージ | DISCONNECT メッセージは、接続された 2 人のプレイヤーを切断するリクエストを示します。 |
10 | RELAY メッセージ | RELAY メッセージは、2 人のプレイヤー (クライアント) 間でメッセージを送信するリクエストを示します。 |
11 | CLOSE メッセージ | CLOSE メッセージは、Relay サーバーからのバインド解除を求めるクライアントからのリクエストを示します。 |
12 | ERROR メッセージ | ERROR メッセージは発生したエラーを示します。 |
承諾モードの種類
承諾モードは、クライアント からの接続リクエストを Relay サーバー がどのように処理するかを定義するものです。
Relay では、AUTO
承諾モードのみがサポートされています。AUTO
モードの接続は、Relay サーバーのキャパシティを超えていなければ (接続数が許容される最大接続数を超えていなければ)、自動的に承諾されます。
コード | 名前 | 説明 |
0 | AcceptModeAuto | AcceptModeAuto は、クライアントへの接続が Relay サーバーによって自動的に承諾されることを示します。 |
1 | 予約済み。 |
標準ヘッダー
すべてのメッセージタイプには共有の標準ヘッダーがあり、そのヘッダーには署名、Relay メッセージプロトコルのバージョン、およびパケットの本体に含まれるメッセージが含まれています。
バイト | 1 ..2 | 3 | 4 |
目的 | Signature | Version | Type |
以下の表は、標準ヘッダー内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
Signature | []byte | Signature は常に 0xDA72 です。 |
Version | uint8 | Version は Relay メッセージプロトコルのバージョンです。初期リリースの場合、この値は 0 になります。 |
Type | uint8 | Type は、本体に含まれるメッセージの種類を表す整数です。メッセージの種類 を参照してください。 |
メッセージ本文
BIND メッセージ
BIND
メッセージは、特定の割り当てに対応するクライアントの IP アドレスとポートのマッピングを作成するために、クライアントから Relay サーバーに送信されます。このメッセージは、クライアントの ID を確認するために認証されます。
割り当てサービス から受信した応答には、クライアントが BIND
メッセージを認証するために必要な情報が含まれています。BIND
メッセージに対する割り当てサービスからの応答は、バインディングの状態を示します。
クライアントは、クライアントの IP アドレスとポートが変更されていない限り、同じ BIND
メッセージを送信できます。例えば、クライアントが IP アドレスまたはポートを変更した後の次の接続で BIND
メッセージを送信する場合、Nonce
値は以前に指定された値よりも大きくなければなりません。
バイト | 1 ..4 | 5 | 6 ..7 | 8 | 9 ..N | N+1 ..33 |
目的 | ヘッダー (タイプ 0) | AcceptMode | Nonce | ConnectionDataLength | ConnectionData | HMAC |
以下の表は、BIND
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
AcceptMode | uint8 | AcceptMode は、この割り当ての所有者への接続を試みるクライアントからのリクエストを、Relay サーバーがどのように処理すべきかを定義するものです。現在、 承諾モードの種類 を参照してください。 |
Nonce | uint16 | Nonce は一度だけ使用される暗号学的なノンスです。後続の BIND メッセージごとに、nonce の値を増加させる必要があります。nonce の値は 0 から開始するのが一般的です。 |
ConnectionDataLength | uint8 | ConnectionDataLength は ConnectionData のバイト長を示します。許容される最大値は 255 です。 |
ConnectionData | []byte | ConnectionData は、接続中のクライアント の暗号化された 接続データ です。このフィールドの長さは可変です。最大長は 255 バイトです。 |
HMAC | [32]byte | HMAC は、既知のキーとメッセージ内の前のバイト (ヘッダーを含む) を使用して生成される、ハッシュベースのメッセージ認証コードです。認証 を参照してください。 |
セキュリティ
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 サーバーから ErrClientPlayerMismatch
ERROR
メッセージ が返されます。
- クライアントが
BIND
メッセージを介して Relay サーバーにバインドする前にPING
メッセージを送信した。 - クライアントが IP アドレスを変更した後、新しい IP アドレスで Relay サーバーに再バインドする前に
PING
メッセージを送信した。
バイト | 1 ..4 | 5 ..20 | 21 ..22 |
目的 | ヘッダー (タイプ 2) | AllocationID | Number |
以下の表は、PING
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
AllocationID | [16]byte | AllocationID は、PING を送信している割り当て済みクライアントを識別する 16 バイトの UUID です。 |
Number | uint16 | Number は、Relay サーバーがクライアントにエコーバックする任意の符号なし整数です。クライアントはこれを使用して、送受信される PING メッセージを関連付けることができます。 |
CONNECT_REQUEST メッセージ
CONNECT_REQUEST
メッセージは、ターゲットクライアントへの接続を確立するために、リクエスト元クライアントから Relay サーバーに送信されます。リクエスト元クライアントが接続しようとしているターゲットプレイヤー (またはターゲットクライアント) は ToConnectionData
によって表され、Relay サーバーはこれを解読してどのプレイヤーと接続するかを判断します。
警告: ターゲットクライアントとリクエスト元クライアントは、同じ Unity プロジェクト内、および同じ環境内に存在している必要があります。
ノート: Relay サーバーには、プレイヤーグループ (セッション とも呼ばれます) の正式な概念はありません。論理的なゲームセッション内のすべてのプレイヤーは、同じ Relay サーバーにバインドされます。これに基づく考え方として、Relay はゲームセッションに関連するプレイヤーのバインディングと接続の長さについて、一切の仮定を行いません。プレイヤーがセッションの終了時に Relay サーバーからバインドを解除するかどうかや、複数のセッションで同じバインディングを使用するかどうかは、ゲームクライアントによって判断されます。
バイト | 1 ..4 | 5 ..20 | 21 | 22 .. |
目的 | ヘッダー (タイプ 3) | AllocationID | ToConnectionData Length | ToConnectionData |
以下の表は、CONNECT_REQUEST
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
AllocationID | [16]byte | AllocationID は、接続をリクエストしている割り当て済みクライアントを識別するための 16 バイトの UUID です。 |
ToConnectionDataLength | uint8 | ToConnectionDataLength は ToConnectionData のバイト長です。許容される最大値は 255 です。 |
ToConnectionData | []byte | ToConnectionData は、接続先のクライアントを説明する暗号化されたデータブロブです。接続データ を参照してください。このフィールドの長さは可変です。最大バイト長は 255 バイトです。 |
ACCEPTED メッセージ
Relay サーバーは、ターゲットクライアントへの接続が成功した後に、リクエスト元クライアントに ACCEPTED
メッセージを送信します。
ノート: Relay サーバーがリクエスト元クライアントに ACCEPTED
メッセージを返すのは、ターゲットクライアントが指定された最大接続数を超えていない場合です。
バイト | 1 ..4 | 5 ..20 | 21 ..36 |
目的 | ヘッダー (タイプ 6) | FromAllocationID | ToAllocationID |
以下の表は、ACCEPTED
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
FromAllocationID | [16]byte | FromAllocationID は、ターゲットクライアントを識別するための 16 バイトの UUID です。 |
ToAllocationID | [16]byte | ToAllocationID は、接続をリクエストした割り当て済みクライアント (リクエスト元クライアント) を識別するための 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 ..4 | 5 ..20 | 21 ..36 |
目的 | ヘッダー (タイプ 9) | FromAllocationID | ToAllocationID |
以下の表は、DISCONNECT
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
FromAllocationID | [16]byte | FromAllocationID は、接続を閉じるようリクエストしている割り当て済みクライアント (リクエスト元クライアント) を識別するための 16 バイトの UUID です。 |
ToAllocationID | [16]byte | ToAllocationID は、接続が閉じられようとしている割り当て済みクライアント (ターゲットクライアント) を識別するための 16 バイトの UUID です。 |
RELAY メッセージ
RELAY
メッセージを使用すると、クライアントは互いの IP アドレスとポートを意識することなく、任意のバイトのペイロードを含んだメッセージを相互に送信することができます。
Relay サーバーは、クライアント間で RELAY
メッセージが送信される前に、パケットの送信元クライアントが以前に BIND message
を通じて FromAllocationID
として認証されていることを確認します。クライアントが以前にバインドされていない場合、Relay サーバーは ErrClientPlayerMismatch
ERROR
メッセージ を返します。
Relay サーバーはまた、2 つのクライアントの間に、以前の CONNECT_REQUEST
の交換を通じて確立された接続があることを確認します。クライアントが接続されていない場合、Relay サーバーは ErrNotConnected
ERROR message
を返します。
すべての検証が成功した場合、Relay サーバーはメッセージ全体を ToAllocationID
にそのまま送信します。Relay サーバーは FromAllocationID
には確認メッセージを送信しません。
バイト | 1 ..4 | 5 ..20 | 21 ..36 | 37 ..38 | 39 .. |
目的 | ヘッダー (タイプ 10) | FromAllocationID | ToAllocationID | Length | Content |
ノート: RELAY
メッセージの最大長は、プロトコルレベルでは保証されていません。これは Relay サーバー自体の設定によって定義されます。デフォルトでは、最大コンテンツ長が **1400 **バイトなので、RELAY
メッセージの最大サイズは **1438 **バイトになります。
以下の表は、RELAY
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
FromAllocationID | [16]byte | FromAllocationID は、メッセージを送信している割り当て済みクライアント (リクエスト元クライアント) を識別するための 16 バイトの UUID です。 |
ToAllocationID | [16]byte | ToAllocateID は、メッセージを受信する割り当て済みクライアント (ターゲットクライアント) を識別するための 16 バイトの UUID です。 |
Length | uint16 | Length は、メッセージコンテンツの長さをバイト単位で指定するものです。最大値は 1400 です。 |
Content | []byte | Content には、メッセージのコンテンツが含められます。 |
CLOSE メッセージ
CLOSE
メッセージは、クライアントが Relay サーバーからバインドを解除し、割り当てを解除するための冪等性のあるメッセージです。クライアントは、ゲームセッションを終了する際、またはゲームクライアントを閉じる際に、Relay サーバー に CLOSE
メッセージを送信する必要があります。クライアントは、Relay サーバーに対する自身のバインディングのみを閉じることができます。他のクライアントのバインディングを閉じることはできません。
クライアントは、成功確率を高めるために CLOSE
メッセージを複数回送信する必要があります。CLOSE
メッセージは冪等性があるため、クライアントがすでに 切断されている 場合でも、Relay サーバーから ERROR
メッセージ が送信されるリスクはありません。
CLOSE
メッセージは、割り当てを円滑に終了させるためのベストエフォートであり、成功を保証するものではありません。Relay サーバーはタイムアウトでクライアントを割り当て解除できるので、クライアントの割り当てを解除するために必ずしも CLOSE
メッセージを必要としません。
CLOSE
メッセージを送信するクライアントは、以前の BIND
リクエスト を通じて Relay サーバーにバインドされている必要があります。クライアントが Relay サーバーにバインドされていない場合 (またはクライアントの IP アドレスが変更されている場合)、Relay サーバーはメッセージを暗黙的に拒否します。意図しない割り当てタイムアウトを防ぐために、PING
メッセージを使用してください。
ノート: バインドされていないクライアントも、タイムアウトで期限切れになります。クライアントタイムアウト を参照してください。
バイト | 1 ..4 | 5 ..20 |
目的 | ヘッダー (タイプ 11) | AllocationID |
以下の表は、CLOSE
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
AllocationID | [16]byte | AllocationID は、クライアントの割り当てを識別するための 16 バイトの UUID です。 |
ERROR メッセージ
Relay サーバーは、クライアントにエラーが発生したことを通知するために、ERROR
メッセージを厳格に使用します。
バイト | 1 ..4 | 5 ..20 | 21 |
目的 | ヘッダー (タイプ 12) | AllocationID | ErrorCode |
以下の表は、ERROR
メッセージ内にある各フィールドについて説明したものです。
フィールド | Type | 説明 |
AllocationID | [16]byte | AllocationID は、クライアントの割り当てを識別するための 16 バイトの UUID です。 |
ErrorCode | uint8 | ErrorCode はエラーコードを表します。エラーコード を参照してください。 |
エラーコード
以下の表は、Relay サーバーがクライアントに送信できるエラーメッセージをそれぞれ説明したものです。
コード | 名前 | 説明 |
0 | 無効なプロトコルバージョン (ErrInvalidProtocolVersion ) | ErrInvalidProtocolVersion は、解析されたメッセージのプロトコルバージョンが予期しないものであった場合に返されます。 |
1 | 非アクティブを理由にプレイヤーがタイムアウトした (ErrTimeout ) | ErrTimeout は、Relay サーバーに対するクライアントのバインディングがタイムアウトした場合に返されます。クライアントタイムアウト を参照してください。クライアントは、このエラーを防ぐために |
2 | 認証されていない (ErrUnauthorized ) | ErrUnauthorized は、クライアントが許可されていない操作を試みた場合に返されます。 |
3 | 割り当て ID とクライアントの不一致 (ErrClientPlayerMismatch ) | ErrClientPlayerMismatch は、クライアントが不明なネットワーク接続を使用してサーバーに RELAY メッセージを送信した場合に返されます。これは、クライアントが使用している IP アドレスが Relay サーバーで認識済みのものから変更されたことをクライアントに知らせるためのものです。 このエラーメッセージは、クライアントが新しい |
4 | 割り当て ID が見つからない (ErrAllocationNotFound ) | ErrAllocationNotFound は、Relay サーバーが指定された割り当て ID に対応する割り当てを見つけられない場合に返されます。 |
5 | 接続されていない (ErrNotConnected ) | ErrNotConnected は、クライアントが自身に接続されていないクライアントと通信しようとした場合に返されます。 |
6 | 自己接続は許可されていない (ErrSelfConnectNotAllowed ) | ErrSelfConnectNotAllowed は、クライアントが同じ割り当て ID を持つクライアントに CONNECT_REQUEST メッセージ を送信した場合に返されます。 |