예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }