Steamworksドキュメント
Steamデータグラムリレー
Steamデータグラムリレー(SDR)はValveの仮想プライベートゲーミングネットワークです。弊社のAPIを使用することで、Valveのゲームコンテンツ専用バックボーンにあなたのゲームトラフィックを伝送することができ、弊社のリレーネットワークにもアクセスできるようになります。トラフィックをリレーすると、IPアドレスが公開されないため、サーバーやプレイヤーをDoS攻撃から守ることができます。ゲームが受け取るトラフィックはすべて、認証され、暗号化され、レート制限がかけられます。さらに、弊社ネットワーク経由で、非常に多数のプレイヤーがより速いルートを見つけることができるようになり、プレイヤーのping時間が改善されます。

このリレーネットワークはピアツーピアのトラフィックと専用サーバーの両方に使用できます。

既存のネットワークコードを移植するための一般的要件とヒント

以下は、P2P接続と専用サーバー接続に共通する一般的な注意事項です。

まず、ネットワークホストがパブリックIPで識別されている場合(ほとんどのゲームサーバーに当てはまります)は、代わりに別の識別子を使用するように変更する必要があります。これにはいくつかのオプションがあります。
  • Steamにサインインするゲームサーバーとクライアントの場合、通常はSteamIDを使用します。
  • ゲームサーバーがSteamにサインインせず、チケットベースの認証フローを使用している場合、意味のある他の識別子を使用することができます。 SteamNetworkingIdentityを参照してください。
  • 一部のコードベースでは、ネットワークホストやゲームサーバーの識別にIPv4アドレスを使用することが前提となっており、この前提を変更するのは大変な作業です。弊社の『Team Fortress 2』のようなゲームと同様に、SteamworksのISteamMatchmakingとISteamMatchmakingServersのAPIには、実際にこのプロパティがあります。この場合、Steamworks「Fake IP」システムを使用できます。 FakeIPは、ほとんどの用途で有効なIPv4アドレスのように「扱われる」IPで、インターネット上で使用されていない予約済みのアドレス空間から取得されます。サーバーにFakeIPを割り当てることにより、サーバーはIPv4アドレスを使用してアドレス指定でき、ほぼすべてが「機能」します。 ISteamNetworkingSocketsおよびISteamMatchmakingServersシステムは、これらの特別なIPを認識し、適切なアクションを取ります。 FakeIPはルーティングできず、一般的なインターネット用途には使用できません(例:pingに応答しません)。詳細は、ISteamNetworkingSockets::BeginAsyncRequestFakeIPを参照してください。

次に、接続にSteamworksAPIの1つを使用するために、低レベルのソケットコードを修正する必要があります。
  • 理想としては、HSteamNetConnectionを返す接続指向APIのひとつであるISteamNetworkingSocketsインターフェイスを使用することです。
    (これらのAPIはプレーンなUDPトランスポートもサポートしており、テストする際にも非常に役立ちます。オープンソース版もあります。)
  • コードベースの中には、よりUDPに近い方法で書かれているものがあります。それらは、パケットをいつでも任意のリモートホストにアドホックに送信できますが、すべてのメッセージが確立された「接続」に送信されるわけではありません。これらの状況に役立つSteamworks機能が2つあります。
    • SteamIDのようなSteamNetworkingIdentityタイプを使用して識別されるホストとの通信には、ISteamNetworkingMessagesを使用します。
    • FakeIPを使用して識別されるホストとの通信には、ISteamNetworkingFakeUDPPortを使用します。

他のプラットフォームやストアでSDRを使用するための要件

クロスプラットフォームゲームに対して、単一プラットフォームでのみ機能するネットワーキングAPIや、DDoSソリューションは役に立ちません。ほとんどの場合、ゲームがいくつかの基本的な条件を満たしていれば、他のプラットフォームやストアにいるプレイヤーもリレーネットワークにアクセスすることができます。
  • Steamでゲームのバージョンを配信していること。
  • Valveがバグ修正またはセキュリティパッチを配信する必要がある場合、要請があった際には妥当な時間枠内(例えば、数か月以内)でのゲームのアップデートの配信に同意すること。
  • 残念ながら、このサービスを非Steamプレイヤーが常に利用できるという確約はできないことを理解すること。万が一、このサービスをダウングレードする必要が生じた場合は、計画を立てる時間の確保など、プレイヤーの混乱を避けるために可能な限りのことを行います。 SDKには、UDPによる直接接続にフォールバックするか、NATパンチを試行するようにクライアントに指示できるメカニズムが組み込まれていますが、このような事態が発生する可能性にも留意する必要があります。
  • 何らかのマッチメイキングサービス(SDRはこれを「ゲームコーディネーター」と呼びます)を使用して、認証資格情報を発行できるようにすること。このために別のSDKがあります。以下を参照してください。

