Пример #1
0
        public override void WriteToStream(Stream output_stream)
        {
            PGUtil.WriteInt32(output_stream,
                              4 + 4 + 5 + (UTF8Encoding.GetByteCount(user_name) + 1) + 9 +
                              (UTF8Encoding.GetByteCount(database_name) + 1) + 10 + 4 + 1);

            PGUtil.WriteInt32(output_stream, 196608);
            // User name.
            PGUtil.WriteString("user", output_stream);
            // User name.
            PGUtil.WriteString(user_name, output_stream);
            // Database name.
            PGUtil.WriteString("database", output_stream);
            // Database name.
            PGUtil.WriteString(database_name, output_stream);
            // DateStyle.
            PGUtil.WriteString("DateStyle", output_stream);
            // DateStyle.
            PGUtil.WriteString("ISO", output_stream);

            output_stream.WriteByte(0);
            output_stream.Flush();
        }
Пример #2
0
 public override int DoSkip(int length)
 {
     return(PGUtil.SkipEscapedBytes(_stream, buffer, length, ref _remainingBytes));
 }
Пример #3
0
 public override int DoRead(byte[] output, int outputIdx, int length)
 {
     return(PGUtil.ReadEscapedBytes(_stream, buffer, output, length, ref _remainingBytes, outputIdx));
 }
Пример #4
0
 public override int DoSkip(int length)
 {
     return(PGUtil.SkipChars(_stream, length, ref _remainingBytes));
 }
Пример #5
0
 public override int DoRead(char[] output, int outputIdx, int length)
 {
     return(PGUtil.ReadChars(_stream, output, length, ref _remainingBytes, outputIdx));
 }
Пример #6
0
 public void Dispose()
 {
     PGUtil.EatStreamBytes(_stream, _remainingBytes);
 }
Пример #7
0
        // Logging related values
        //private static readonly String CLASSNAME = MethodBase.GetCurrentMethod().DeclaringType.Name;

        public override void WriteToStream(Stream outputStream)
        {
            outputStream.WriteByte((byte)FrontEndMessageCode.Flush);

            PGUtil.WriteInt32(outputStream, 4);
        }
Пример #8
0
 public NpgsqlBackEndKeyData(Stream stream, byte[] buffer)
 {
     PGUtil.EatShortStreamBytes(stream, 4);
     ProcessID = PGUtil.ReadInt32(stream, buffer);
     SecretKey = PGUtil.ReadInt32(stream, buffer);
 }
Пример #9
0
        // Logging related values
        //private static readonly String CLASSNAME = MethodBase.GetCurrentMethod().DeclaringType.Name;

        public static void Send(Stream stream)
        {
            stream.WriteByte((byte)FrontEndMessageCode.Sync);

            PGUtil.WriteInt32(stream, 4);
        }
