浏览代码

Merge from DTLS branch

/main/staging
nathaniel.buck@unity3d.com 3 年前
当前提交
9ec8e971
共有 7 个文件被更改,包括 167 次插入24 次删除
  1. 34
      Assets/Scripts/Relay/RelayUtpClient.cs
  2. 41
      Assets/Scripts/Relay/RelayUtpSetup.cs
  3. 3
      Assets/Scripts/Tests/PlayMode/Tests.Play.asmdef
  4. 2
      Packages/manifest.json
  5. 2
      Packages/packages-lock.json
  6. 98
      Assets/Scripts/Tests/PlayMode/UtpTests.cs
  7. 11
      Assets/Scripts/Tests/PlayMode/UtpTests.cs.meta

34
Assets/Scripts/Relay/RelayUtpClient.cs


{
if (cmd == NetworkEvent.Type.Data)
{
MsgType msgType = (MsgType)strm.ReadByte();
string id = ReadLengthAndString(ref strm);
if (id == m_localUser.ID || !m_localLobby.LobbyUsers.ContainsKey(id)) // We don't hold onto messages, since an incoming user will be fully initialized before they send events.
List<byte> msgContents = new List<byte>(ReadMessageContents(ref strm));
if (msgContents.Count < 3) // We require at a minimum - Message type, the length of the user ID, and the user ID.
return;
MsgType msgType = (MsgType)msgContents[0];
int idLength = msgContents[1];
if (msgContents.Count < idLength + 2)
{ UnityEngine.Debug.LogWarning($"Relay client processed message of length {idLength}, but contents were of length {msgContents.Count}.");
return;
}
string id = System.Text.Encoding.UTF8.GetString(msgContents.GetRange(2, idLength).ToArray());
if (id == m_localUser.ID || !m_localLobby.LobbyUsers.ContainsKey(id)) // We don't need to hold onto messages if the ID is absent; users are initialized before they send events.
msgContents.RemoveRange(0, 2 + idLength);
string name = ReadLengthAndString(ref strm);
int nameLength = msgContents[0];
string name = System.Text.Encoding.UTF8.GetString(msgContents.GetRange(1, nameLength).ToArray());
EmoteType emote = (EmoteType)strm.ReadByte();
EmoteType emote = (EmoteType)msgContents[0];
UserStatus status = (UserStatus)strm.ReadByte();
UserStatus status = (UserStatus)msgContents[0];
m_localLobby.LobbyUsers[id].UserStatus = status;
}
else if (msgType == MsgType.StartCountdown)

/// <summary>
/// Relay uses raw pointers for efficiency. This converts them to byte arrays, assuming the stream contents are 1 byte for array length followed by contents.
/// </summary>
unsafe private string ReadLengthAndString(ref DataStreamReader strm)
unsafe private byte[] ReadMessageContents(ref DataStreamReader strm)
byte length = strm.ReadByte();
int length = strm.Length;
return System.Text.Encoding.UTF8.GetString(bytes);
return bytes;
}
/// <summary>

message.Add((byte)strBytes.Length);
message.AddRange(strBytes);
if (driver.BeginSend(connection, out var dataStream) == 0) // Oh, should check this first?
if (driver.BeginSend(connection, out var dataStream) == 0)
{
byte[] bytes = message.ToArray();
unsafe

message.AddRange(idBytes);
message.Add(value);
if (driver.BeginSend(connection, out var dataStream) == 0) // Oh, should check this first?
if (driver.BeginSend(connection, out var dataStream) == 0)
{
byte[] bytes = message.ToArray();
unsafe

41
Assets/Scripts/Relay/RelayUtpSetup.cs


}
protected abstract void JoinRelay();
/// <summary>
/// Determine the server endpoint for connecting to the Relay server, for either an Allocation or a JoinAllocation.
/// If DTLS encryption is available, and there's a secure server endpoint available, use that as a secure connection. Otherwise, just connect to the Relay IP unsecured.
/// </summary>
protected NetworkEndPoint GetEndpointForAllocation(List<RelayServerEndpoint> endpoints, string ip, int port, out bool isSecure)
{
#if ENABLE_MANAGED_UNITYTLS
foreach (RelayServerEndpoint endpoint in endpoints)
{
if (endpoint.Secure && endpoint.Network == RelayServerEndpoint.NetworkOptions.Udp)
{
isSecure = true;
return NetworkEndPoint.Parse(endpoint.Host, (ushort)endpoint.Port);
}
}
#endif
isSecure = false;
return NetworkEndPoint.Parse(ip, (ushort)port);
}
protected void BindToAllocation(string ip, int port, byte[] allocationIdBytes, byte[] connectionDataBytes, byte[] hostConnectionDataBytes, byte[] hmacKeyBytes, int connectionCapacity)
protected void BindToAllocation(NetworkEndPoint serverEndpoint, byte[] allocationIdBytes, byte[] connectionDataBytes, byte[] hostConnectionDataBytes, byte[] hmacKeyBytes, int connectionCapacity, bool isSecure)
NetworkEndPoint serverEndpoint = NetworkEndPoint.Parse(ip, (ushort)port);
m_endpointForServer = serverEndpoint;
//TODO Implement DTLS
bool isSecure = false;
relayServerData.ComputeNewNonce();
relayServerData.ComputeNewNonce(); // For security, the nonce value sent when authenticating the allocation must be increased.
var relayNetworkParameter = new RelayNetworkParameter { ServerData = relayServerData };
m_networkDriver = NetworkDriver.Create(new INetworkParameter[] { relayNetworkParameter });

{
m_allocation = allocation;
RelayAPIInterface.GetJoinCodeAsync(allocation.AllocationId, OnRelayCode);
BindToAllocation(allocation.RelayServer.IpV4, allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.ConnectionData, allocation.Key, 16);
bool isSecure = false;
m_endpointForServer = GetEndpointForAllocation(allocation.ServerEndpoints, allocation.RelayServer.IpV4, allocation.RelayServer.Port, out isSecure);
BindToAllocation(m_endpointForServer, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.ConnectionData, allocation.Key, 16, isSecure);
m_localLobby.RelayServer = new ServerAddress(m_allocation.RelayServer.IpV4, m_allocation.RelayServer.Port);
m_localLobby.RelayServer = new ServerAddress(m_endpointForServer.Address.Split(':')[0], m_endpointForServer.Port);
m_joinState |= JoinState.Joined;
CheckForComplete();
}

if (joinAllocation == null)
return;
m_allocation = joinAllocation;
BindToAllocation(joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port, joinAllocation.AllocationIdBytes, joinAllocation.ConnectionData, joinAllocation.HostConnectionData, joinAllocation.Key, 1);
m_localLobby.RelayServer = new ServerAddress(joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port);
bool isSecure = false;
m_endpointForServer = GetEndpointForAllocation(joinAllocation.ServerEndpoints, joinAllocation.RelayServer.IpV4, joinAllocation.RelayServer.Port, out isSecure);
BindToAllocation(m_endpointForServer, joinAllocation.AllocationIdBytes, joinAllocation.ConnectionData, joinAllocation.HostConnectionData, joinAllocation.Key, 1, isSecure);
m_localLobby.RelayServer = new ServerAddress(m_endpointForServer.Address.Split(':')[0], m_endpointForServer.Port);
}
protected override void OnBindingComplete()

