private SecureSocketProxy CreateSocketByUri(Uri uri)
        {
            if (!String.Equals(uri.Scheme, "http", StringComparison.OrdinalIgnoreCase) &&
                !String.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
                throw new InvalidOperationException("Unrecognized scheme: " + uri.Scheme);

            SecureSocketProxy s = new SecureSocketProxy(String.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase));
            try
            {
                s.Connect(uri.Host, uri.Port);
            }
            catch(Exception ex)
            {
                s.Dispose();

                // Emitting protocol error. It will emit session OnError
                if (OnError != null)
                    this.OnError(this, new ProtocolErrorEventArgs(ex));

                throw;
            }

            return s;
        }
        /// <summary>
        /// Initializes connection to the remote host.
        /// </summary>
        public HandshakeHeadersBlock Connect()
        {
            _socket = CreateSocketByUri(uri);

            this.opened = true;

            var handshakeBlock = new HandshakeHeadersBlock(this, uri);

            bool isHandShakeOk = false;

            try
            {
                isHandShakeOk = handshakeBlock.StartHandshake();
            }
            catch(Exception)
            {
                isHandShakeOk = false;
            }

            if (isHandShakeOk)
            {
                if (OnOpen != null)
                    OnOpen(this, null);

                ThreadPool.QueueUserWorkItem(ProcessMessages);
            }
            else
            {
                CloseInternal(StatusCode.Cancel, 0, false);
                throw new HandshakeException("Handshake failed");
            }

            return handshakeBlock;
        }