関連SDKや細かい点については、弊社までお問い合わせください。コードをパートナーに配布する最善の方法の詳細については、現在も模索中です。すべてのパートナーおよびすべてのゲームに対してクロスプラットフォームサポートを提供することはできない場合もあることをご理解ください。

他のプラットフォームやストアでのSDRの実装に関する技術情報については、以下を参照してください。

上記の条件を満たしていない場合は、オープンソース版のAPIをご自由にお使いください。なお、オープンソースコードはリレーネットワークへのアクセスをサポートしていないことにご注意ください。

ピアツーピアゲーム

SteamでのピアツーピアトラフィックでSDRを活用したい場合に必要なことは、 ISteamNetworkingSockets::CreateListenSocketP2PやISteamNetworkingSockets::ConnectP2PのようなAPIを使用するだけです。それ以外はSteamが処理します。その他のプラットフォームやストアでの活用については、以下の技術的要件をご確認ください。

既知のデータセンター内の専用サーバー

ピアツーピアAPIは、1つのピアが専用サーバーの場合でも問題なく動作します。しかし、一つの難点があります。リレーを実行しているデータセンターの近くにゲームの専用サーバーがないと、最適なリレールートがデフォルトのIPルートよりも遅くなる場合があり、一部のプレイヤーにとって遅延が現状より悪化します。

最適な専用サーバーエクスペリエンスのために、SDRネットワークの一部である既知のデータセンターでサーバーを実行する必要があります。これは、リレーを確実に近くで実行し、リレーされたルートがデフォルトのIPルートよりも遅くなりすぎないようにするためです。既知のデータセンターで実行されるサーバーは特別なAPIを使用して接続します。このユースケースは、SDKでは「ホストされた専用サーバー(Hosted Dedicated Server)」と呼ばれます。これは必ずしもValveがサーバーまたはリレーをホストしているという意味ではなく、Valveが関係を確立した、Steamデータグラムリレーシステムにとって既知のサードパーティーのデータセンターでホストされている場合があります。

主要なホスティングプロバイダーでゲームサーバーを実行していて、SDRの利用に興味がある場合は、弊社までご連絡ください。ホスティング会社と協力して、データセンターでリレーを実行するように努めます。これは理想的な状況ですが、それが不可能な場合でも、データセンターを弊社のネットワーク構成システムに追加して、近くにあるValveのリレーを使用できる場合があります。

貴社が専用サーバーホスティング会社で、顧客がSDRを利用できるよう弊社のネットワークに参加したい場合は、弊社までご連絡ください!弊社では、まだサードパーティーのホスティング会社にリレーを導入していませんが、将来的な導入は視野に入れています。

ゲームコーディネーターなしの専用サーバーへのシンプルな接続フロー

プレイヤーをサーバーに割り当てる中央マッチメイキング/ログインサービス(これを「ゲームコーディネーター」と呼ぶことがあります)がない場合や、できるだけ処理をシンプルにしたい場合は、ISteamNetworkingSockets::CreateListenSocketP2PおよびISteamNetworkingSockets::ConnectP2Pを使用して、既知のデータセンターにある専用サーバーに接続することができます。この場合、通常のP2P接続と同様に、クライアント側で接続が開始されます。ランデブーメッセージはSteam経由で送信されるため、プレイヤーやサーバーがSteamとの接続を失うと、接続を確立できなくなります。また、Steamは、プレイヤーがSteamにサインインしていることと、ゲームを所有していることを確認する場合を除き、接続の試行を制限していません。

チケットベースのサーバー接続フロー

