Esempio n. 1
0
        void OnDisconnected(object sender, DisconnectedEventArgs e)
        {
            state      = EncryptionState.Disconnected;
            encryption = null;

            Disconnected?.Invoke(this, e);
        }
Esempio n. 2
0
        private void Release( bool userRequestedDisconnect )
        {
            lock (netLock)
            {
                cancellationToken.Dispose();
                cancellationToken = null;

                if (netWriter != null)
                {
                    netWriter.Dispose();
                    netWriter = null;
                }

                if (netReader != null)
                {
                    netReader.Dispose();
                    netReader = null;
                }

                if (netStream != null)
                {
                    netStream.Dispose();
                    netStream = null;
                }

                socket.Close();
                socket = null;

                netFilter = null;
            }

            OnDisconnected( new DisconnectedEventArgs( userRequestedDisconnect ) );

            connectionFree.Set();
        }
Esempio n. 3
0
        private void Release(bool userRequestedDisconnect)
        {
            lock (netLock)
            {
                cancellationToken.Dispose();
                cancellationToken = null;

                if (netWriter != null)
                {
                    netWriter.Dispose();
                    netWriter = null;
                }

                if (netReader != null)
                {
                    netReader.Dispose();
                    netReader = null;
                }

                if (netStream != null)
                {
                    netStream.Dispose();
                    netStream = null;
                }

                socket.Close();
                socket = null;

                netFilter = null;
            }

            OnDisconnected(new DisconnectedEventArgs(userRequestedDisconnect));

            connectionFree.Set();
        }
Esempio n. 4
0
 public override void SetNetEncryptionFilter(INetFilterEncryption filter)
 {
     lock (netLock)
     {
         if (socket != null)
         {
             netFilter = filter;
         }
     }
 }
Esempio n. 5
0
        /// <summary>
        /// Connects this client to a Steam3 server.
        /// This begins the process of connecting and encrypting the data channel between the client and the server.
        /// Results are returned asynchronously in a <see cref="SteamClient.ConnectedCallback"/>.
        /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/>
        /// will be posted instead.
        /// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
        /// preferrably after a short delay.
        /// </summary>
        /// <param name="cmServer">
        /// The <see cref="IPEndPoint"/> of the CM server to connect to.
        /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list.
        /// </param>
        public void Connect(IPEndPoint cmServer = null)
        {
            this.Disconnect();

            encryptionSetup            = false;
            pendingNetFilterEncryption = null;
            ExpectDisconnection        = false;

            if (cmServer == null)
            {
                cmServer = Servers.GetNextServerCandidate();
            }

            connection.Connect(cmServer, ( int )ConnectionTimeout.TotalMilliseconds);
        }
