A P2P connection proxy for Supreme Commander: Forged Alliance using ICE.
The faf-ice-adapter
is controlled using a bi-directional JSON-RPC interface over TCP.
Name | Parameters | Returns | Description |
---|---|---|---|
quit | Gracefully shuts down the faf-ice-adapter . |
||
hostGame | mapName (string) | Tell the game to create the lobby and host game on Lobby-State. | |
joinGame | remotePlayerLogin (string), remotePlayerId (int) | Tell the game to create the Lobby, create a PeerRelay in answer mode and join the remote game. | |
connectToPeer | remotePlayerLogin (string), remotePlayerId (int), offer (bool) | Create a PeerRelay and tell the game to connect to the remote peer with offer/answer mode. | |
disconnectFromPeer | remotePlayerId (int) | Destroy PeerRelay and tell the game to disconnect from the remote peer. | |
setLobbyInitMode | lobbyInitMode (string): "normal" or "auto" | Set the lobby mode the game will use. Supported values are "normal" for normal lobby and "auto" for automatch lobby (aka ladder). | |
iceMsg | remotePlayerId (int), msg (object) | Add the remote ICE message to the PeerRelay to establish a connection. | |
sendToGpgNet | header (string), chunks (array) | Send an arbitrary message to the game. | |
setIceServers | iceServers (array) | ICE server array for use in webrtc. Must be called before joinGame/connectToPeer. See https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer | |
status | status structure | Polls the current status of the faf-ice-adapter . |
Name | Parameters | Description |
---|---|---|
onConnectionStateChanged | "Connected"/"Disconnected" (string) | The game connected to the internal GPGNetServer. |
onGpgNetMessageReceived | header (string), chunks (array) | The game sent a message to the faf-ice-adapter via the internal GPGNetServer. |
onIceMsg | localPlayerId (int), remotePlayerId (int), msg (object) | The PeerRelays gathered a local ICE message for connecting to the remote player. This message must be forwarded to the remote peer and set using the iceMsg command. |
onIceConnectionStateChanged | localPlayerId (int), remotePlayerId (int), state (string) | See https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState |
onConnected | localPlayerId (int), remotePlayerId (int), connected (bool) | Informs the client that ICE connectivity to the peer is established or unestablished. |
{
"version" : /* string: faf-ice-adapter version */
"ice_servers_size" : /* the number of ICE servers set using `setIceServers` */
"lobby_port" : /* the actual game lobby UDP port. Should match --lobby-port option if non-zero port is specified. */
"init_mode" : /* the current init mode. See setLobbyInitMode */
"options" : /* The specified commandline options */
"gpgnet" : { /* The GPGNet state */
"local_port" : /* int: The port the game should connect to via /gpgnet 127.0.0.1:port */
"connected" : /* boolean: Is the game connected? */
"game_state" : /* string: The last received "GameState" */
"task_string" : /* string: A string describing the task/role of the game (joining/hosting)*/
}
"relays" : [/* An array of relay information*/
{
"remote_player_id" : /* int: The ID of the remote player */
"remote_player_login" : /* string: The name of the remote player */
"local_game_udp_port" : /* int: The UDP port opened for the game to connect to */
"ice_agent": {/* Information about the IceAgent for this peer */
"state": /* string: The connection state https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceConnectionState */
"connected": /* bool: Is the data channel open for sending/receiving game packets ? */
"loc_cand_addr": /* string: The local address used for the connection */
"rem_cand_addr": /* string: The remote address used for the connection */
"loc_cand_type": /* string: The type of the local candidate 'local'/'stun'/'relay' */
"rem_cand_type": /* string: The type of the remote candidate 'local'/'stun'/'relay' */
"time_to_connected": /* double: The time it took to connect to the peer in seconds */
}
},
...
]
}
The first two commandline arguments --id
and --login
must be specified like this: faf-ice-adapter -i 3 -l "Rhiza"
The full commandline help text is:
faf-ice-adapter usage:
--help produce help message
--id arg set the ID of the local player
--login arg set the login of the local player, e.g. "Rhiza"
--rpc-port arg (=7236) set the port of internal JSON-RPC server
--gpgnet-port arg (=0) set the port of internal GPGNet server
--lobby-port arg (=0) set the port the game lobby should use for incoming UDP packets from the PeerRelay
--log-directory arg set a log directory to write ice_adapter_0 log files
Step | Player 1 "Alice" | Player 2 "Bob" |
---|---|---|
1 | Start the client | |
2 | The client starts faf-ice-adapter and connects to the JSONRPC server |
|
3 | The client starts the game and makes it connect to the GPGNet server of the faf-ice-adapter using /gpgnet 127.0.0.1:7237 commandline argument for ForgedAlliance.exe |
|
3.1 | The game sends GameState Idle |
|
3.2 | The client sends CreateLobby ... |
|
3.3 | The game sends GameState Lobby |
|
4 | The client sends hostGame('monument_valley.v0001') |
|
5 | The game should now wait in the lobby and the client receives a lot of onGpgNetMessageReceived notifications from faf-ice-adapter |
|
6 | Now Bob want to join Alices game, starts the client, the client starts faf-ice-adapter and the game like Alice did. |
|
6.1 | The game sends GameState Idle |
|
6.2 | The client sends CreateLobby ... |
|
6.3 | The game sends GameState Lobby |
|
7 | The client sends connectToPeer('Bob', 2, true) |
The client sends joinGame('Alice', 1) |
8 | The game should connect to the internal PeerRelay, and shows that it's connecting to the peer. | The game should connect to the internal PeerRelay, and shows that it's connecting to the peer. |
9 | The client receives multiple onIceMsg(1, 2, someIceMsg) notifications and must now transfer these messages string ordered to the peer. |
The client receives multiple onIceMsg(1, 2, someIceMsg) notifications and must now transfer these messages string ordered to the peer. |
10 | The client must set the transferred ICE messages for the peer using iceMsg(2, someIceMsg) . |
The client must set the transferred ICE messages for the peer using iceMsg(1, someIceMsg) . |
11 | The client received multiple iceConnectionStateChanged(...) notifications which would finally show the 'Connected' or 'Complete' state, which should also let the game connect to the peer. Another indicator for a connection is the onDatachannelOpen notification. |
The client received multiple iceConnectionStateChanged(...) notifications which would finally show the 'Connected' or 'Complete' state, which should also let the game connect to the peer. |
Webrtc is build using clang and linked against clangs libc++, so you need to use these for building the ice-adapter.
- Build libwebrtc with
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DWEBRTC_BRANCH_HEAD=refs/branch-heads/60 -DBUILD_TESTS=ON
- Build the ice-adapter with
cmake -DWEBRTC_INCLUDE_DIRS="path/to/webrtc/include" -DWEBRTC_LIBRARIES="path/to/webrtc/lib/libwebrtc.a" -DCMAKE_BUILD_TYPE=Release
- Download and extract latest libwebrtc win32 release zip file.
- Install Visual Studio 2015 compilers and open x86 shell.
- Build the ice-adapter using
cmake -DWEBRTC_INCLUDE_DIRS="path/to/webrtc/include" -DWEBRTC_LIBRARIES="path/to/webrtc/lib/libwebrtc.lib" -DCMAKE_BUILD_TYPE=Release