独自のゲームコーディネーターサービスがある場合は、チケットベースの接続フローを使用することを推奨しています。これは通常、単純なP2Pスタイルの接続フローと比較すると、少しだけ労力はかかるものの2つの重要な利点があります。
  • 接続を許可すべきプレイヤーにのみチケットを発行するため、不要な接続試行があなたのサーバーに到達することがありません。
  • 一度チケットを取得したプレイヤーは、Steamへの接続を失った場合やサーバーがSteamへの接続を失った場合、またはコンピューターがクラッシュして再起動した場合などでも、サーバーに接続することができます。こういった一般的な失敗に対してゲームサーバーへの再接続をより堅牢にすることは、ゲームから離れることでプレイヤーにペナルティを課すゲームにおいては非常に重要です。

SDRを介した専用サーバーへのチケットベース接続は、次のように機能します。
  • ゲームサーバーがゲームコーディネーターにログインすると、SteamDatagramHostedAddressという、物理的なルーティング情報を含む不透明なBLOBが送信されます。 ( ISteamNetworkingSockets::GetHostedDedicatedServerAddressを参照してください。)また、ゲームコーディネーターへの認証ログインを支援するツールも用意しています。
  • サーバーはISteamNetworkingSockets::CreateHostedDedicatedServerListenSocketを使用して、リレーされたトラフィックのリッスンを開始します。
  • ある時点で、クライアントはマッチメイキングへの参加や、サーバーへの接続を要求します。
  • クライアントはISteamNetworkingUtilsインターフェイスのメソッドを使用して、データセンターへのping時間を取得し、接続を確認できます。クライアントからゲームコーディネーターにこの情報を送信すると、プレイヤーをデータセンターに割り当てる際のゲームコーディネーターの判断に役立ちます。
  • ゲームコーディネーターは、クライアントによるサーバーへの接続を許可する準備ができると、SteamDatagramRelayAuthTicketを生成し、秘密鍵で署名します。このチケットは、特定のクライアントが特定のゲームサーバーと限られた時間内に通信することを許可します。これには、暗号化されたルーティング情報も含まれています。ゲームコーディネーターはチケットをクライアントに送信します。
  • クライアントはチケットをローカルキャッシュに保存します。(一見、手間に思えるキャッシュの利点を含め、詳細はISteamNetworkingSockets::ReceivedRelayAuthTicketを参照してください。)
  • クライアントはISteamNetworkingSockets::ConnectToHostedDedicatedServerを使用してサーバーに接続します。メッセージの送受信方法に関する詳細は、ISteamNetworkingSocketsを参照してください。

現時点では、チケットベースの認証をFakeIPシステムと組み合わせて使用することはできません。

ゲームコーディネーターSDK

「ゲームコーディネーター」は、ゲームのバックエンド/マッチメイキングサービスを指すために使用する用語です。ゲームコーディネーターとリンクできる別の小さなSDKがあり、次の用途に使用できます。
  • クライアントが、SDRの背後でホストされているゲームサーバーにアクセスするためのチケットを発行
  • PingLocation_t文字列を解析し、オブジェクト間のping時間を計算
  • 他のプラットフォームやストアのプレイヤーにID証明書を発行
  • その他の高度な機能の活用

SDKは、こちらから入手可能です。

ゲームコーディネーターSDKを使った認証

SDRは2つの認証メカニズムを使用します。

  • ホストされたサーバーチケットはゲームコーディネーターによって発行され、特定のクライアントが一定期間、特定の専用サーバーと通信することを許可します。リレーチケットは、専用サーバーのユースケースでのみ使用されます。 SteamDatagramRelayAuthTicketを参照してください。
  • 証明書は従来の方法による認証に使用され、DHキー交換を行い、暗号化されたチャンネルを確立します。証明書はエンドツーエンドの概念であり、UDPによる直接接続やP2Pを含む、あらゆる形式のSteamNetworkingSockets通信で使用できます。ゲームコーディネーターSDKのSteamDatagram_CreateCertおよびISteamNetworkingSockets::GetCertificateRequestを参照してください。

クライアントとサーバーの認証には、専用の公開キー基盤(PKI)を使用しています。プレイヤーには、特定のプレイヤーIDに関連付けられた個別の短期的な証明書が発行されます。これはSteamが処理します。ゲームサーバーには、通常、特定のAppIDのデータセンター全体を認証する長期的な証明書を使用します。それらの証明書はそちらで発行します。

チケットと証明書を発行する前には、キーペアを生成して公開キーをこちらに送信する必要があります。弊社はそのキーがアプリにとって信頼できるものであることを示すマスターCAキーで署名された証明書を発行します。次に、オフラインで、弊社の証明書ツールを使用して、サーバーを稼働させたいデータセンターごとに証明書を作成し、それに秘密鍵で署名します。その証明書を安全なチャネルを介してゲームサーバーに配布し、環境内のサーバーに渡します(以下参照)。

