Esempio n. 1
0
        public void StreamToStream()
        {
            using (var server = new StreamSocket())
                using (var client = new StreamSocket())
                {
                    var port = server.BindRandomPort("tcp://*");
                    client.Connect("tcp://127.0.0.1:" + port);

                    byte[] clientId = client.Options.Identity;

                    const string request = "GET /\r\n";

                    const string response = "HTTP/1.0 200 OK\r\n" +
                                            "Content-Type: text/plain\r\n" +
                                            "\r\n" +
                                            "Hello, World!";

                    client.SendMoreFrame(clientId).SendFrame(request);

                    byte[] serverId = server.ReceiveFrameBytes();

                    Console.WriteLine(serverId);
                    Assert.AreEqual(request, server.ReceiveFrameString());

                    server.SendMoreFrame(serverId).SendFrame(response);

                    CollectionAssert.AreEqual(clientId, client.ReceiveFrameBytes());
                    Assert.AreEqual(response, client.ReceiveFrameString());
                }
        }
Esempio n. 2
0
        private void OnHTTPResponse(IAsyncResult result)
        {
            AsyncHttpResponse state = (AsyncHttpResponse)result.AsyncState;
            var success             = false;

            try
            {
                state.Request.EndGetResponse(result);
                success = true;
            }
            catch (WebException)
            {
                if (state.AssociatedAccount.Protocol == "https")
                {
                    // try to fetch certificate
                    try
                    {
                        var tls = new TLSHandshake();
                        tls.SetServerNameExtension(state.AssociatedAccount.Hostname);
                        var socket = new StreamSocket();
                        socket.Connect(state.AssociatedAccount.Hostname, state.AssociatedAccount.GetPort(true));
                        socket.Write(tls.CreateClientHello());

                        DateTime startTime = DateTime.Now;
                        while (true)
                        {
                            var data = socket.Read();
                            if (data.Length > 0)
                            {
                                var cert = tls.FindPacket(data, TLSHandshake.TLS_HANDSHAKE_CERTIFICATE);
                                if (cert.Length > 0)
                                {
                                    var details = tls.GetCertificateDetails(cert);
                                    if (details.Count > 0)
                                    {
                                        var certDetails = details[0];
                                        if (certDetails.ContainsKey("CN"))
                                        {
                                            Dispatcher.BeginInvoke(() =>
                                            {
                                                MessageBox.Show("EditAccountPage_Connection_Rejected".Translate(state.AssociatedAccount.Hostname, certDetails["CN"], certDetails["ValidAfter"], certDetails["ValidTo"]), "EditAccountPage_Connection_Rejected_Caption".Translate(), MessageBoxButton.OK);
                                                _overlay.Hide();
                                            });
                                            return;
                                        }
                                    }
                                    break;
                                }
                            }

                            if (DateTime.Now.Subtract(startTime).TotalSeconds > 5)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        // Host not reachable, no SSL host or TLS version not supported
                    }
                }
            }
            catch (Exception)
            {
                // HTTPWebRequest has failed
            }

            if (success)
            {
                // Testing DAV
                //TODO: Add your additional connection test statement here
                // To complete the test all fragments must have been fired.
                EventCollector collector = new EventCollector()
                {
                    Complete = () =>
                    {
                        OnConnectTestComplete(success, state.AssociatedAccount);
                    }
                };
                collector.WaitFor(state.AssociatedAccount.WebDAVPath);
                collector.WaitFor(state.AssociatedAccount.CalDAVPath);

                // define paths to test
                Queue <string> pathsToTest = new Queue <string>();
                pathsToTest.Enqueue(state.AssociatedAccount.WebDAVPath);
                pathsToTest.Enqueue(state.AssociatedAccount.CalDAVPath);

                // create master instance
                WebDAV davTest = new WebDAV(state.AssociatedAccount.GetUri(), state.AssociatedAccount.GetCredentials());

                // call tests
                while (pathsToTest.Count > 0)
                {
                    var path = pathsToTest.Dequeue();
                    davTest.StartRequest(DAVRequestHeader.CreateListing(path), path, (requestResult, userObj) =>
                    {
                        if (requestResult.Status != ServerStatus.MultiStatus)
                        {
                            // all other states are fail states
                            success = false;
                            Dispatcher.BeginInvoke(() =>
                            {
                                MessageBox.Show("EditAccountPage_CheckingConnection_DAVTestFailed".Translate(userObj, requestResult.StatusText), "Error_Caption".Translate(), MessageBoxButton.OK);
                            });
                        }
                        collector.Raise(userObj);
                    });
                }
            }
            else
            {
                OnConnectTestComplete(success, state.AssociatedAccount);
            }
        }
Esempio n. 3
0
        //------------------------------------------------------------------------------------------------------------------------
        SimpleActionResult _sockConnection(string RemoteHost, int RemotePort)
        {
            //declares
            bool   isSecured   = false;
            string sslProtocol = "";
            var    result      = new SimpleActionResult()
            {
                IsSuccessful = false,
                Message      = "",
            };

            lock (this)
            {
                //create socket
#if NETFX
                _sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
#elif UNIVERSAL
                _sock = new StreamSocket();
#endif

                //Try to connect
                try
                {
                    //attemp connection
#if NETFX
                    _sock.Connect(RemoteHost, RemotePort);
#elif UNIVERSAL
                    SocketSetup?.Invoke(this, _sock);
                    _sock.Control.KeepAlive = true;
                    _sock.ConnectAsync(new Windows.Networking.HostName(RemoteHost), RemotePort.ToStringInvariant(), SocketProtectionLevel.PlainSocket).AsTask().Wait();
#endif
                }
                catch (Exception ex)
                {
                    DebugEx.TraceError(ex, "Connection Error");
                    result.Message = ex.Message;
                    try { Close("Connection Error"); } catch { }
                    return(result);
                }


                //create network stream
#if NETFX
                //Stream _netstream = new BufferedStream(new NetworkStream(_sock, true));
                Stream _netstream = new NetworkStream(_sock, true);
#endif

                //Wrap with a secure stream?
                if (Secure)
                {
#if NETFX
                    //create ssl stream
                    var sslstream = new SslStream(_netstream, false);
#endif
                    //decide on certifacte server name
                    var remCertHostName = !string.IsNullOrWhiteSpace(CertificateServerName) ? CertificateServerName : RemoteHost;

                    try
                    {
#if NETFX
                        //collect certificates
                        var certs = Yodiwo.Tools.Certificates.CollectCertificates();
                        if (CustomCertificates != null)
                        {
                            foreach (var c in CustomCertificates)
                            {
                                certs.Add(c);
                            }
                        }

                        //try authenticate
                        sslstream.AuthenticateAsClient(remCertHostName,
                                                       certs,
                                                       System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12,
                                                       true
                                                       );


                        //checks
                        if (!sslstream.IsAuthenticated)
                        {
                            DebugEx.Assert("Not authenticated");
                            throw new Exception("Not authenticated");
                        }
                        if (!sslstream.IsEncrypted)
                        {
                            DebugEx.Assert("No encryption");
                            throw new Exception("Not encryption");
                        }

                        //get info
                        isSecured   = true;
                        sslProtocol = sslstream.SslProtocol.ToStringInvariant();

                        //use this stream from now on
                        _netstream = sslstream;
#elif UNIVERSAL
                        _sock.UpgradeToSslAsync(SocketProtectionLevel.Tls12, new Windows.Networking.HostName(remCertHostName)).AsTask().Wait();
                        var _isSecured = _sock.Information.ProtectionLevel == SocketProtectionLevel.Tls10 ||
                                         _sock.Information.ProtectionLevel == SocketProtectionLevel.Tls11 ||
                                         _sock.Information.ProtectionLevel == SocketProtectionLevel.Tls12;
                        if (!_isSecured)
                        {
                            throw new Exception("Connection not secured (" + _sock.Information.ProtectionLevel + ")");
                        }
#endif
                    }
                    catch (Exception ex)
                    {
                        DebugEx.TraceError(ex, "Certificate not accepted, " + ex.Message);
                        result.Message = "Certificate not accepted, " + ex.Message;
                        if (ex.InnerException != null)
                        {
                            result.Message += "  (inner msg=" + ex.InnerException.Message + ")";
                        }
                        try { Close("Certificate not accepted, " + ex.Message); } catch { }
#if NETFX
                        try { _netstream?.Close(); _netstream?.Dispose(); } catch { }
                        try { sslstream?.Close(); sslstream?.Dispose(); } catch { }
                        try { _sock?.Close(); } catch { }
#endif
                        try { _sock?.Dispose(); } catch { }
                        return(result);
                    }
                }


                //write packers
#if NETFX
                var _nodelay = _sock.NoDelay;
                _sock.NoDelay = true; //Disable the Nagle Algorithm
                _netstream.WriteByte((byte)this.SupportedChannelSerializationModes);
                _netstream.WriteByte((byte)this.PreferredChannelSerializationModes);
                _sock.NoDelay = _nodelay; //Restore (default:enable) the Nagle Algorithm
#elif UNIVERSAL
                {
                    var wStream = _sock.OutputStream.AsStreamForWrite();
                    wStream.WriteByte((byte)this.SupportedChannelSerializationModes);
                    wStream.WriteByte((byte)this.PreferredChannelSerializationModes);
                    wStream.Flush();
                }
#endif

                //read final packer
                var packerType = ChannelSerializationMode.Unkown;
#if NETFX
                packerType = (ChannelSerializationMode)_netstream.ReadByte();
#elif UNIVERSAL
                packerType = (ChannelSerializationMode)_sock.InputStream.AsStreamForRead().ReadByte();
#endif
                if (!this.SupportedChannelSerializationModes.HasFlag(packerType))
                {
                    DebugEx.Assert("Invalid ChannelSerializationMode. Server uses  " + packerType);
                    result.Message = "Invalid ChannelSerializationMode. Server uses  " + packerType;
                    try { Close("Invalid ChannelSerializationMode. Server uses  " + packerType); } catch { }
#if NETFX
                    try { _netstream?.Close(); _netstream?.Dispose(); } catch { }
                    try { _sock?.Close(); } catch { }
#endif
                    try { _sock?.Dispose(); } catch { }
                    return(result);
                }
                //select serialization mode
                _ChannelSerializationMode = packerType;

                //setup info
                try
                {
#if NETFX
                    this.LocalHost  = _sock.LocalEndPoint.GetIPAddress().ToString();
                    this.RemotePort = _sock.LocalEndPoint.GetPort().ToStringInvariant();
#elif UNIVERSAL
                    this.LocalHost  = _sock.Information.LocalAddress.ToString();
                    this.RemotePort = _sock.Information.LocalPort;
#endif
                }
                catch { }

                //setup info
                this.RemoteHost = RemoteHost;
                this.RemotePort = RemotePort.ToStringInvariant();

                //log
                DebugEx.TraceLog("YPClient (socks) new connection to " + RemoteHost + ":" + RemotePort + " (Secure=" + isSecured + ",SSL=" + sslProtocol + ")");

                //create stream
#if NETFX
                SetupStream(_netstream);
#elif UNIVERSAL
                SetupStream();
#endif
                result.IsSuccessful = true;
                return(result);
            }
        }
Esempio n. 4
0
 public static PhpResource fsockopen(Context ctx, string target, int port, out int errno, out string errstr, double timeout, bool persistent = false)
 {
     return(StreamSocket.Connect(ctx, target, port, out errno, out errstr, timeout,
                                 persistent ? StreamSocket.SocketOptions.Persistent : StreamSocket.SocketOptions.None,
                                 StreamContext.Default));
 }
Esempio n. 5
0
        public void Do()
        {
            // we are using dealer here, but we can use router as well, we just have to manager
            // SecureChannel for each identity
            using (var socket = new StreamSocket())
            {
                socket.Connect("tcp://127.0.0.1:9696");

                using (SecureChannel secureChannel = SecureChannel.CreateClientSecureChannel(null, m_configuration))
                {
                    secureChannel.AllowedCipherSuites = new [] { CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA };
                    // we need to set X509Certificate with a private key for the server
                    X509Certificate2 certificate = new X509Certificate2(
                        System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "server.pfx"), "1234");
                    secureChannel.Certificate = certificate;
                    List <NetMQMessage> outgoingMessages = new List <NetMQMessage>();
                    bool clientComplete = secureChannel.ProcessMessage(null, outgoingMessages);

                    SendMessages(socket, outgoingMessages);
                    bool done = false;
                    // waiting for message from client
                    byte[] cache = null;
                    do
                    {
                        outgoingMessages.Clear();
                        NetMQMessage incomingMessage = socket.ReceiveMultipartMessage();
                        if (cache == null || cache.Length <= 0)
                        {
                            cache = incomingMessage.Last.Buffer;
                        }
                        else
                        {
                            cache = CombineV2(cache, incomingMessage.Last.Buffer);
                        }
                        //SplitInMessage
                        int offset;
                        List <NetMQMessage> sslMessages;
                        secureChannel.ResolveRecordLayer(cache, out offset, out sslMessages);
                        if (cache.Length == offset)
                        {
                            cache = null;
                        }
                        else if (cache.Length > offset)
                        {
                            byte[] temp = new byte[cache.Length - offset];
                            Buffer.BlockCopy(cache, offset, temp, 0, temp.Length);
                            cache = temp;
                        }
                        foreach (var sslMessage in sslMessages)
                        {
                            // calling ProcessMessage until ProcessMessage return true
                            // and the SecureChannel is ready to encrypt and decrypt messages
                            done = secureChannel.ProcessMessage(sslMessage, outgoingMessages);
                            SendMessages(socket, outgoingMessages);
                        }
                    } while (!done);
                    SendMessages(socket, outgoingMessages);
                    for (int i = 0; i < 10; i++)
                    {
                        outgoingMessages.Clear();

                        NetMQMessage plainMessage = new NetMQMessage();
                        byte[]       data         = Encoding.GetEncoding("GBK").GetBytes("10009<Root><Head><CommandCode>10009</CommandCode><TransSeqID>2020051514384165</TransSeqID><VerifyCode>MbzZvbTp9Cnw9iqvRjJ3in6wNry59ZB1ubSCpWxeRiov9eU0c8MCGTE+u+7ED7NlU4EA8mf+OATBvS6OlgYzggKmsEt6CoPhQB3V/xzMZzlLGwym7r1arrNYIUjW6oJKXWNe84SYTe8Mqfw1+gmzEcj72QpadujHdDTJ9WNEsmg=</VerifyCode><ZipType></ZipType><CorpBankCode>103</CorpBankCode><FGCommandCode>11111</FGCommandCode><EnterpriseNum>AS330106</EnterpriseNum><TransKeyEncryptFlag>0</TransKeyEncryptFlag><FGVerifyCode>nQuCJ41Gp1wuankSkCvscwFVISkdI0XoGUJwKTB9IS7dbg+OgxpHe/zdSQkIZQjZbS5rzkFlmx31mrR8cmZa/jXJ+r4xeBfncS6qKJdYEH4jJra4/JyFkcb2mE8yolxN3v1C/M/Kq2+d532oXuQfiBqkEAv3gSb30zjurtVs3+I=</FGVerifyCode></Head><RealTimeSingleTransReq><MoneyWay>2</MoneyWay><TransDate>20200515</TransDate><Trans><TransNo>testClwTLS20200515003</TransNo><ProtocolCode></ProtocolCode><EnterpriseAccNum>19030101040014391</EnterpriseAccNum><CustBankCode>103</CustBankCode><CustAccNum>12312312</CustAccNum><CustAccName>陈大帅逼</CustAccName><AreaCode></AreaCode><BankLocationCode></BankLocationCode><BankLocationName></BankLocationName><CardType></CardType><IsPrivate>0</IsPrivate><IsUrgent></IsUrgent><Amount>232.00</Amount><Currency>CNY</Currency><CertType>0</CertType><CertNum></CertNum><Mobile></Mobile><Purpose></Purpose><Memo></Memo><PolicyNumber></PolicyNumber><Extent1></Extent1><Extent2></Extent2><SourceTransNo>testClwTLS20200515003</SourceTransNo></Trans></RealTimeSingleTransReq></Root>");
                        string       length       = data.Length.ToString().PadLeft(8, ' ');
                        plainMessage.Append(length);
                        plainMessage.Append(data);

                        socket.SendMoreFrame(socket.Options.Identity);
                        socket.SendFrame(secureChannel.EncryptApplicationMessage(plainMessage)[0].Buffer);

                        // this message is now encrypted
                        NetMQMessage        cipherMessage = socket.ReceiveMultipartMessage();
                        int                 offset2;
                        List <NetMQMessage> sslMessages2;
                        secureChannel.ResolveRecordLayer(cipherMessage.Last.Buffer, out offset2, out sslMessages2);
                        // decrypting the message
                        plainMessage = secureChannel.DecryptApplicationMessage(sslMessages2[0]);
                        System.Console.WriteLine(plainMessage.First.ConvertToString());
                    }
                    // encrypting the message and sending it over the socket
                }
            }
        }
        private void OnHTTPResponse(IAsyncResult result)
        {
            AsyncHttpResponse state = (AsyncHttpResponse)result.AsyncState;
            var success             = false;

            try
            {
                state.Request.EndGetResponse(result);
                success = true;
            }
            catch (WebException)
            {
                if (state.AssociatedAccount.Protocol == "https")
                {
                    // try to fetch certificate
                    try
                    {
                        var tls = new TLSHandshake();
                        tls.SetServerNameExtension(state.AssociatedAccount.Hostname);
                        var socket = new StreamSocket();
                        socket.Connect(state.AssociatedAccount.Hostname, TLSHandshake.TLS_HTTP_PORT);
                        socket.Write(tls.CreateClientHello());

                        DateTime startTime = DateTime.Now;
                        while (true)
                        {
                            var data = socket.Read();
                            if (data.Length > 0)
                            {
                                var cert = tls.FindPacket(data, TLSHandshake.TLS_HANDSHAKE_CERTIFICATE);
                                if (cert.Length > 0)
                                {
                                    var details = tls.GetCertificateDetails(cert);
                                    if (details.Count > 0)
                                    {
                                        var certDetails = details[0];
                                        if (certDetails.ContainsKey("CN"))
                                        {
                                            Dispatcher.BeginInvoke(() =>
                                            {
                                                MessageBox.Show("EditAccountPage_Connection_Rejected".Translate(state.AssociatedAccount.Hostname, certDetails["CN"], certDetails["ValidAfter"], certDetails["ValidTo"]), "EditAccountPage_Connection_Rejected_Caption".Translate(), MessageBoxButton.OK);
                                                overlayFadeOut.Begin();
                                            });
                                            return;
                                        }
                                    }
                                    break;
                                }
                            }

                            if (DateTime.Now.Subtract(startTime).TotalSeconds > 5)
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception)
                    {
                        // Host not reachable, no SSL host or TLS version not supported
                    }
                }
            }
            catch (Exception)
            {
                // HTTPWebRequest has failed
            }

            Dispatcher.BeginInvoke(() =>
            {
                if (success)
                {
                    overlayFadeOut.Begin();
                    StoreAccount(state.AssociatedAccount);
                }
                else
                {
                    overlayFadeOut.Begin();
                    OnConnectFailed(state.AssociatedAccount);
                }
            });
        }
Esempio n. 7
0
        /// <summary>
        /// Establishes a connection to the specified IMAP server.
        /// </summary>
        /// <remarks>
        /// <para>Establishes a connection to an IMAP or IMAP/S server. If the schema
        /// in the uri is "imap", a clear-text connection is made and defaults to using
        /// port 143 if no port is specified in the URI. However, if the schema in the
        /// uri is "imaps", an SSL connection is made using the
        /// <see cref="ClientCertificates"/> and defaults to port 993 unless a port
        /// is specified in the URI.</para>
        /// <para>It should be noted that when using a clear-text IMAP connection,
        /// if the server advertizes support for the STARTTLS extension, the client
        /// will automatically switch into TLS mode before authenticating unless the
        /// <paramref name="uri"/> contains a query string to disable it.</para>
        /// <para>If the IMAP server advertizes the COMPRESS extension and either does not
        /// support the STARTTLS extension or the <paramref name="uri"/> explicitly disabled
        /// the use of the STARTTLS extension, then the client will automatically opt into
        /// using a compressed data connection to optimize bandwidth usage unless the
        /// <paramref name="uri"/> contains a query string to explicitly disable it.</para>
        /// <para>If a successful connection is made, the <see cref="AuthenticationMechanisms"/>
        /// and <see cref="Capabilities"/> properties will be populated.</para>
        /// </remarks>
        /// <param name="uri">The server URI. The <see cref="System.Uri.Scheme"/> should either
        /// be "imap" to make a clear-text connection or "imaps" to make an SSL connection.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// The <paramref name="uri"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// The <paramref name="uri"/> is not an absolute URI.
        /// </exception>
        /// <exception cref="System.ObjectDisposedException">
        /// The <see cref="ImapClient"/> has been disposed.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// The <see cref="ImapClient"/> is already connected.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="ImapProtocolException">
        /// An IMAP protocol error occurred.
        /// </exception>
        public void Connect(Uri uri, CancellationToken cancellationToken)
        {
            CheckDisposed();

            if (uri == null)
            {
                throw new ArgumentNullException("uri");
            }

            if (!uri.IsAbsoluteUri)
            {
                throw new ArgumentException("The uri must be absolute.", "uri");
            }

            if (IsConnected)
            {
                throw new InvalidOperationException("The ImapClient is already connected.");
            }

            var    imaps = uri.Scheme.ToLowerInvariant() == "imaps";
            var    port  = uri.Port > 0 ? uri.Port : (imaps ? 993 : 143);
            var    query = uri.ParsedQuery();
            Stream stream;
            string value;

            var starttls = !imaps && (!query.TryGetValue("starttls", out value) || Convert.ToBoolean(value));
            var compress = !imaps && (!query.TryGetValue("compress", out value) || Convert.ToBoolean(value));

#if !NETFX_CORE
            var    ipAddresses = Dns.GetHostAddresses(uri.DnsSafeHost);
            Socket socket      = null;

            for (int i = 0; i < ipAddresses.Length; i++)
            {
                socket = new Socket(ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                cancellationToken.ThrowIfCancellationRequested();

                try {
                    socket.Connect(ipAddresses[i], port);
                    break;
                } catch {
                    if (i + 1 == ipAddresses.Length)
                    {
                        throw;
                    }
                }
            }

            if (imaps)
            {
                var ssl = new SslStream(new NetworkStream(socket, true), false, ValidateRemoteCertificate);
                ssl.AuthenticateAsClient(uri.Host, ClientCertificates, SslProtocols.Default, true);
                stream = ssl;
            }
            else
            {
                stream = new NetworkStream(socket, true);
            }
#else
            socket = new StreamSocket();

            cancellationToken.ThrowIfCancellationRequested();
            socket.ConnectAsync(new HostName(uri.DnsSafeHost), port.ToString(), imaps ? SocketProtectionLevel.Tls12 : SocketProtectionLevel.PlainSocket)
            .AsTask(cancellationToken)
            .GetAwaiter()
            .GetResult();

            stream = new DuplexStream(socket.InputStream.AsStreamForRead(), socket.OutputStream.AsStreamForWrite());
#endif
            host = uri.Host;

            logger.LogConnect(uri);

            engine.Connect(new ImapStream(stream, logger), cancellationToken);

            // Only query the CAPABILITIES if the greeting didn't include them.
            if (engine.CapabilitiesVersion == 0)
            {
                engine.QueryCapabilities(cancellationToken);
            }

            if (starttls && (engine.Capabilities & ImapCapabilities.StartTLS) != 0)
            {
                var ic = engine.QueueCommand(cancellationToken, null, "STARTTLS\r\n");

                engine.Wait(ic);

                if (ic.Result == ImapCommandResult.Ok)
                {
#if !NETFX_CORE
                    var tls = new SslStream(stream, false, ValidateRemoteCertificate);
                    tls.AuthenticateAsClient(uri.Host, ClientCertificates, SslProtocols.Tls, true);
                    engine.Stream.Stream = tls;
#else
                    socket.UpgradeToSslAsync(SocketProtectionLevel.Tls12, new HostName(uri.DnsSafeHost))
                    .AsTask(cancellationToken)
                    .GetAwaiter()
                    .GetResult();
#endif

                    // Query the CAPABILITIES again if the server did not include an
                    // untagged CAPABILITIES response to the STARTTLS command.
                    if (engine.CapabilitiesVersion == 1)
                    {
                        engine.QueryCapabilities(cancellationToken);
                    }
                }
            }
            else if (compress && (engine.Capabilities & ImapCapabilities.Compress) != 0)
            {
                var ic = engine.QueueCommand(cancellationToken, null, "COMPRESS DEFLATE\r\n");

                engine.Wait(ic);

                if (ic.Result == ImapCommandResult.Ok)
                {
                    var unzip = new DeflateStream(stream, CompressionMode.Decompress);
                    var zip   = new DeflateStream(stream, CompressionMode.Compress);

                    engine.Stream.Stream = new DuplexStream(unzip, zip);

                    // Query the CAPABILITIES again if the server did not include an
                    // untagged CAPABILITIES response to the COMPRESS command.
                    if (engine.CapabilitiesVersion == 1)
                    {
                        engine.QueryCapabilities(cancellationToken);
                    }
                }
            }
        }