Esempio n. 1
0
        /// <summary>
        /// Negotiates compression capabilities with the server.
        /// </summary>
        /// <param name="serverSupportedAlgorithms">An array containing the compression algorithms supported by the server.</param>
        /// <param name="clientAgainstUserAlgorithms">An array containing the compression algorithms given by user/client.</param>
        private Dictionary <string, object> NegotiateCompression(string[] serverSupportedAlgorithms, string[] clientAgainstUserAlgorithms)
        {
            if (serverSupportedAlgorithms == null || serverSupportedAlgorithms.Length == 0)
            {
                if (Settings.Compression == CompressionType.Required && clientAgainstUserAlgorithms.Length > 0)
                {
                    throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed);
                }
                return(null);
            }

            // If server and client don't have matching compression algorithms either log a warning message
            // or raise an exception based on the selected compression type.
            XCompressionController.LoadLibzstdLibrary();
            if (!clientAgainstUserAlgorithms.Any(element => serverSupportedAlgorithms.Contains(element)))
            {
                if (Settings.Compression == CompressionType.Preferred)
                {
                    MySqlTrace.LogWarning(-1, ResourcesX.CompressionAlgorithmNegotiationFailed);
                    return(null);
                }
                else if (Settings.Compression == CompressionType.Required)
                {
                    throw new NotSupportedException(ResourcesX.CompressionAlgorithmNegotiationFailed);
                }
            }

            string negotiatedAlgorithm = null;

            for (int index = 0; index < clientAgainstUserAlgorithms.Length; index++)
            {
                if (!serverSupportedAlgorithms.Contains(clientAgainstUserAlgorithms[index]))
                {
                    continue;
                }

                negotiatedAlgorithm = clientAgainstUserAlgorithms[index];
                break;
            }

            if (negotiatedAlgorithm == null)
            {
                return(null);
            }

            // Create the compression capability object.
            var compressionCapabilities = new Dictionary <string, object>();

            compressionCapabilities.Add(XCompressionController.ALGORITHMS_SUBKEY, negotiatedAlgorithm);
            compressionCapabilities.Add(XCompressionController.SERVER_COMBINE_MIXED_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_COMBINE_MIXED_MESSAGES_VALUE);

            // TODO: For future use.
            //compressionCapabilities.Add(XCompressionController.SERVER_MAX_COMBINE_MESSAGES_SUBKEY, XCompressionController.DEFAULT_SERVER_MAX_COMBINE_MESSAGES_VALUE);

            return(compressionCapabilities);
        }
Esempio n. 2
0
        private void GetAndSetCapabilities()
        {
            protocol.GetServerCapabilities();
            var clientCapabilities = new Dictionary <string, object>();

            Mysqlx.Connection.Capability capability = null;

            // Validates TLS use.
            if (Settings.SslMode != MySqlSslMode.None)
            {
                capability = protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == "tls");
                if (capability != null)
                {
                    serverSupportsTls = true;
                    clientCapabilities.Add("tls", "1");
                }
            }

            // Set connection-attributes.
            if (Settings.ConnectionAttributes.ToLower() != "false")
            {
                clientCapabilities.Add("session_connect_attrs", GetConnectionAttributes(Settings.ConnectionAttributes));
            }

            // Set compression algorithm.
            if (Settings.Compression != CompressionType.Disabled)
            {
                capability = protocol.Capabilities.Capabilities_.FirstOrDefault(i => i.Name.ToLowerInvariant() == XCompressionController.COMPRESSION_KEY);

                // Raise error if client expects compression but server doesn't support it.
                if (Settings.Compression == CompressionType.Required && capability == null)
                {
                    throw new NotSupportedException(ResourcesX.CompressionNotSupportedByServer);
                }

                // Update capabilities with the compression algorithm negotiation if server supports compression.
                if (capability != null)
                {
                    var algorithmsDictionary = capability.Value.Obj.Fld.ToDictionary(
                        field => field.Key,
                        field => field.Value.Array.Value.ToDictionary(value => value.Scalar.VString.Value.ToStringUtf8().ToLowerInvariant()).Keys.ToList());

                    if (algorithmsDictionary.ContainsKey(XCompressionController.ALGORITHMS_SUBKEY))
                    {
                        var supportedCompressionAlgorithms = algorithmsDictionary[XCompressionController.ALGORITHMS_SUBKEY].ToList().ToArray();
                        VerifyDefaultOrder(ref supportedCompressionAlgorithms);
                        var userCompressionAlgorithms = NegotiateUserAgainstClientAlgorithms(Settings.CompressionAlgorithm);
                        var compressionCapabilities   = NegotiateCompression(supportedCompressionAlgorithms, userCompressionAlgorithms);
                        if (compressionCapabilities != null)
                        {
                            clientCapabilities.Add(XCompressionController.COMPRESSION_KEY, compressionCapabilities);
                            var compressionAlgorithm = compressionCapabilities.First().Value.ToString();
                            _readerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), false);
                            _writerCompressionController = new XCompressionController((CompressionAlgorithms)Enum.Parse(typeof(CompressionAlgorithms), compressionAlgorithm), true);
                            _reader = new XPacketReaderWriter(_stream, _readerCompressionController);
                            _writer = new XPacketReaderWriter(_stream, _writerCompressionController);
                        }
                    }
                }
            }

            try
            {
                protocol.SetCapabilities(clientCapabilities);
            }
            catch (MySqlException ex)
            {
                if (ex.Message == "Capability 'session_connect_attrs' doesn't exist")
                {
                    clientCapabilities.Remove("session_connect_attrs");
                }
                protocol.SetCapabilities(clientCapabilities);
            }
        }