鍵はプレイヤーがゲームサーバーに接続するたびに、チケットを作成するためにも使用します。

CAの秘密鍵と証明書の秘密鍵は安全に保管してください!漏洩により鍵の取り消しや置換が必要になると、混乱が生じる可能性があります。

他のプラットフォームやストアでのSDRの実装


Steam以外の他のプラットフォームやストアのユーザーは、Steamにサインインしないため、SteamがSteamプレイヤーに提供するいくつかのサービスを、それらのユーザーにも提供する必要があります。

ゲームコーディネーターの初期化

  • マッチメイキングサービス(「ゲームコーディネーター」と呼びます)は、ゲームコーディネーターSDKとリンクする必要があります。詳細は、ヘッダーファイル、steamdatagram_gamecoordinator.hを参照してください。ゲームコーディネーターSDKは、プレーンなC APIを使用するため、他の言語との統合も比較的容易なはずです。
  • 初期化時にネットワーク設定をダウンロードし、1時間に1回程度更新をチェックします。 (SteamDatagram_GameCoordinator_GetNetworkConfigURLとSteamDatagram_GameCoordinator_SetNetworkConfigをご覧ください。)ネットワーク構成は、このドキュメントの執筆時点では、約26K(9Kに圧縮済み)の小さなJSONファイルです。このURLは非常に高い可用性を持ちますが、エラーの可能性に対処したい場合は、最近ダウンロードしたバージョンを使用することができます。
  • ゲーム用に認証されたキーペアが必要です。公開キーを弊社に送信し、秘密鍵でゲームコーディネーターSDKを初期化します。(詳細は、SteamDatagram_SetPrivateKey_Ed25519を参照してください。)

クライアントサインオン

  • クライアントは、ISteamNetworkingSockets::GetCertificateRequestを呼び出してBLOBを取得し、それをサインオンリクエストメッセージとともにゲームコーディネーターに送信します。
  • ゲームコーディネーターがサインオンリクエストを受け取ると、SteamDatagram_CreateCertを使用してクライアント用の証明書を生成します。
  • 生成された証明書を、ログオン応答としてクライアントに送り返します。クライアントは、ISteamNetworkingSockets::SetCertificateを使用して証明書をインストールする必要があります。
  • その際に、クライアントにもネットワーク構成を配布することを強く推奨します。クライアントは、SteamDatagram_SetNetworkConfigを使用してネットワーク構成を適用します。

証明書には有効期限がありますが、ここでは48時間の有効期限を使用することを推奨します。クライアントが48時間以上接続する可能性がある場合、定期的に証明書を更新する必要があります。新しい証明書はいつでも適用できるため、より頻繁(各マッチの開始時など)に証明書を発行しても問題ありません。

すべてのクライアントは、一意のIDを持つ必要があります。可能であれば、プラットフォームに固有のIDを使用してください。 (Steamクライアントでは、これは必須です。)ただし、これが不可能な場合は、マッチメイキングシステムにとって意味のある「汎用文字列」のIDを使用することができます。 SteamNetworkingIdentityを参照してください。

ピアツーピアゲーム

P2P接続には「シグナリング」サービスが必要です。これは、ルーティングのネゴシエーションに使用される不定期のランデブーメッセージを転送できる、低帯域幅で遅延の影響を受けないベストエフォート型の配信チャネルです。これには、クライアントにメッセージをプッシュできるように、クライアントとマッチメイキングサービスとの永続的な接続(例:WebSocketやTCP接続)が必要です。 httpを介する場合のように、クライアントが要求/応答のパターンを使用してゲームコーディネーターと通信するだけの場合には機能しません。必要なのは「ベストエフォート」の配信を提供することであり、つまり、これはライブラリがメッセージの欠落や重複配信を許容することを意味します。

  • 接続を開始するには、ISteamNetworkingSockets::ConnectP2PCustomSignalingを使用します。 ISteamNetworkingConnectionSignalingのサブクラスを実装する必要があります。SendSignalが呼び出されると、クライアントはバックエンドにメッセージを送信し、バックエンドはピアに対しメッセージを送信するために最善を尽くします。最初に接続を確立する際、通常は初めに4~10回、メッセージをやりとりします。その後、ルーティングの条件が変わった場合、確立された接続用に信号を送信するために呼び出されることがあります。
  • クライアントが信号を受け取ると、ISteamNetworkingSockets::ReceivedP2PCustomSignalを呼び出します。ライブラリはメッセージを復号化します。既存の接続に影響する場合、信号は内部で処理されます。信号が、新しい接続のためのものである場合、ISteamNetworkingSignalingRecvContext::OnConnectRequestが呼び出されます。

