internal void Connect(ConnectionState State)
        {
            IPAddress[] resolved = Dns.GetHostAddresses(Properties.HostIp);
            string DnsIp = "";
            bool IsIPv6 = false;

            for (int i = 0; i < resolved.Length; i++)
            {
                if (resolved[i].AddressFamily == AddressFamily.InterNetwork ||
                    resolved[i].AddressFamily == AddressFamily.InterNetworkV6)
                {
                    IsIPv6 = resolved[i].AddressFamily == AddressFamily.InterNetworkV6;
                    DnsIp = resolved[i].ToString();
                    break;
                }
            }

            if (DnsIp == "")
            {
                throw new Exception("Unable to resolve \"" + Properties.HostIp + "\" by using DNS");
            }

            int ConTimeout = Properties.ConnectionTimeout;
            do
            {
                this.Handle = new Socket(IsIPv6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IAsyncResult result = this.Handle.BeginConnect(new IPEndPoint(resolved[0], Properties.Port), (IAsyncResult ar) =>
                {
                    try
                    {
                        this.Handle.EndConnect(ar);
                    }
                    catch (Exception ex)
                    {
                        /* Will throw a error if connection couldn't be made */
                        SysLogger.Log(ex.Message, SysLogType.Error);
                    }
                }, null);

                Stopwatch sw = Stopwatch.StartNew();
                if (ConTimeout > 0)
                {
                    result.AsyncWaitHandle.WaitOne(ConTimeout);
                }
                else
                {
                    result.AsyncWaitHandle.WaitOne();
                }

                sw.Stop();
                ConTimeout -= (int)sw.ElapsedMilliseconds;

                if (!this.Handle.Connected)
                    this.Handle.Close();

            } while (ConTimeout > 0 && !this.Handle.Connected);

            if (!Handle.Connected)
                throw new Exception("Unable to establish a connection with " + Properties.HostIp + ":" + Properties.Port);

            Connection = new Connection(this);
            Connection.StartReceiver();

            onBeforeConnect();

            //let's begin the handshake
            User user = new User(Properties.Username, Properties.Password, new List<Stream>(Properties.PrivateKeyFiles), Properties.PublicKeyFile);
            user.GenKey(this, SessionSide.Client, Properties.Handshake_Maze_Size, Properties.Handshake_MazeCount, Properties.Handshake_StepSize);

            this.clientHS = user.MazeHandshake;
            byte[] encryptedPublicKey = clientHS.GetEncryptedPublicKey();

            byte[] byteCode = clientHS.GetByteCode();
            Connection.SendMessage(new MsgHandshake(byteCode), new SystemHeader());

            //send our encrypted public key
            Connection.SendMessage(new MsgHandshake(encryptedPublicKey), new SystemHeader());

            //and now just wait for the handshake to finish... can't take longer then 60 seconds
            MazeErrorCode errorCode = Connection.HandshakeSync.Wait<MazeErrorCode>(MazeErrorCode.Error, 60000);

            if (errorCode != MazeErrorCode.Finished)
            {
                throw new Exception("Username or Password is incorrect.");
            }

            bool initOk = Connection.InitSync.Wait<bool>(false, 30000);
            if (!initOk)
            {
                throw new Exception("A server time-out occured");
            }

            //re-calculate the private keys
            for(int i = 0; i < Properties.PrivateKeyFiles.Length; i++)
            {
                clientHS.RecalculatePrivateKey(Properties.PrivateKeyFiles[i]);
            }

            this.Username = Properties.Username;

            this.KeepAliveTimer = new System.Timers.Timer();
            this.KeepAliveTimer.Interval = 5000;
            this.KeepAliveTimer.Elapsed += KeepAliveTimer_Elapsed;
            this.KeepAliveTimer.Enabled = true;

            onConnect();
        }
 /// <summary>
 /// Create a new instance of User
 /// </summary>
 /// <param name="Username">The Username for the user</param>
 /// <param name="Password">The Password for the user</param>
 /// <param name="PrivateKeys">The Private Key(s) that are being used to Encrypt the Session</param>
 /// <param name="PublicKey">The Public Key to indentify the user</param>
 public User RegisterUser(string Username, string Password, List<Stream> PrivateKeys, Stream PublicKey)
 {
     User user = new User(Username, Password, PrivateKeys, PublicKey);
     user.GenKey(SessionSide.Server, serverProperties.Handshake_Maze_Size, serverProperties.Handshake_MazeCount, serverProperties.Handshake_StepSize);
     return user;
 }