public override void Open(NpgsqlConnector context) { try { IPAddress[] ips = ResolveIPHost(context.Host); Socket socket = null; // try every ip address of the given hostname, use the first reachable one foreach (IPAddress ip in ips) { IPEndPoint ep = new IPEndPoint(ip, context.Port); socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { IAsyncResult result = socket.BeginConnect(ep, null, null); if (!result.AsyncWaitHandle.WaitOne(context.ConnectionTimeout * 1000, true)) { socket.Close(); throw new Exception("Connection establishment timeout. Increase Timeout value in ConnectionString."); } socket.EndConnect(result); // connect was successful, leave the loop break; } catch (Exception) { socket.Close(); } } if (socket == null || !socket.Connected) { throw new Exception(string.Format("Failed to establish a connection to '{0}'.", context.Host)); } Stream stream = new NpgsqlNetworkStream(context, socket, true); // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer)) { PGUtil.WriteInt32(stream, 8); PGUtil.WriteInt32(stream, 80877103); // Receive response Char response = (Char)stream.ReadByte(); if (response == 'S') { //create empty collection X509CertificateCollection clientCertificates = new X509CertificateCollection(); //trigger the callback to fetch some certificates context.DefaultProvideClientCertificatesCallback(clientCertificates); stream = new SslClientStream( stream, context.Host, true, SecurityProtocolType.Default, clientCertificates); ((SslClientStream)stream).ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback); ((SslClientStream)stream).ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback); ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback); } else if (context.SslMode == SslMode.Require) { throw new InvalidOperationException("Ssl connection requested. No Ssl enabled connection from this host is configured."); } } context.Stream = new NpgsqlBufferedStream(stream); context.Socket = socket; ChangeState(context, NpgsqlConnectedState.Instance); } //FIXME: Exceptions that come from what we are handling should be wrapped - e.g. an error connecting to //the server should definitely be presented to the uesr as an NpgsqlError. Exceptions from userland should //be passed untouched - e.g. ThreadAbortException because the user started this in a thread they created and //then aborted should be passed through. //Are there any others that should be pass through? Alternatively, are there a finite number that should //be wrapped? catch (ThreadAbortException) { throw; } catch (Exception e) { throw new NpgsqlException(e.Message, e); } }
public override void Open(NpgsqlConnector context) { try { IPAddress[] ips = ResolveIPHost(context.Host); Socket socket = null; // try every ip address of the given hostname, use the first reachable one foreach (IPAddress ip in ips) { IPEndPoint ep = new IPEndPoint(ip, context.Port); socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { IAsyncResult result = socket.BeginConnect(ep, null, null); if (!result.AsyncWaitHandle.WaitOne(context.ConnectionTimeout * 1000, true)) { socket.Close(); throw new Exception(resman.GetString("Exception_ConnectionTimeout")); } socket.EndConnect(result); // connect was successful, leave the loop break; } catch (Exception) { socket.Close(); } } if (socket == null || !socket.Connected) { throw new Exception(string.Format(resman.GetString("Exception_FailedConnection"), context.Host)); } Stream stream = new NpgsqlNetworkStream(context, socket, true); // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') { if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer)) { PGUtil.WriteInt32(stream, 8); PGUtil.WriteInt32(stream, 80877103); // Receive response Char response = (Char)stream.ReadByte(); if (response == 'S') { //create empty collection X509CertificateCollection clientCertificates = new X509CertificateCollection(); //trigger the callback to fetch some certificates context.DefaultProvideClientCertificatesCallback(clientCertificates); stream = new SslClientStream( stream, context.Host, true, SecurityProtocolType.Default, clientCertificates); ((SslClientStream)stream).ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback); ((SslClientStream)stream).ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback); ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback); } else if (context.SslMode == SslMode.Require) { throw new InvalidOperationException(resman.GetString("Exception_Ssl_RequestError")); } } context.Stream = new NpgsqlBufferedStream(stream); context.Socket = socket; ChangeState(context, NpgsqlConnectedState.Instance); } //FIXME: Exceptions that come from what we are handling should be wrapped - e.g. an error connecting to //the server should definitely be presented to the uesr as an NpgsqlError. Exceptions from userland should //be passed untouched - e.g. ThreadAbortException because the user started this in a thread they created and //then aborted should be passed through. //Are there any others that should be pass through? Alternatively, are there a finite number that should //be wrapped? catch (ThreadAbortException) { throw; } catch (Exception e) { throw new NpgsqlException(e.Message, e); } }