詳細は、steamnetworkingcustomsignaling.hを参照してください。

既知のデータセンターでのサーバーの実行

このセクションでは、既知のデータセンターで専用サーバーを実行する際の技術的な詳細を説明します。

環境変数

専用サーバーは環境変数からその構成を取得します。注:Valveのデータセンターでは、これらの値はすべて自動的に設定されます。
  • SDR_LISTEN_PORT:サーバーがリレーからトラフィックを受信するUDPポート。専用サーバーは単一のソケットのみを使用します。(ただし、「仮想ポート」を使用すれば、複数の論理的な「リッスンソケット」を持つことができます。 ISteamNetworkingSockets::CreateHostedDedicatedServerListenSocketを参照してください。)弊社のデータセンターでは、通常30xxxの範囲を使用しています。
  • SDR_IP:サーバーには「要請していない」トラフィックをリレーから受信できるパブリックIPが必要です。サーバーに、パブリックIPを持つインターフェイスが1つしかない場合、これが使用されます。それ以外の場合、使用するIPをゲームサーバーに指示する必要があります。 SDRソケットはINADDR_ANYにバインドされますが、この情報はサーバーのSteamDatagramHostedAddressへの入力に必要です。特に、この設定は企業のファイアウォールの背後にサーバーがある開発環境で必要になります。(以下を参照してください。)パブリックポートがSDR_LISTEN_PORTと異なる場合は、ポートを指定することもできます。
  • SDR_POPID:実稼働環境のデータセンターの3文字または4文字の英数字コード(SteamNetworkingPOPID)。開発環境では空白のままにします。
  • SDR_PRIVATE_KEY:あなたの証明書からの秘密鍵。 「-----BEGIN OPENSSH PRIVATE KEY-----」で始まるOpenSSH PEMブロックです。
  • SDR_CERT:署名された証明書。 「-----BEGIN STEAMDATAGRAM CERT-----」で始まるPEMのような専用フォーマットのブロックです。
  • SDR_NETWORK_CONFIG:アプリのSDRネットワーク構成ファイルの最新のローカルコピーへのフルパス。この変数が設定されていない場合、ネットワーク構成を取得するために、サーバーは起動時にHTTPを使用してコピーを取得します。最適なパフォーマンスを得るためには、定期的に(例:1時間に1度)最新の構成をダウンロードし、ローカルに保存してください。ネットワークの不調による影響を受けずに済みます。 Valveサーバーはこのように構成されています。

開発環境での実行

ISteamNetworkingSocketsはUDP接続をサポートしているため、通常はリレーを気にせずに、UDP経由でこのインターフェイスを通してコードを機能させることから始めるのがベストです。

サーバーコードでSDR_LISTEN_PORT環境変数の有無を利用して、サーバーがSDRをリッスンするかどうかを判断することを推奨します。 ISteamNetworkingSockets::GetHostedDedicatedServerPortを使用して値を取得できます。

開発環境では、SDR_POPIDは空白のままにします。 SDR_LISTEN_PORTおよびSDR_POPIDが空白の場合、POPIDは特別な3文字のコード「dev」に設定されます。

一般に、「dev」環境のサーバーでは認証は無効になっています。(クライアントおよびリレーはどちらも、署名されたチケットさえあれば、署名された証明書なしで「dev」サーバーへの接続を許可します。)ゲームコーディネーターとの認証には別のメカニズムが必要になります。また、ゲームコーディネーターは「dev」と称するサーバーにチケットを発行する際には注意が必要です!

サーバーは、要請していないパブリックトラフィックを受信できる必要があります。これは、パブリックIPがない場合、ファイアウォール内にポート転送を設定する必要があることを意味します。おそらく、SDR_IPを適切なパブリックIPで設定する必要があります(SDR_LISTEN_PORTと異なる場合はポートの設定も必要です)。