public override void Open(NpgsqlConnector context, Int32 timeout) { try { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open"); IAsyncResult result; // Keep track of time remaining; Even though there may be multiple timeout-able calls, // this allows us to still respect the caller's timeout expectation. DateTime attemptStart; attemptStart = DateTime.Now; result = Dns.BeginGetHostAddresses(context.Host, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout, true)) { // Timeout was used up attempting the Dns lookup throw new TimeoutException(resman.GetString("Exception_DnsLookupTimeout")); } timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); IPAddress[] ips = Dns.EndGetHostAddresses(result); Socket socket = null; Exception lastSocketException = null; // try every ip address of the given hostname, use the first reachable one // make sure not to exceed the caller's timeout expectation by splitting the // time we have left between all the remaining ip's in the list. for (int i = 0; i < ips.Length; i++) { NpgsqlEventLog.LogMsg(resman, "Log_ConnectingTo", LogLevel.Debug, ips[i]); IPEndPoint ep = new IPEndPoint(ips[i], context.Port); socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); attemptStart = DateTime.Now; try { result = socket.BeginConnect(ep, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout / (ips.Length - i), true)) { throw new TimeoutException(resman.GetString("Exception_ConnectionTimeout")); } socket.EndConnect(result); // connect was successful, leave the loop break; } catch (Exception e) { NpgsqlEventLog.LogMsg(resman, "Log_FailedConnection", LogLevel.Normal, ips[i]); timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); lastSocketException = e; socket.Close(); socket = null; } } if (socket == null) { throw lastSocketException; } NpgsqlNetworkStream baseStream = new NpgsqlNetworkStream(socket, true); Stream sslStream = null; // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer)) { baseStream .WriteInt32(8) .WriteInt32(80877103); // Receive response Char response = (Char)baseStream.ReadByte(); if (response == 'S') { //create empty collection X509CertificateCollection clientCertificates = new X509CertificateCollection(); //trigger the callback to fetch some certificates context.DefaultProvideClientCertificatesCallback(clientCertificates); //if (context.UseMonoSsl) if (!NpgsqlConnector.UseSslStream) { SslClientStream sslStreamPriv; sslStreamPriv = new SslClientStream( baseStream, context.Host, true, SecurityProtocolType.Default, clientCertificates); sslStreamPriv.ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback); sslStreamPriv.ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback); sslStreamPriv.PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback); sslStream = sslStreamPriv; } else { SslStream sslStreamPriv; sslStreamPriv = new SslStream(baseStream, true, context.DefaultValidateRemoteCertificateCallback); sslStreamPriv.AuthenticateAsClient(context.Host, clientCertificates, System.Security.Authentication.SslProtocols.Default, false); sslStream = sslStreamPriv; } } else if (context.SslMode == SslMode.Require) { throw new InvalidOperationException(resman.GetString("Exception_Ssl_RequestError")); } } context.Socket = socket; context.BaseStream = baseStream; context.Stream = new BufferedStream(sslStream == null ? baseStream : sslStream, 8192); NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.Host, context.Port); ChangeState(context, NpgsqlConnectedState.Instance); } catch (Exception e) { throw new NpgsqlException(string.Format(resman.GetString("Exception_FailedConnection"), context.Host), e); } }
public void RawOpen(int timeout) { // Keep track of time remaining; Even though there may be multiple timeout-able calls, // this allows us to still respect the caller's timeout expectation. var attemptStart = DateTime.Now; var result = Dns.BeginGetHostAddresses(Host, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout, true)) { // Timeout was used up attempting the Dns lookup throw new TimeoutException(L10N.DnsLookupTimeout); } timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); var ips = Dns.EndGetHostAddresses(result); Socket socket = null; Exception lastSocketException = null; // try every ip address of the given hostname, use the first reachable one // make sure not to exceed the caller's timeout expectation by splitting the // time we have left between all the remaining ip's in the list. for (var i = 0; i < ips.Length; i++) { _log.Trace("Attempting to connect to " + ips[i]); var ep = new IPEndPoint(ips[i], Port); socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); attemptStart = DateTime.Now; try { result = socket.BeginConnect(ep, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout / (ips.Length - i), true)) { throw new TimeoutException(L10N.ConnectionTimeout); } socket.EndConnect(result); // connect was successful, leave the loop break; } catch (Exception e) { _log.Warn("Failed to connect to " + ips[i]); timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); lastSocketException = e; socket.Close(); socket = null; } } if (socket == null) { throw lastSocketException; } var baseStream = new NpgsqlNetworkStream(socket, true); Stream sslStream = null; // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (SSL || (SslMode == SslMode.Require) || (SslMode == SslMode.Prefer)) { baseStream .WriteInt32(8) .WriteInt32(80877103); // Receive response var response = (Char)baseStream.ReadByte(); if (response != 'S') { if (SslMode == SslMode.Require) { throw new InvalidOperationException(L10N.SslRequestError); } } else { //create empty collection var clientCertificates = new X509CertificateCollection(); //trigger the callback to fetch some certificates DefaultProvideClientCertificatesCallback(clientCertificates); //if (context.UseMonoSsl) if (!UseSslStream) { var sslStreamPriv = new SslClientStream(baseStream, Host, true, SecurityProtocolType.Default, clientCertificates) { ClientCertSelectionDelegate = DefaultCertificateSelectionCallback, ServerCertValidationDelegate = DefaultCertificateValidationCallback, PrivateKeyCertSelectionDelegate = DefaultPrivateKeySelectionCallback }; sslStream = sslStreamPriv; IsSecure = true; } else { var sslStreamPriv = new SslStream(baseStream, true, DefaultValidateRemoteCertificateCallback); sslStreamPriv.AuthenticateAsClient(Host, clientCertificates, System.Security.Authentication.SslProtocols.Default, false); sslStream = sslStreamPriv; IsSecure = true; } } } Socket = socket; BaseStream = baseStream; //Stream = new BufferedStream(sslStream ?? baseStream, 8192); Stream = BaseStream; Buffer = new NpgsqlBuffer(Stream, BufferSize, PGUtil.UTF8Encoding); _log.DebugFormat("Connected to {0}:{1 }", Host, Port); }
public override void Open(NpgsqlConnector context, Int32 timeout) { try { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open"); IAsyncResult result; // Keep track of time remaining; Even though there may be multiple timeout-able calls, // this allows us to still respect the caller's timeout expectation. DateTime attemptStart; attemptStart = DateTime.Now; result = Dns.BeginGetHostAddresses(context.Host, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout, true)) { // Timeout was used up attempting the Dns lookup throw new TimeoutException(resman.GetString("Exception_DnsLookupTimeout")); } timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); IPAddress[] ips = Dns.EndGetHostAddresses(result); Socket socket = null; Exception lastSocketException = null; // try every ip address of the given hostname, use the first reachable one // make sure not to exceed the caller's timeout expectation by splitting the // time we have left between all the remaining ip's in the list. for (int i = 0 ; i < ips.Length ; i++) { NpgsqlEventLog.LogMsg(resman, "Log_ConnectingTo", LogLevel.Debug, ips[i]); IPEndPoint ep = new IPEndPoint(ips[i], context.Port); socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); attemptStart = DateTime.Now; try { result = socket.BeginConnect(ep, null, null); if (!result.AsyncWaitHandle.WaitOne(timeout / (ips.Length - i), true)) { throw new TimeoutException(resman.GetString("Exception_ConnectionTimeout")); } socket.EndConnect(result); // connect was successful, leave the loop break; } catch (Exception e) { NpgsqlEventLog.LogMsg(resman, "Log_FailedConnection", LogLevel.Normal, ips[i]); timeout -= Convert.ToInt32((DateTime.Now - attemptStart).TotalMilliseconds); lastSocketException = e; socket.Close(); socket = null; } } if (socket == null) { throw lastSocketException; } NpgsqlNetworkStream baseStream = new NpgsqlNetworkStream(socket, true); Stream sslStream = null; // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer)) { baseStream .WriteInt32(8) .WriteInt32(80877103); // Receive response Char response = (Char) baseStream.ReadByte(); if (response == 'S') { //create empty collection X509CertificateCollection clientCertificates = new X509CertificateCollection(); //trigger the callback to fetch some certificates context.DefaultProvideClientCertificatesCallback(clientCertificates); if (context.UseMonoSsl) { SslClientStream sslStreamPriv; sslStreamPriv = new SslClientStream( baseStream, context.Host, true, SecurityProtocolType.Default, clientCertificates); sslStreamPriv.ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback); sslStreamPriv.ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback); sslStreamPriv.PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback); sslStream = sslStreamPriv; } else { SslStream sslStreamPriv; sslStreamPriv = new SslStream(baseStream, true, context.DefaultValidateRemoteCertificateCallback); sslStreamPriv.AuthenticateAsClient(context.Host, clientCertificates, System.Security.Authentication.SslProtocols.Default, false); sslStream = sslStreamPriv; } } else if (context.SslMode == SslMode.Require) { throw new InvalidOperationException(resman.GetString("Exception_Ssl_RequestError")); } } context.Socket = socket; context.BaseStream = baseStream; context.Stream = new BufferedStream(sslStream == null ? baseStream : sslStream, 8192); NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.Host, context.Port); ChangeState(context, NpgsqlConnectedState.Instance); } catch (Exception e) { throw new NpgsqlException(string.Format(resman.GetString("Exception_FailedConnection"), context.Host), e); } }