/// <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); }
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); } }