3
Assets/Scripts/Tests/PlayMode/Tests.Play.asmdef


"UnityEditor.TestRunner",
"LobbyRelaySample",
"Unity.Services.Lobbies",
"Unity.Services.Relay"
"Unity.Services.Relay",
"Unity.Networking.Transport"
],
"includePlatforms": [],
"excludePlatforms": [],

2
Packages/manifest.json


"com.unity.test-framework": "1.1.27",
"com.unity.textmeshpro": "3.0.6",
"com.unity.toolchain.win-x86_64-linux-x86_64": "0.1.20-preview",
"com.unity.transport": "1.0.0-pre.3",
"com.unity.transport": "1.0.0-pre.5",
"com.unity.ugui": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",

2
Packages/packages-lock.json


"url": "https://packages.unity.com"
},
"com.unity.transport": {
"version": "1.0.0-pre.3",
"version": "1.0.0-pre.5",
"depth": 0,
"source": "registry",
"dependencies": {

98
Assets/Scripts/Tests/PlayMode/UtpTests.cs


using System;
using System.Collections;
using LobbyRelaySample.relay;
using NUnit.Framework;
using Unity.Networking.Transport;
using Unity.Services.Relay.Models;
using UnityEngine;
using UnityEngine.TestTools;
namespace Test
{
public class UtpTests
{
private class RelayUtpTest : RelayUtpSetupHost
{
public Action<NetworkEndPoint, bool> OnGetEndpoint { private get; set; }
public void JoinRelayPublic()
{
JoinRelay();
}
protected override void JoinRelay()
{
RelayAPIInterface.AllocateAsync(1, OnAllocation);
void OnAllocation(Allocation allocation)
{
bool isSecure = false;
NetworkEndPoint endpoint = GetEndpointForAllocation(allocation.ServerEndpoints, allocation.RelayServer.IpV4, allocation.RelayServer.Port, out isSecure);
OnGetEndpoint?.Invoke(endpoint, isSecure);
// The allocation will be cleaned up automatically, since we won't be pinging it regularly.
}
}
}
private LobbyRelaySample.Auth.SubIdentity_Authentication m_auth;
private bool m_didSigninComplete = false;
GameObject m_dummy;
[OneTimeSetUp]
public void Setup()
{
m_dummy = new GameObject();
m_auth = new LobbyRelaySample.Auth.SubIdentity_Authentication(() => { m_didSigninComplete = true; });
}
[OneTimeTearDown]
public void Teardown()
{
m_auth?.Dispose();
GameObject.Destroy(m_dummy);
}
[UnityTest]
public IEnumerator DTLSCheck()
{
#if ENABLE_MANAGED_UNITYTLS
if (!m_didSigninComplete)
yield return new WaitForSeconds(3);
if (!m_didSigninComplete)
Assert.Fail("Did not sign in.");
yield return new WaitForSeconds(1); // To prevent a possible 429 after a previous test.
RelayUtpTest relaySetup = m_dummy.AddComponent<RelayUtpTest>();
relaySetup.OnGetEndpoint = OnGetEndpoint;
bool? isSecure = null;
NetworkEndPoint endpoint = default;
relaySetup.JoinRelayPublic();
float timeout = 5;
while (!isSecure.HasValue && timeout > 0)
{
timeout -= 0.25f;
yield return new WaitForSeconds(0.25f);
}
Component.Destroy(relaySetup);
Assert.IsTrue(timeout > 0, "Timeout check.");
Assert.IsTrue(isSecure, "Should have a secure server endpoint.");
Assert.IsTrue(endpoint.IsValid, "Endpoint should be valid.");
void OnGetEndpoint(NetworkEndPoint resultEndpoint, bool resultIsSecure)
{
endpoint = resultEndpoint;
isSecure = resultIsSecure;
}
#else
Assert.Ignore("DTLS encryption for Relay is not currently available for this version of Unity.");
yield break;
#endif
}
}
}

11
Assets/Scripts/Tests/PlayMode/UtpTests.cs.meta


fileFormatVersion: 2
guid: 0a6dfe6148a08af46a8eb5ffbbcf3f09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存