internal byte[] GenerateConnectToken(IPEndPoint[] addressList, double time, int expirySeconds, int serverTimeout, ulong sequence, ulong clientID, byte[] userData) { if (userData.Length > 256) { throw new ArgumentOutOfRangeException("User data cannot be larger than 256 bytes"); } if (addressList == null) { throw new NullReferenceException("Address list cannot be null"); } else if (addressList.Length == 0) { throw new ArgumentOutOfRangeException("Address list cannot be empty"); } else if (addressList.Length > Defines.MAX_SERVER_ADDRESSES) { throw new ArgumentOutOfRangeException("Address list cannot contain more than " + Defines.MAX_SERVER_ADDRESSES + " entries"); } NetcodePrivateConnectToken privateConnectToken = new NetcodePrivateConnectToken(); privateConnectToken.ClientID = clientID; privateConnectToken.TimeoutSeconds = serverTimeout; // generate random crypto keys byte[] clientToServerKey = new byte[32]; byte[] serverToClientKey = new byte[32]; KeyUtils.GenerateKey(clientToServerKey); KeyUtils.GenerateKey(serverToClientKey); privateConnectToken.ClientToServerKey = clientToServerKey; privateConnectToken.ServerToClientKey = serverToClientKey; privateConnectToken.UserData = new byte[256]; Buffer.BlockCopy(userData, 0, privateConnectToken.UserData, 0, userData.Length); privateConnectToken.ConnectServers = new ConnectTokenServerEntry[addressList.Length]; for (int i = 0; i < privateConnectToken.ConnectServers.Length; i++) { privateConnectToken.ConnectServers[i] = new ConnectTokenServerEntry() { AddressType = addressList[i].AddressFamily == AddressFamily.InterNetwork ? NetcodeAddressType.IPv4 : NetcodeAddressType.IPv6, Endpoint = addressList[i] }; } byte[] privateConnectTokenBytes = new byte[1024]; using (var writer = ByteArrayReaderWriter.Get(privateConnectTokenBytes)) { privateConnectToken.Write(writer); } ulong createTimestamp = (ulong)Math.Truncate(time); ulong expireTimestamp = expirySeconds >= 0 ? (createTimestamp + (ulong)expirySeconds) : 0xFFFFFFFFFFFFFFFFUL; byte[] encryptedPrivateToken = new byte[1024]; PacketIO.EncryptPrivateConnectToken(privateConnectTokenBytes, protocolID, expireTimestamp, sequence, privateKey, encryptedPrivateToken); NetcodePublicConnectToken publicToken = new NetcodePublicConnectToken(); publicToken.ProtocolID = protocolID; publicToken.CreateTimestamp = createTimestamp; publicToken.ExpireTimestamp = expireTimestamp; publicToken.ConnectTokenSequence = sequence; publicToken.PrivateConnectTokenBytes = encryptedPrivateToken; publicToken.ConnectServers = privateConnectToken.ConnectServers; publicToken.ClientToServerKey = clientToServerKey; publicToken.ServerToClientKey = serverToClientKey; publicToken.TimeoutSeconds = serverTimeout; byte[] publicTokenBytes = new byte[2048]; using (var writer = ByteArrayReaderWriter.Get(publicTokenBytes)) { publicToken.Write(writer); } return(publicTokenBytes); }