Esempio n. 6
0
        private void ConnectCompleted(bool success)
        {
            // Always discard result if our request was cancelled
            // If we have no cancellation token source, we were already Release()'ed
            if (cancellationToken?.IsCancellationRequested ?? true)
            {
                DebugLog.WriteLine("TcpConnection", "Connection request to {0} was cancelled", destination);
                if (success)
                {
                    Shutdown();
                }
                Release(userRequestedDisconnect: true);
                return;
            }
            else if (!success)
            {
                DebugLog.WriteLine("TcpConnection", "Timed out while connecting to {0}", destination);
                Release(userRequestedDisconnect: false);
                return;
            }

            DebugLog.WriteLine("TcpConnection", "Connected to {0}", destination);

            try
            {
                lock (netLock)
                {
                    netStream = new NetworkStream(socket, false);
                    netReader = new BinaryReader(netStream);
                    netWriter = new BinaryWriter(netStream);
                    netFilter = null;

                    netThread      = new Thread(NetLoop);
                    netThread.Name = "TcpConnection Thread";
                }

                netThread.Start();

                OnConnected(EventArgs.Empty);
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("TcpConnection", "Exception while setting up connection to {0}: {1}", destination, ex);
                Release(userRequestedDisconnect: false);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Connects this client to a UFS server.
        /// This begins the process of connecting and encrypting the data channel between the client and the UFS server.
        /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>.
        /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead.
        /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay.
        /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server.
        /// </summary>
        /// <param name="ufsServer">
        /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to.
        /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers.
        /// </param>
        public void Connect(IPEndPoint ufsServer = null)
        {
            DebugLog.Assert(steamClient.IsConnected, "UFSClient", "CMClient is not connected!");

            this.Disconnect();

            pendingNetFilterEncryption = null;

            if (ufsServer == null)
            {
                var serverList = steamClient.GetServersOfType(EServerType.UFS);

                Random random = new Random();
                ufsServer = serverList[random.Next(serverList.Count)];
            }

            connection.Connect(ufsServer, ( int )ConnectionTimeout.TotalMilliseconds);
        }
Esempio n. 8
0
        void HandleEncryptResult(IPacketMsg packetMsg)
        {
            var encResult = new Msg <MsgChannelEncryptResult>(packetMsg);

            DebugLog.WriteLine("UFSClient", "Encryption result: {0}", encResult.Body.Result);

            if (encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null)
            {
                Debug.Assert(pendingNetFilterEncryption != null);
                connection.SetNetEncryptionFilter(pendingNetFilterEncryption);

                pendingNetFilterEncryption = null;
                steamClient.PostCallback(new ConnectedCallback(encResult.Body));
            }
            else
            {
                DebugLog.WriteLine("UFSClient", "Encryption channel setup failed");
                connection.Disconnect();
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Connects this client to a Steam3 server.
        /// This begins the process of connecting and encrypting the data channel between the client and the server.
        /// Results are returned asynchronously in a <see cref="SteamClient.ConnectedCallback"/>.
        /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/>
        /// will be posted instead.
        /// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
        /// preferrably after a short delay.
        /// </summary>
        /// <param name="cmServer">
        /// The <see cref="IPEndPoint"/> of the CM server to connect to.
        /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list.
        /// </param>
        public void Connect(IPEndPoint cmServer = null)
        {
            this.Disconnect();

            encryptionSetup            = false;
            pendingNetFilterEncryption = null;
            ExpectDisconnection        = false;

            Task <IPEndPoint> epTask = null;

            if (cmServer == null)
            {
                epTask = Servers.GetNextServerCandidateAsync();
            }
            else
            {
                epTask = Task.FromResult(cmServer);
            }

            connection.Connect(epTask, ( int )ConnectionTimeout.TotalMilliseconds);
        }
Esempio n. 10
0
        bool HandleEncryptResult(IPacketMsg packetMsg)
        {
            var encResult = new Msg <MsgChannelEncryptResult>(packetMsg);

            DebugLog.WriteLine("CMClient", "Encryption result: {0}", encResult.Body.Result);

            if (encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null)
            {
                Debug.Assert(pendingNetFilterEncryption != null);
                connection.SetNetEncryptionFilter(pendingNetFilterEncryption);

                pendingNetFilterEncryption = null;
                encryptionSetup            = true;
                return(true);
            }
            else
            {
                DebugLog.WriteLine("CMClient", "Encryption channel setup failed");
                connection.Disconnect();
                return(false);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Connects to the specified CM server.
        /// </summary>
        /// <param name="endPointTask">Task returning the CM server.</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        public override void Connect(Task <IPEndPoint> endPointTask, int timeout)
        {
            Disconnect();

            outPackets = new List <UdpPacket>();
            inPackets  = new Dictionary <uint, UdpPacket>();

            remoteEndPoint = null;
            remoteConnId   = 0;

            outSeq      = 1;
            outSeqSent  = 0;
            outSeqAcked = 0;

            inSeq        = 0;
            inSeqAcked   = 0;
            inSeqHandled = 0;

            filter = null;

            netThread      = new Thread(NetLoop);
            netThread.Name = "UdpConnection Thread";
            netThread.Start(endPointTask);
        }
Esempio n. 12
0
 /// <summary>
 /// Sets the network encryption filter for this connection
 /// </summary>
 /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param>
 public override void SetNetEncryptionFilter( INetFilterEncryption filter )
 {
     this.filter = filter;
 }
Esempio n. 13
0
        void HandleEncryptResult( IPacketMsg packetMsg )
        {
            var encResult = new Msg<MsgChannelEncryptResult>( packetMsg );

            DebugLog.WriteLine( "UFSClient", "Encryption result: {0}", encResult.Body.Result );

            if ( encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null )
            {
                Debug.Assert( pendingNetFilterEncryption != null );
                connection.SetNetEncryptionFilter( pendingNetFilterEncryption );

                pendingNetFilterEncryption = null;
                steamClient.PostCallback( new ConnectedCallback( encResult.Body ) );
            }
            else
            {
                DebugLog.WriteLine( "UFSClient", "Encryption channel setup failed" );
                connection.Disconnect();
            }
        }
Esempio n. 14
0
        bool HandleEncryptResult( IPacketMsg packetMsg )
        {
            var encResult = new Msg<MsgChannelEncryptResult>( packetMsg );

            DebugLog.WriteLine( "CMClient", "Encryption result: {0}", encResult.Body.Result );

            if ( encResult.Body.Result == EResult.OK && pendingNetFilterEncryption != null )
            {
                Debug.Assert( pendingNetFilterEncryption != null );
                connection.SetNetEncryptionFilter( pendingNetFilterEncryption );

                pendingNetFilterEncryption = null;
                encryptionSetup = true;
                return true;
            }
            else
            {
                DebugLog.WriteLine( "CMClient", "Encryption channel setup failed" );
                connection.Disconnect();
                return false;
            }
        }
Esempio n. 15
0
 /// <summary>
 /// Sets the network encryption filter for this connection
 /// </summary>
 /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param>
 public abstract void SetNetEncryptionFilter(INetFilterEncryption filter);
Esempio n. 16
0
        void HandleEncryptRequest(IPacketMsg packetMsg)
        {
            var request = new Msg <MsgChannelEncryptRequest>(packetMsg);

            var connectedUniverse = request.Body.Universe;
            var protoVersion      = request.Body.ProtocolVersion;

            DebugLog.WriteLine(nameof(EnvelopeEncryptedConnection), "Got encryption request. Universe: {0} Protocol ver: {1}", connectedUniverse, protoVersion);
            DebugLog.Assert(protoVersion == 1, nameof(EnvelopeEncryptedConnection), "Encryption handshake protocol version mismatch!");
            DebugLog.Assert(connectedUniverse == universe, nameof(EnvelopeEncryptedConnection), FormattableString.Invariant($"Expected universe {universe} but server reported universe {connectedUniverse}"));

            byte[] randomChallenge;
            if (request.Payload.Length >= 16)
            {
                randomChallenge = request.Payload.ToArray();
            }
            else
            {
                randomChallenge = null;
            }

            var publicKey = KeyDictionary.GetPublicKey(connectedUniverse);

            if (publicKey == null)
            {
                DebugLog.WriteLine(nameof(EnvelopeEncryptedConnection), "HandleEncryptRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", connectedUniverse, protoVersion);

                Disconnect();
            }

            var response = new Msg <MsgChannelEncryptResponse>();

            var tempSessionKey = CryptoHelper.GenerateRandomBlock(32);

            byte[] encryptedHandshakeBlob = null;

            using (var rsa = new RSACrypto(publicKey))
            {
                if (randomChallenge != null)
                {
                    var blobToEncrypt = new byte[tempSessionKey.Length + randomChallenge.Length];
                    Array.Copy(tempSessionKey, blobToEncrypt, tempSessionKey.Length);
                    Array.Copy(randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length);

                    encryptedHandshakeBlob = rsa.Encrypt(blobToEncrypt);
                }
                else
                {
                    encryptedHandshakeBlob = rsa.Encrypt(tempSessionKey);
                }
            }

            var keyCrc = CryptoHelper.CRCHash(encryptedHandshakeBlob);

            response.Write(encryptedHandshakeBlob);
            response.Write(keyCrc);
            response.Write(( uint )0);

            if (randomChallenge != null)
            {
                encryption = new NetFilterEncryptionWithHMAC(tempSessionKey);
            }
            else
            {
                encryption = new NetFilterEncryption(tempSessionKey);
            }

            state = EncryptionState.Challenged;
            Send(response.Serialize());
        }
Esempio n. 17
0
 /// <summary>
 /// Sets the network encryption filter for this connection
 /// </summary>
 /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param>
 public abstract void SetNetEncryptionFilter( INetFilterEncryption filter );
Esempio n. 18
0
 /// <summary>
 /// Sets the network encryption filter for this connection
 /// </summary>
 /// <param name="filter">filter implementing <see cref="INetFilterEncryption"/></param>
 public override void SetNetEncryptionFilter(INetFilterEncryption filter)
 {
     this.filter = filter;
 }
Esempio n. 19
0
        bool HandleEncryptRequest(IPacketMsg packetMsg)
        {
            var encRequest = new Msg <MsgChannelEncryptRequest>(packetMsg);

            EUniverse eUniv        = encRequest.Body.Universe;
            uint      protoVersion = encRequest.Body.ProtocolVersion;

            DebugLog.WriteLine("CMClient", "Got encryption request. Universe: {0} Protocol ver: {1}", eUniv, protoVersion);
            DebugLog.Assert(protoVersion == 1, "CMClient", "Encryption handshake protocol version mismatch!");

            byte[] randomChallenge;
            if (encRequest.Payload.Length >= 16)
            {
                randomChallenge = encRequest.Payload.ToArray();
            }
            else
            {
                randomChallenge = null;
            }

            byte[] pubKey = KeyDictionary.GetPublicKey(eUniv);

            if (pubKey == null)
            {
                connection.Disconnect();

                DebugLog.WriteLine("CMClient", "HandleEncryptionRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", eUniv, protoVersion);
                return(false);
            }

            ConnectedUniverse = eUniv;

            var encResp = new Msg <MsgChannelEncryptResponse>();

            var tempSessionKey = CryptoHelper.GenerateRandomBlock(32);

            byte[] encryptedHandshakeBlob = null;

            using (var rsa = new RSACrypto(pubKey))
            {
                if (randomChallenge != null)
                {
                    var blobToEncrypt = new byte[tempSessionKey.Length + randomChallenge.Length];
                    Array.Copy(tempSessionKey, blobToEncrypt, tempSessionKey.Length);
                    Array.Copy(randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length);

                    encryptedHandshakeBlob = rsa.Encrypt(blobToEncrypt);
                }
                else
                {
                    encryptedHandshakeBlob = rsa.Encrypt(tempSessionKey);
                }
            }

            var keyCrc = CryptoHelper.CRCHash(encryptedHandshakeBlob);

            encResp.Write(encryptedHandshakeBlob);
            encResp.Write(keyCrc);
            encResp.Write(( uint )0);

            if (randomChallenge != null)
            {
                pendingNetFilterEncryption = new NetFilterEncryptionWithHMAC(tempSessionKey);
            }
            else
            {
                pendingNetFilterEncryption = new NetFilterEncryption(tempSessionKey);
            }

            this.Send(encResp);
            return(true);
        }
Esempio n. 20
0
        /// <summary>
        /// Connects this client to a Steam3 server.
        /// This begins the process of connecting and encrypting the data channel between the client and the server.
        /// Results are returned asynchronously in a <see cref="SteamClient.ConnectedCallback"/>.
        /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/>
        /// will be posted instead.
        /// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
        /// preferrably after a short delay.
        /// </summary>
        /// <param name="cmServer">
        /// The <see cref="IPEndPoint"/> of the CM server to connect to.
        /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list.
        /// </param>
        public void Connect( IPEndPoint cmServer = null  )
        {
            this.Disconnect();

            encryptionSetup = false;
            pendingNetFilterEncryption = null;
            ExpectDisconnection = false;

            if ( cmServer == null )
            {
                cmServer = Servers.GetNextServerCandidate();
            }

            connection.Connect( cmServer, ( int )ConnectionTimeout.TotalMilliseconds );
        }
Esempio n. 21
0
        /// <summary>
        /// Connects this client to a Steam3 server.
        /// This begins the process of connecting and encrypting the data channel between the client and the server.
        /// Results are returned asynchronously in a <see cref="SteamClient.ConnectedCallback"/>.
        /// If the server that SteamKit attempts to connect to is down, a <see cref="SteamClient.DisconnectedCallback"/>
        /// will be posted instead.
        /// SteamKit will not attempt to reconnect to Steam, you must handle this callback and call Connect again
        /// preferrably after a short delay.
        /// </summary>
        /// <param name="cmServer">
        /// The <see cref="IPEndPoint"/> of the CM server to connect to.
        /// If <c>null</c>, SteamKit will randomly select a CM server from its internal list.
        /// </param>
        public void Connect( IPEndPoint cmServer = null  )
        {
            this.Disconnect();

            encryptionSetup = false;
            pendingNetFilterEncryption = null;
            ExpectDisconnection = false;

            Task<IPEndPoint> epTask = null;

            if ( cmServer == null )
            {
                epTask = Servers.GetNextServerCandidateAsync();
            }
            else
            {
                epTask = Task.FromResult( cmServer );
            }

            connection.Connect( epTask, ( int )ConnectionTimeout.TotalMilliseconds );
        }
Esempio n. 22
0
 public override void SetNetEncryptionFilter( INetFilterEncryption filter )
 {
     lock (netLock)
     {
         if (socket != null)
         {
             netFilter = filter;
         }
     }
 }
Esempio n. 23
0
        void HandleEncryptRequest( IPacketMsg packetMsg )
        {
            var encRequest = new Msg<MsgChannelEncryptRequest>( packetMsg );

            EUniverse eUniv = encRequest.Body.Universe;
            uint protoVersion = encRequest.Body.ProtocolVersion;

            DebugLog.WriteLine( "UFSClient", "Got encryption request. Universe: {0} Protocol ver: {1}", eUniv, protoVersion );
            DebugLog.Assert( protoVersion == 1, "UFSClient", "Encryption handshake protocol version mismatch!" );

            byte[] randomChallenge;
            if ( encRequest.Payload.Length >= 16 )
            {
                randomChallenge = encRequest.Payload.ToArray();
            }
            else
            {
                randomChallenge = null;
            }

            byte[] pubKey = KeyDictionary.GetPublicKey( eUniv );

            if ( pubKey == null )
            {
                connection.Disconnect();

                DebugLog.WriteLine( "UFSClient", "HandleEncryptionRequest got request for invalid universe! Universe: {0} Protocol ver: {1}", eUniv, protoVersion );
                return;
            }

            ConnectedUniverse = eUniv;

            var encResp = new Msg<MsgChannelEncryptResponse>();

            var tempSessionKey = CryptoHelper.GenerateRandomBlock( 32 );
            byte[] encryptedHandshakeBlob = null;

            using ( var rsa = new RSACrypto( pubKey ) )
            {
                if ( randomChallenge != null )
                {
                    var blobToEncrypt = new byte[ tempSessionKey.Length + randomChallenge.Length ];
                    Array.Copy( tempSessionKey, blobToEncrypt, tempSessionKey.Length );
                    Array.Copy( randomChallenge, 0, blobToEncrypt, tempSessionKey.Length, randomChallenge.Length );

                    encryptedHandshakeBlob = rsa.Encrypt( blobToEncrypt );
                }
                else
                {
                    encryptedHandshakeBlob = rsa.Encrypt( tempSessionKey );
                }
            }

            var keyCrc = CryptoHelper.CRCHash( encryptedHandshakeBlob );

            encResp.Write( encryptedHandshakeBlob );
            encResp.Write( keyCrc );
            encResp.Write( ( uint )0 );

            if ( randomChallenge != null )
            {
                pendingNetFilterEncryption = new NetFilterEncryptionWithHMAC( tempSessionKey );
            }
            else
            {
                pendingNetFilterEncryption = new NetFilterEncryption( tempSessionKey );
            }

            this.Send( encResp );
        }
Esempio n. 24
0
        private void ConnectCompleted(bool success)
        {
            // Always discard result if our request was cancelled
            if (cancellationToken.IsCancellationRequested)
            {
                DebugLog.WriteLine("TcpConnection", "Connection request to {0} was cancelled", destination);
                if (success) Shutdown();
                Release( userRequestedDisconnect: true );
                return;
            }
            else if (!success)
            {
                DebugLog.WriteLine("TcpConnection", "Timed out while connecting to {0}", destination);
                Release( userRequestedDisconnect: false );
                return;
            }

            DebugLog.WriteLine("TcpConnection", "Connected to {0}", destination);

            try
            {
                lock (netLock)
                {
                    netStream = new NetworkStream(socket, false);
                    netReader = new BinaryReader(netStream);
                    netWriter = new BinaryWriter(netStream);
                    netFilter = null;

                    netThread = new Thread(NetLoop);
                    netThread.Name = "TcpConnection Thread";
                }

                netThread.Start();

                OnConnected(EventArgs.Empty);
            }
            catch (Exception ex)
            {
                DebugLog.WriteLine("TcpConnection", "Exception while setting up connection to {0}: {1}", destination, ex);
                Release( userRequestedDisconnect: false );
            }
        }
Esempio n. 25
0
        /// <summary>
        /// Connects this client to a UFS server.
        /// This begins the process of connecting and encrypting the data channel between the client and the UFS server.
        /// Results are returned asynchronously in a <see cref="ConnectedCallback"/>.
        /// If the UFS server that this client attempts to connect to is down, a <see cref="DisconnectedCallback"/> will be posted instead.
        /// <see cref="UFSClient"/> will not attempt to reconnect to Steam, you must handle this callback and call <see cref="Connect"/> again, preferrably after a short delay.
        /// In order to connect to the UFS server, the parent <see cref="SteamClient"/> must be connected to the CM server.
        /// </summary>
        /// <param name="ufsServer">
        /// The <see cref="System.Net.IPEndPoint"/> of the UFS server to connect to.
        /// If <c>null</c>, <see cref="UFSClient"/> will randomly select a UFS server from the <see cref="SteamClient"/>'s list of servers.
        /// </param>
        public void Connect( IPEndPoint ufsServer = null )
        {
            DebugLog.Assert( steamClient.IsConnected, "UFSClient", "CMClient is not connected!" );

            this.Disconnect();

            pendingNetFilterEncryption = null;

            if ( ufsServer == null )
            {
                var serverList = steamClient.GetServersOfType( EServerType.UFS );

                Random random = new Random();
                ufsServer = serverList[ random.Next( serverList.Count ) ];
            }

            connection.Connect( ufsServer, ( int )ConnectionTimeout.TotalMilliseconds );
        }
Esempio n. 26
0
        /// <summary>
        /// Connects to the specified CM server.
        /// </summary>
        /// <param name="endPointTask">Task returning the CM server.</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        public override void Connect(Task<IPEndPoint> endPointTask, int timeout)
        {
            Disconnect();

            outPackets = new List<UdpPacket>();
            inPackets = new Dictionary<uint, UdpPacket>();

            remoteEndPoint = null;
            remoteConnId = 0;

            outSeq = 1;
            outSeqSent = 0;
            outSeqAcked = 0;

            inSeq = 0;
            inSeqAcked = 0;
            inSeqHandled = 0;

            filter = null;

            netThread = new Thread(NetLoop);
            netThread.Name = "UdpConnection Thread";
            netThread.Start(endPointTask);
        }