public async Task <IClusterNode> CreateAndConnectAsync(HostEndpoint endPoint, CancellationToken cancellationToken = default) { var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(endPoint.Host, endPoint.Port.GetValueOrDefault(), cancellationToken).ConfigureAwait(false); var clusterNode = new ClusterNode(_clusterContext, _connectionPoolFactory, _logger, _transcoder, _circuitBreaker, _saslMechanismFactory, _redactor, ipEndPoint) { BootstrapEndpoint = endPoint }; //ensure server calls are made to set the state await clusterNode.InitializeAsync().ConfigureAwait(false); return(clusterNode); }
private async Task <IList <IPEndPoint> > GetIpEndPointsAsync(BucketConfig config, CancellationToken cancellationToken) { var ipEndPoints = new List <IPEndPoint>(); foreach (var node in config.GetNodes().Where(p => p.IsKvNode)) { var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(node, cancellationToken); if (ipEndPoint == null) { throw new InvalidOperationException("IP endpoint lookup failed."); } ipEndPoints.Add(ipEndPoint); } return(ipEndPoints); }
public async Task <IClusterNode> CreateAndConnectAsync(HostEndpoint endPoint, BucketType bucketType, NodeAdapter?nodeAdapter, CancellationToken cancellationToken = default) { var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(endPoint.Host, endPoint.Port.GetValueOrDefault(), cancellationToken).ConfigureAwait(false); //for recording k/v latencies per request var valueRecorder = _meter.ValueRecorder(OuterRequestSpans.ServiceSpan.Kv.Name); var clusterNode = new ClusterNode(_clusterContext, _connectionPoolFactory, _logger, _operationBuilderPool, _circuitBreaker, _saslMechanismFactory, _redactor, ipEndPoint, bucketType, nodeAdapter, _tracer, valueRecorder) { BootstrapEndpoint = endPoint }; //ensure server calls are made to set the state await clusterNode.InitializeAsync().ConfigureAwait(false); return(clusterNode); }
private async Task <IList <IPEndPoint> > GetIpEndPointsAsync(BucketConfig config, CancellationToken cancellationToken) { var ipEndPoints = new List <IPEndPoint>(); foreach (var node in config.GetNodes().Where(p => p.IsKvNode)) { //log any alternate address mapping _logger.LogInformation(node.ToString()); var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(node, cancellationToken).ConfigureAwait(false); if (ipEndPoint == null) { throw new InvalidOperationException("IP endpoint lookup failed."); } ipEndPoints.Add(ipEndPoint); } return(ipEndPoints); }
private async IAsyncEnumerable <IPEndPoint> GetIpEndPointsAsync(IEnumerable <string> serverList, [EnumeratorCancellation] CancellationToken cancellationToken) { foreach (var server in serverList) { var(hostName, port) = HostEndpoint.Parse(server); if (port == null) { // Should not happen with data from BucketConfig ThrowHelper.ThrowInvalidOperationException("Server list is missing port numbers."); } var ipEndPoint = await _ipEndPointService.GetIpEndPointAsync(hostName, port.Value, cancellationToken) .ConfigureAwait(false); if (ipEndPoint == null) { ThrowHelper.ThrowArgumentException($"Unable to resolve '{server}'.", nameof(serverList)); } yield return(ipEndPoint); } }
public async Task <IConnection> CreateAndConnectAsync(HostEndpointWithPort hostEndpoint, CancellationToken cancellationToken = default) { if (_clusterOptions.IsCapella && !_clusterOptions.EffectiveEnableTls) { _multiplexLogger.LogWarning("TLS is required when connecting to Couchbase Capella. Please enable TLS by prefixing the connection string with \"couchbases://\" (note the final 's')."); } var endPoint = await _ipEndPointService.GetIpEndPointAsync(hostEndpoint.Host, hostEndpoint.Port, cancellationToken) .ConfigureAwait(false); if (endPoint is null) { throw new ConnectException($"Unable to resolve host '{hostEndpoint}'."); } var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { var connectTask = socket.ConnectAsync(endPoint); var whichTask = await Task .WhenAny(connectTask, Task.Delay(_clusterOptions.KvConnectTimeout, cancellationToken)) .ConfigureAwait(false); if (whichTask != connectTask) { // Was a timeout const int connectionTimedOut = 10060; throw new SocketException(connectionTimedOut); } } catch { socket.Dispose(); throw; } #if NETCOREAPP3_0_OR_GREATER _multiplexLogger.LogDebug("Setting TCP Keep-Alives using SocketOptions - enable keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}.", _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TryEnableKeepAlives(_clusterOptions.EnableTcpKeepAlives, (int)_clusterOptions.TcpKeepAliveTime.TotalSeconds, (int)_clusterOptions.TcpKeepAliveInterval.TotalSeconds, out string setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #else _multiplexLogger.LogDebug( "Setting TCP Keep-Alives using Socket.IOControl on {endpoint} - enable tcp keep-alives {EnableTcpKeepAlives}, time {TcpKeepAliveTime}, interval {TcpKeepAliveInterval}", endPoint, _clusterOptions.EnableTcpKeepAlives, _clusterOptions.TcpKeepAliveTime, _clusterOptions.TcpKeepAliveInterval); if (!socket.TrySetKeepAlives(_clusterOptions.EnableTcpKeepAlives, (uint)_clusterOptions.TcpKeepAliveTime.TotalMilliseconds, (uint)_clusterOptions.TcpKeepAliveInterval.TotalMilliseconds, out var setKeepAliveMessage) ) { _multiplexLogger.LogWarning(setKeepAliveMessage); } #endif if (_clusterOptions.EffectiveEnableTls) { //Check if were using x509 auth, if so fetch the certificates X509Certificate2Collection?certs = null; if (_clusterOptions.X509CertificateFactory != null) { certs = _clusterOptions.X509CertificateFactory.GetCertificates(); if (certs == null || certs.Count == 0) { throw new AuthenticationException( "No certificates matching the X509FindType and specified FindValue were found in the Certificate Store."); } if (_sslLogger.IsEnabled(LogLevel.Debug)) { foreach (var cert in certs) { _sslLogger.LogDebug("Cert sent {cert.FriendlyName} - Thumbprint {cert.Thumbprint}", cert.FriendlyName, cert.Thumbprint); } _sslLogger.LogDebug("Sending {certs.Count} certificates to the server.", certs.Count); } } //The endpoint we are connecting to var targetHost = _clusterOptions.ForceIpAsTargetHost ? endPoint.Address.ToString() : hostEndpoint.Host; //create the sslstream with appropriate authentication RemoteCertificateValidationCallback?certValidationCallback = _clusterOptions.KvCertificateCallbackValidation; if (certValidationCallback == null) { certValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { if (_clusterOptions.KvIgnoreRemoteCertificateNameMismatch && CertificateFactory.ValidatorWithIgnoreNameMismatch(sender, certificate, chain, sslPolicyErrors)) { return(true); } return(CertificateFactory.ValidateWithDefaultCertificates(sender, certificate, chain, sslPolicyErrors)); }; } var sslStream = new SslStream(new NetworkStream(socket, true), false, certValidationCallback); #if !NETCOREAPP3_1_OR_GREATER await sslStream.AuthenticateAsClientAsync(targetHost, certs, _clusterOptions.EnabledSslProtocols, _clusterOptions.EnableCertificateRevocation) .ConfigureAwait(false); #else SslClientAuthenticationOptions sslOptions = new SslClientAuthenticationOptions() { TargetHost = targetHost, ClientCertificates = certs, EnabledSslProtocols = _clusterOptions.EnabledSslProtocols, CertificateRevocationCheckMode = _clusterOptions.EnableCertificateRevocation ? X509RevocationMode.Online : X509RevocationMode.NoCheck }; if (_clusterOptions.EnabledTlsCipherSuites != null && _clusterOptions.EnabledTlsCipherSuites.Count > 0) { sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(_clusterOptions.EnabledTlsCipherSuites); } await sslStream.AuthenticateAsClientAsync(sslOptions) .ConfigureAwait(false); #endif var isSecure = sslStream.IsAuthenticated && sslStream.IsSigned && sslStream.IsEncrypted; _sslLogger.LogDebug("IsAuthenticated {0} on {1}", sslStream.IsAuthenticated, targetHost); _sslLogger.LogDebug("IsSigned {0} on {1}", sslStream.IsSigned, targetHost); _sslLogger.LogDebug("IsEncrypted {0} on {1}", sslStream.IsEncrypted, targetHost); //punt if we cannot successfully authenticate if (!isSecure) { throw new AuthenticationException($"The SSL/TLS connection could not be authenticated on [{targetHost}]."); } return(new SslConnection(sslStream, socket.LocalEndPoint !, socket.RemoteEndPoint !, _sslLogger, _multiplexLogger)); } return(new MultiplexingConnection(socket, _multiplexLogger)); }