Пример #10
0
        internal NpgsqlError(Stream stream, byte[] buffer, ByteBuffer queue)
        {
            // Check the messageLength value. If it is 1178686529, this would be the
            // "FATA" string, which would mean a protocol 2.0 error string.
            if (PGUtil.ReadInt32(stream, buffer) == 1178686529)
            {
                string[] v2Parts = ("FATA" + PGUtil.ReadString(stream, queue)).Split(new char[] { ':' }, 2);
                if (v2Parts.Length == 2)
                {
                    _severity = v2Parts[0].Trim();
                    _message  = v2Parts[1].Trim();
                }
                else
                {
                    _severity = string.Empty;
                    _message  = v2Parts[0].Trim();
                }
            }
            else
            {
                for (char field = (char)stream.ReadByte(); field != 0; field = (char)stream.ReadByte())
                {
                    switch (field)
                    {
                    case 'S':
                        _severity = PGUtil.ReadString(stream, queue);
                        break;

                    case 'C':
                        _code = PGUtil.ReadString(stream, queue);
                        break;

                    case 'M':
                        _message = PGUtil.ReadString(stream, queue);
                        break;

                    case 'D':
                        _detail = PGUtil.ReadString(stream, queue);
                        break;

                    case 'H':
                        _hint = PGUtil.ReadString(stream, queue);
                        break;

                    case 'P':
                        _position = PGUtil.ReadString(stream, queue);
                        break;

                    case 'p':
                        _internalPosition = PGUtil.ReadString(stream, queue);
                        break;

                    case 'q':
                        _internalQuery = PGUtil.ReadString(stream, queue);
                        break;

                    case 'W':
                        _where = PGUtil.ReadString(stream, queue);
                        break;

                    case 'F':
                        _file = PGUtil.ReadString(stream, queue);
                        break;

                    case 'L':
                        _line = PGUtil.ReadString(stream, queue);
                        break;

                    case 'R':
                        _routine = PGUtil.ReadString(stream, queue);
                        break;

                    case 's':
                        _schemaName = PGUtil.ReadString(stream, queue);
                        break;

                    case 't':
                        _tableName = PGUtil.ReadString(stream, queue);
                        break;

                    case 'c':
                        _columnName = PGUtil.ReadString(stream, queue);
                        break;

                    case 'd':
                        _datatypeName = PGUtil.ReadString(stream, queue);
                        break;

                    case 'n':
                        _constraintName = PGUtil.ReadString(stream, queue);
                        break;

                    default:
                        // Unknown error field; consume and discard.
                        PGUtil.ReadString(stream, queue);
                        break;
                    }
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Opens the physical connection to the server.
        /// </summary>
        /// <remarks>Usually called by the RequestConnector
        /// Method of the connection pool manager.</remarks>
        internal void Open()
        {
            ServerVersion = null;
            // If Connection.ConnectionString specifies a protocol version, we will
            // not try to fall back to version 2 on failure.

            // Reset state to initialize new connector in pool.
            CurrentState = NpgsqlClosedState.Instance;

            // Get a raw connection, possibly SSL...
            CurrentState.Open(this);
            try
            {
                // Establish protocol communication and handle authentication...
                CurrentState.Startup(this);
            }
            catch (NpgsqlException)
            {
                throw;
            }

            // Change the state of connection to open and ready.
            State        = ConnectionState.Open;
            CurrentState = NpgsqlReadyState.Instance;

            // Fall back to the old way, SELECT VERSION().
            // This should not happen for protocol version 3+.
            if (ServerVersion == null)
            {
                using (NpgsqlCommand command = new NpgsqlCommand("set DATESTYLE TO ISO;select version();", this))
                {
                    ServerVersion = new Version(PGUtil.ExtractServerVersion((string)command.ExecuteScalar()));
                }
            }

            StringBuilder sbInit = new StringBuilder();

            // Adjust client encoding.
            NpgsqlParameterStatus clientEncodingParam = null;

            if (!ServerParameters.TryGetValue("client_encoding", out clientEncodingParam) ||
                !string.Equals(clientEncodingParam.ParameterValue, "UTF8", StringComparison.OrdinalIgnoreCase) && !string.Equals(clientEncodingParam.ParameterValue, "UNICODE", StringComparison.OrdinalIgnoreCase))
            {
                sbInit.AppendLine("SET CLIENT_ENCODING TO UTF8;");
            }

            if (!string.IsNullOrEmpty(settings.SearchPath))
            {
                // TODO: Add proper message when finding a semicolon in search_path.
                // This semicolon could lead to a sql injection security hole as someone could write in connection string:
                // searchpath=public;delete from table; and it would be executed.

                if (settings.SearchPath.Contains(";"))
                {
                    throw new InvalidOperationException();
                }

                sbInit.AppendLine("SET SEARCH_PATH=" + settings.SearchPath + ";");
            }

            if (!string.IsNullOrEmpty(settings.ApplicationName))
            {
                if (!SupportsApplicationName)
                {
                    //TODO
                    //throw new InvalidOperationException(resman.GetString("Exception_ApplicationNameNotSupported"));
                    throw new InvalidOperationException("ApplicationName not supported.");
                }

                if (settings.ApplicationName.Contains(";"))
                {
                    throw new InvalidOperationException();
                }

                sbInit.AppendLine("SET APPLICATION_NAME='" + settings.ApplicationName.Replace('\'', '-') + "';");
            }

            /*
             * Try to set SSL negotiation to 0. As of 2010-03-29, recent problems in SSL library implementations made
             * postgresql to add a parameter to set a value when to do this renegotiation or 0 to disable it.
             * Currently, Npgsql has a problem with renegotiation so, we are trying to disable it here.
             * This only works on postgresql servers where the ssl renegotiation settings is supported of course.
             * See http://lists.pgfoundry.org/pipermail/npgsql-devel/2010-February/001065.html for more information.
             */
            sbInit.AppendLine("SET ssl_renegotiation_limit=0;");

            /*
             * Set precision digits to maximum value possible. For postgresql before 9 it was 2, after that, it is 3.
             * This way, we set first to 2 and then to 3. If there is an error because of 3, it will have been set to 2 at least.
             * Check bug report #1010992 for more information.
             */
            sbInit.AppendLine("SET extra_float_digits=3;");
            try
            {
                new NpgsqlCommand(sbInit.ToString(), this).ExecuteBlind();
            }
            catch
            {
                foreach (var line in sbInit.ToString().Split(Environment.NewLine.ToCharArray()))
                {
                    try
                    {
                        if (line.Length > 0)
                        {
                            new NpgsqlCommand(line, this).ExecuteBlind();
                        }
                    }
                    catch { }
                }
            }

            // Make a shallow copy of the type mapping that the connector will own.
            // It is possible that the connector may add types to its private
            // mapping that will not be valid to another connector, even
            // if connected to the same backend version.
            _oidToNameMapping = NpgsqlTypesHelper.CreateAndLoadInitialTypesMapping(this).Clone();

            ProcessServerVersion();

            // The connector is now fully initialized. Beyond this point, it is
            // safe to release it back to the pool rather than closing it.
            IsInitialized = true;
        }
Пример #12
0
        protected override object ReadNext()
        {
            int fieldSize = GetThisFieldCount();

            if (fieldSize >= _messageSize)
            {
                AbandonShip();
            }
            _nextFieldSize = null;

            // Check if this field is null
            if (fieldSize == -1)             // Null value
            {
                return(DBNull.Value);
            }

            NpgsqlRowDescription.FieldData field_descr = FieldData;

            if (fieldSize >= 32768)
            {
                return(ReadLargeObject(field_descr, fieldSize));
            }

            try
            {
                if (field_descr.FormatCode == FormatCode.Text)
                {
                    PGUtil.CheckedStreamRead(Stream, bytes.Large, 0, fieldSize);
                    var str = UTF8Encoding.GetString(bytes.Large, 0, fieldSize);
                    return
                        (NpgsqlTypesHelper.ConvertBackendStringToSystemType(
                             field_descr.TypeInfo,
                             str,
                             field_descr.TypeSize,
                             field_descr.TypeModifier));
                }
                else
                {
                    var buffer = new byte[fieldSize];
                    PGUtil.CheckedStreamRead(Stream, buffer, 0, fieldSize);
                    return
                        (NpgsqlTypesHelper.ConvertBackendBytesToSystemType(
                             field_descr.TypeInfo,
                             buffer,
                             fieldSize,
                             field_descr.TypeModifier));
                }
            }
            catch (IOException)
            {
                throw;
            }
            catch (InvalidCastException ice)
            {
                return(ice);
            }
            catch (Exception ex)
            {
                return(new InvalidCastException(ex.Message, ex));
            }
        }
Пример #13
0
 private int GetThisFieldCount()
 {
     return((_nextFieldSize = _nextFieldSize ?? PGUtil.ReadInt32(Stream, buffer)).Value);
 }
Пример #14
0
        protected IEnumerable <IServerResponseObject> ProcessBackendResponses_Ver_3(NpgsqlConnector context)
        {
            try
            {
                Stream         stream   = context.Stream;
                NpgsqlMediator mediator = context.Mediator;

                var buffer = context.TmpBuffer;
                var queue  = context.ArrayBuffer;
                List <NpgsqlError> errors = null;

                for (; ;)
                {
                    // Check the first Byte of response.
                    BackEndMessageCode message = (BackEndMessageCode)stream.ReadByte();
                    switch (message)
                    {
                    case BackEndMessageCode.ErrorResponse:

                        NpgsqlError error = new NpgsqlError(stream, buffer, queue);
                        error.ErrorSql = mediator.SqlSent;

                        if (errors == null)
                        {
                            errors = new List <NpgsqlError>();
                        }
                        errors.Add(error);

                        // Return imediately if it is in the startup state or connected state as
                        // there is no more messages to consume.
                        // Possible error in the NpgsqlStartupState:
                        //        Invalid password.
                        // Possible error in the NpgsqlConnectedState:
                        //        No pg_hba.conf configured.

                        if (!context.RequireReadyForQuery)
                        {
                            throw new NpgsqlException(errors);
                        }

                        break;

                    case BackEndMessageCode.AuthenticationRequest:

                        // Get the length in case we're getting AuthenticationGSSContinue
                        int authDataLength = PGUtil.ReadInt32(stream, buffer) - 8;

                        AuthenticationRequestType authType = (AuthenticationRequestType)PGUtil.ReadInt32(stream, buffer);
                        switch (authType)
                        {
                        case AuthenticationRequestType.AuthenticationOk:
                            break;

                        case AuthenticationRequestType.AuthenticationClearTextPassword:
                            // Send the PasswordPacket.

                            ChangeState(context, NpgsqlStartupState.Instance);
                            context.Authenticate(context.Password);

                            break;

                        case AuthenticationRequestType.AuthenticationMD5Password:
                            // Now do the "MD5-Thing"
                            // for this the Password has to be:
                            // 1. md5-hashed with the username as salt
                            // 2. md5-hashed again with the salt we get from the backend


                            MD5 md5 = MD5.Create();


                            // 1.
                            byte[] passwd       = context.Password;
                            byte[] saltUserName = ENCODING_UTF8.GetBytes(context.UserName);

                            byte[] crypt_buf = new byte[passwd.Length + saltUserName.Length];

                            passwd.CopyTo(crypt_buf, 0);
                            saltUserName.CopyTo(crypt_buf, passwd.Length);


                            StringBuilder sb         = new StringBuilder();
                            byte[]        hashResult = md5.ComputeHash(crypt_buf);
                            foreach (byte b in hashResult)
                            {
                                sb.Append(b.ToString("x2"));
                            }


                            String prehash = sb.ToString();

                            byte[] prehashbytes = ENCODING_UTF8.GetBytes(prehash);
                            crypt_buf = new byte[prehashbytes.Length + 4];


                            stream.Read(crypt_buf, prehashbytes.Length, 4);
                            // Send the PasswordPacket.
                            ChangeState(context, NpgsqlStartupState.Instance);


                            // 2.
                            prehashbytes.CopyTo(crypt_buf, 0);

                            sb         = new StringBuilder("md5");                                     // This is needed as the backend expects md5 result starts with "md5"
                            hashResult = md5.ComputeHash(crypt_buf);
                            foreach (byte b in hashResult)
                            {
                                sb.Append(b.ToString("x2"));
                            }

                            context.Authenticate(ENCODING_UTF8.GetBytes(sb.ToString()));

                            break;

#if WINDOWS && UNMANAGED
                        case AuthenticationRequestType.AuthenticationSSPI:
                        {
                            if (context.IntegratedSecurity)
                            {
                                // For SSPI we have to get the IP-Address (hostname doesn't work)
                                string ipAddressString = ((IPEndPoint)context.Socket.RemoteEndPoint).Address.ToString();
                                context.SSPI = new SSPIHandler(ipAddressString, "POSTGRES");
                                ChangeState(context, NpgsqlStartupState.Instance);
                                context.Authenticate(context.SSPI.Continue(null));
                                break;
                            }
                            else
                            {
                                // TODO: correct exception
                                throw new Exception();
                            }
                        }


                        case AuthenticationRequestType.AuthenticationGSSContinue:
                        {
                            byte[] authData = new byte[authDataLength];
                            PGUtil.CheckedStreamRead(stream, authData, 0, authDataLength);
                            byte[] passwd_read = context.SSPI.Continue(authData);
                            if (passwd_read.Length != 0)
                            {
                                context.Authenticate(passwd_read);
                            }
                            break;
                        }
#endif

                        default:
                            // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
                            if (errors == null)
                            {
                                errors = new List <NpgsqlError>();
                            }
                            errors.Add(
                                new NpgsqlError(String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
                            throw new NpgsqlException(errors);
                        }
                        break;

                    case BackEndMessageCode.RowDescription:
                        yield return(context.RowDescription());

                        break;

                    case BackEndMessageCode.ParameterDescription:

                        // Do nothing,for instance,  just read...
                        int length   = PGUtil.ReadInt32(stream, buffer);
                        int nb_param = PGUtil.ReadInt16(stream, buffer);
                        //WTF
                        for (int i = 0; i < nb_param; i++)
                        {
                            int typeoid = PGUtil.ReadInt32(stream, buffer);
                        }

                        break;

                    case BackEndMessageCode.DataRow:
                        yield return(context.NextRow());

                        break;

                    case BackEndMessageCode.ReadyForQuery:

                        // Possible status bytes returned:
                        //   I = Idle (no transaction active).
                        //   T = In transaction, ready for more.
                        //   E = Error in transaction, queries will fail until transaction aborted.
                        // Just eat the status byte, we have no use for it at this time.
                        PGUtil.ReadInt32(stream, buffer);
                        stream.ReadByte();

                        ChangeState(context, NpgsqlReadyState.Instance);

                        if (errors != null)
                        {
                            throw new NpgsqlException(errors);
                        }

                        yield break;

                    case BackEndMessageCode.BackendKeyData:
                        // BackendKeyData message.
                        NpgsqlBackEndKeyData backend_keydata = new NpgsqlBackEndKeyData(stream, buffer);
                        context.BackEndKeyData = backend_keydata;


                        // Wait for ReadForQuery message
                        break;

                    case BackEndMessageCode.NoticeResponse:
                        // Notices and errors are identical except that we
                        // just throw notices away completely ignored.
                        context.FireNotice(new NpgsqlError(stream, buffer, queue));
                        break;

                    case BackEndMessageCode.CompletedResponse:
                        PGUtil.ReadInt32(stream, buffer);
                        yield return(new CompletedResponse(stream, queue));

                        break;

                    case BackEndMessageCode.ParseComplete:
                        // Just read up the message length.
                        PGUtil.ReadInt32(stream, buffer);
                        yield break;

                    case BackEndMessageCode.BindComplete:
                        // Just read up the message length.
                        PGUtil.ReadInt32(stream, buffer);
                        yield break;

                    case BackEndMessageCode.EmptyQueryResponse:
                        PGUtil.ReadInt32(stream, buffer);
                        break;

                    case BackEndMessageCode.NotificationResponse:
                        // Eat the length
                        PGUtil.ReadInt32(stream, buffer);
                        context.FireNotification(new NpgsqlNotificationEventArgs(stream, true, buffer, queue));
                        if (context.IsNotificationThreadRunning)
                        {
                            yield break;
                        }
                        break;

                    case BackEndMessageCode.ParameterStatus:
                        NpgsqlParameterStatus parameterStatus = new NpgsqlParameterStatus(stream, queue);

                        context.AddParameterStatus(parameterStatus);

                        if (parameterStatus.Parameter == "server_version")
                        {
                            // Deal with this here so that if there are
                            // changes in a future backend version, we can handle it here in the
                            // protocol handler and leave everybody else put of it.
                            string versionString = parameterStatus.ParameterValue.Trim();
                            for (int idx = 0; idx != versionString.Length; ++idx)
                            {
                                char c = parameterStatus.ParameterValue[idx];
                                if (!char.IsDigit(c) && c != '.')
                                {
                                    versionString = versionString.Substring(0, idx);
                                    break;
                                }
                            }
                            context.ServerVersion = new Version(versionString);
                        }
                        break;

                    case BackEndMessageCode.NoData:
                        // This nodata message may be generated by prepare commands issued with queries which doesn't return rows
                        // for example insert, update or delete.
                        // Just eat the message.
                        PGUtil.ReadInt32(stream, buffer);
                        break;

                    case BackEndMessageCode.CopyInResponse:
                        // Enter COPY sub protocol and start pushing data to server
                        ChangeState(context, NpgsqlCopyInState.Instance);
                        PGUtil.ReadInt32(stream, buffer);                                 // length redundant
                        context.CurrentState.StartCopy(context, ReadCopyHeader(stream, buffer));
                        yield break;
                    // Either StartCopy called us again to finish the operation or control should be passed for user to feed copy data

                    case BackEndMessageCode.CopyOutResponse:
                        // Enter COPY sub protocol and start pulling data from server
                        ChangeState(context, NpgsqlCopyOutState.Instance);
                        PGUtil.ReadInt32(stream, buffer);                                 // length redundant
                        context.CurrentState.StartCopy(context, ReadCopyHeader(stream, buffer));
                        yield break;
                    // Either StartCopy called us again to finish the operation or control should be passed for user to feed copy data

                    case BackEndMessageCode.CopyData:
                        Int32  len = PGUtil.ReadInt32(stream, buffer) - 4;
                        byte[] buf = new byte[len];
                        PGUtil.ReadBytes(stream, buf, 0, len);
                        context.Mediator.ReceivedCopyData = buf;
                        yield break;                                 // read data from server one chunk at a time while staying in copy operation mode

                    case BackEndMessageCode.CopyDone:
                        PGUtil.ReadInt32(stream, buffer);                                 // CopyDone can not have content so this is always 4
                        // This will be followed by normal CommandComplete + ReadyForQuery so no op needed
                        break;

                    case BackEndMessageCode.IO_ERROR:
                        // Connection broken. Mono returns -1 instead of throwing an exception as ms.net does.
                        throw new IOException();

                    default:
                        // This could mean a number of things
                        //   We've gotten out of sync with the backend?
                        //   We need to implement this type?
                        //   Backend has gone insane?
                        // FIXME
                        // what exception should we really throw here?
                        throw new NotSupportedException(String.Format("Backend sent unrecognized response type: {0}", (Char)message));
                    }
                }
            }
            finally
            {
                context.RequireReadyForQuery = true;
            }
        }
Пример #15
0
        public override void WriteToStream(Stream outputStream)
        {
            Int32 messageLength = 4 + UTF8Encoding.GetByteCount(_portalName) + 1 +
                                  UTF8Encoding.GetByteCount(_preparedStatementName) + 1 + 2 + (_parameterFormatCodes.Length * 2) +
                                  2;


            // Get size of parameter values.
            Int32 i;

            if (_parameterValues != null)
            {
                for (i = 0; i < _parameterValues.Length; i++)
                {
                    messageLength += 4;
                    if (_parameterValues[i] != null)
                    {
                        if (((_parameterFormatCodes.Length == 1) && (_parameterFormatCodes[0] == (Int16)FormatCode.Binary)) ||
                            ((_parameterFormatCodes.Length != 1) && (_parameterFormatCodes[i] == (Int16)FormatCode.Binary)))
                        {
                            messageLength += ((Byte[])_parameterValues[i]).Length;
                        }
                        else
                        {
                            messageLength += UTF8Encoding.GetByteCount((String)_parameterValues[i]);
                        }
                    }
                }
            }

            messageLength += 2 + (_resultFormatCodes.Length * 2);


            outputStream.WriteByte((byte)FrontEndMessageCode.Bind);

            PGUtil.WriteInt32(outputStream, messageLength);
            PGUtil.WriteString(_portalName, outputStream);
            PGUtil.WriteString(_preparedStatementName, outputStream);

            PGUtil.WriteInt16(outputStream, (Int16)_parameterFormatCodes.Length);

            for (i = 0; i < _parameterFormatCodes.Length; i++)
            {
                PGUtil.WriteInt16(outputStream, _parameterFormatCodes[i]);
            }

            if (_parameterValues != null)
            {
                PGUtil.WriteInt16(outputStream, (Int16)_parameterValues.Length);

                for (i = 0; i < _parameterValues.Length; i++)
                {
                    if (((_parameterFormatCodes.Length == 1) && (_parameterFormatCodes[0] == (Int16)FormatCode.Binary)) ||
                        ((_parameterFormatCodes.Length != 1) && (_parameterFormatCodes[i] == (Int16)FormatCode.Binary)))
                    {
                        Byte[] parameterValue = (Byte[])_parameterValues[i];
                        if (parameterValue == null)
                        {
                            PGUtil.WriteInt32(outputStream, -1);
                        }
                        else
                        {
                            PGUtil.WriteInt32(outputStream, parameterValue.Length);
                            outputStream.Write(parameterValue, 0, parameterValue.Length);
                        }
                    }
                    else
                    {
                        if ((_parameterValues[i] == null))
                        {
                            PGUtil.WriteInt32(outputStream, -1);
                        }
                        else
                        {
                            Byte[] parameterValueBytes = UTF8Encoding.GetBytes((String)_parameterValues[i]);
                            PGUtil.WriteInt32(outputStream, parameterValueBytes.Length);
                            outputStream.Write(parameterValueBytes, 0, parameterValueBytes.Length);
                        }
                    }
                }
            }
            else
            {
                PGUtil.WriteInt16(outputStream, 0);
            }

            PGUtil.WriteInt16(outputStream, (Int16)_resultFormatCodes.Length);
            for (i = 0; i < _resultFormatCodes.Length; i++)
            {
                PGUtil.WriteInt16(outputStream, _resultFormatCodes[i]);
            }
        }
Пример #16
0
        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);
            }
        }
Пример #17
0
 internal NpgsqlNotificationEventArgs(Stream stream, bool readAdditional, byte[] buffer, ByteBuffer queue)
 {
     PID                   = PGUtil.ReadInt32(stream, buffer);
     Condition             = PGUtil.ReadString(stream, queue);
     AdditionalInformation = readAdditional ? PGUtil.ReadString(stream, queue) : string.Empty;
 }