public void Connect(byte[] connectToken, bool autoTick) { if (state != ClientState.Disconnected) { throw new InvalidOperationException(); } keepAliveTimer = 0.0; connectServers.Clear(); replayProtection.Reset(); if (connectToken.Length != Defines.NETCODE_CONNECT_TOKEN_PUBLIC_BYTES) { changeState(ClientState.InvalidConnectToken); return; } NetcodePublicConnectToken tokenData = new NetcodePublicConnectToken(); using (var reader = ByteArrayReaderWriter.Get(connectToken)) { if (!tokenData.Read(reader)) { changeState(ClientState.InvalidConnectToken); return; } } if (tokenData.CreateTimestamp >= tokenData.ExpireTimestamp) { changeState(ClientState.InvalidConnectToken); return; } clientToServerKey = tokenData.ClientToServerKey; serverToClientKey = tokenData.ServerToClientKey; foreach (var server in tokenData.ConnectServers) { connectServers.Enqueue(server.Endpoint); } this.connectToken = tokenData; this.state = ClientState.SendingConnectionRequest; // bind socket, spin up threads, and start trying to connect isRunning = true; currentServerEndpoint = connectServers.Dequeue(); createSocket(currentServerEndpoint); if (autoTick) { this.time = DateTime.Now.GetTotalSeconds(); ThreadPool.QueueUserWorkItem(clientTick); } }
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); }