!!! Helper class, for compilation only. Connector implements the logic for the Connection Objects to access the physical connection to the database, and isolate the application developer from connection pooling internals.
Ejemplo n.º 1
0
        public override void Authenticate(NpgsqlConnector context, byte[] password)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Authenticate");
            NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password);

            pwpck.WriteToStream(context.Stream);
        }
        public override void Open(NpgsqlConnector context)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Open");

            TcpClient tcpc = new TcpClient();
            tcpc.Connect(new IPEndPoint(ResolveIPHost(context.Host), context.Port));
            Stream stream = tcpc.GetStream();

            // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') {
            if (context.SSL)
            {
                PGUtil.WriteInt32(stream, 8);
                PGUtil.WriteInt32(stream,80877103);
                // Receive response
                Char response = (Char)stream.ReadByte();
                if (response == 'S')
                {
                    stream = new SslClientStream(
                                 tcpc.GetStream(),
                                 context.Host,
                                 true,
                                 Mono.Security.Protocol.Tls.SecurityProtocolType.Default
                             );

                    ((SslClientStream)stream).ClientCertSelectionDelegate = new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback);
                    ((SslClientStream)stream).ServerCertValidationDelegate = new CertificateValidationCallback(context.DefaultCertificateValidationCallback);
                    ((SslClientStream)stream).PrivateKeyCertSelectionDelegate = new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback);
                }
            }

            context.Stream = stream;

            NpgsqlEventLog.LogMsg(resman, "Log_ConnectedTo", LogLevel.Normal, context.Host, context.Port);
            ChangeState(context, NpgsqlConnectedState.Instance);
        }
 public override void Parse(NpgsqlConnector context, NpgsqlParse parse)
 {
     NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Parse");
     BufferedStream stream = new BufferedStream(context.Stream);
     parse.WriteToStream(stream, context.Encoding);
     stream.Flush();
 }
Ejemplo n.º 4
0
        public override void Close(NpgsqlConnector context)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Close");
            Stream stream = context.Stream;
            try
            {
                stream.WriteByte((byte) FrontEndMessageCode.Termination);
                if (context.BackendProtocolVersion >= ProtocolVersion.Version3)
                {
                    PGUtil.WriteInt32(stream, 4);
                }
                stream.Flush();
            }
            catch
            {
                //Error writting termination message to stream, nothing we can do.
            }

            try
            {
                stream.Close();
            }
            catch
            {
            }

            context.Stream = null;
            ChangeState(context, NpgsqlClosedState.Instance);
        }
		public override IEnumerable<IServerResponseObject> SyncEnum(NpgsqlConnector context)
		{
			NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Sync");
			_syncMessage.WriteToStream(context.Stream);
			context.Stream.Flush();
			return ProcessBackendResponsesEnum(context);
		}
Ejemplo n.º 6
0
 /// <summary>
 /// Sends given packet to server as a CopyData message.
 /// Does not check for notifications! Use another thread for that.
 /// </summary>
 public override void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len)
 {
     Stream toServer = context.Stream;
     toServer.WriteByte((byte) FrontEndMessageCode.CopyData);
     PGUtil.WriteInt32(toServer, len + 4);
     toServer.Write(buf, off, len);
 }
Ejemplo n.º 7
0
        public override void CancelRequest(NpgsqlConnector context)
        {
            NpgsqlCancelRequest CancelRequestMessage = new NpgsqlCancelRequest(context.BackEndKeyData);

            CancelRequestMessage.WriteToStream(context.Stream);
            context.Stream.Flush();
        }
		public override void Parse(NpgsqlConnector context, NpgsqlParse parse)
		{
			NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Parse");

			Stream stream = context.Stream;
			parse.WriteToStream(stream);
			//stream.Flush();
		}
		public override void Authenticate(NpgsqlConnector context, string password)
		{
			NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Authenticate");
			NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password, context.BackendProtocolVersion);
			BufferedStream stream = new BufferedStream(context.Stream);
			pwpck.WriteToStream(stream);
			stream.Flush();
		}
Ejemplo n.º 10
0
        public override void Startup(NpgsqlConnector context,NpgsqlConnectionStringBuilder settings)
        {
            NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(context.Database, context.UserName, settings);

            startupPacket.WriteToStream(context.Stream);
            context.RequireReadyForQuery = false;

            ProcessAndDiscardBackendResponses(context);
        }
Ejemplo n.º 11
0
        public override void Bind(NpgsqlConnector context, NpgsqlBind bind)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Bind");

            Stream stream = context.Stream;

            bind.WriteToStream(stream);
            //stream.Flush();
        }
Ejemplo n.º 12
0
        protected override void Dispose(bool disposing)
        {
            if (!disposing)
            {
                mContext.Close();
                mContext = null;
            }

            base.Dispose(disposing);

        }
Ejemplo n.º 13
0
 /// <summary>
 /// Called from NpgsqlOutStream.Read to read copy data from server.
 /// </summary>
 public override byte[] GetCopyData(NpgsqlConnector context)
 {
     // polling in COPY would take seconds on Windows
     foreach (IServerResponseObject obj in ProcessBackendResponses_Ver_3(context))
     {
         if (obj is IDisposable)
         {
             (obj as IDisposable).Dispose();
         }
     }
     return context.Mediator.ReceivedCopyData;
 }
Ejemplo n.º 14
0
        internal static void ExecuteBlindSuppressTimeout(NpgsqlConnector connector, NpgsqlQuery query)
        {
            // Block the notification thread before writing anything to the wire.
            using (var blocker = connector.BlockNotificationThread())
            {
                // Write the Query message to the wire.
                connector.Query(query);

                // Flush, and wait for and discard all responses.
                connector.ProcessAndDiscardBackendResponses();
            }
        }
Ejemplo n.º 15
0
        public override void Startup(NpgsqlConnector context,NpgsqlConnectionStringBuilder settings)
        {
            NpgsqlStartupPacket startupPacket = NpgsqlStartupPacket.BuildStartupPacket(context.BackendProtocolVersion,
                                                                                       context.Database, context.UserName, settings);

            startupPacket.WriteToStream(context.Stream);
            context.RequireReadyForQuery = false;
            // This still makes part of the connection stablishment handling.
            // So we use the connectiontimeout here too.
            context.Mediator.CommandTimeout = context.ConnectionTimeout;
            ProcessAndDiscardBackendResponses(context);
        }
        public override void Startup(NpgsqlConnector context)
        {
            NpgsqlStartupPacket startupPacket  = new NpgsqlStartupPacket(296, //Not used.
                                                  context.BackendProtocolVersion,
                                                  context.Database,
                                                  context.UserName,
                                                  "",
                                                  "",
                                                  "");

            startupPacket.WriteToStream( new BufferedStream(context.Stream), context.Encoding );
            context.Mediator.RequireReadyForQuery = false;
            ProcessBackendResponses( context );
        }
Ejemplo n.º 17
0
        public override void Startup(NpgsqlConnector context)
        {
            NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(296, //Not used.
                                                                        context.BackendProtocolVersion, context.Database,
                                                                        context.UserName, "", "", "");

            startupPacket.WriteToStream(new BufferedStream(context.Stream));
            context.RequireReadyForQuery = false;
            // This still makes part of the connection stablishment handling.
            // So we use the connectiontimeout here too.
            context.Mediator.CommandTimeout = context.ConnectionTimeout;
            context.Stream.Flush();
            ProcessBackendResponses(context);
        }
        private static void ExecuteBlind(NpgsqlConnector connector, NpgsqlQuery query, int timeout)
        {
            // Block the notification thread before writing anything to the wire.
            using (var blocker = connector.BlockNotificationThread())
            {
                // Set statement timeout as needed.
                connector.SetBackendCommandTimeout(timeout);

                // Write the Query message to the wire.
                connector.Query(query);

                // Flush, and wait for and discard all responses.
                connector.ProcessAndDiscardBackendResponses();
            }
        }
Ejemplo n.º 19
0
        internal ReadBuffer([CanBeNull] NpgsqlConnector connector, Stream stream, int size, Encoding textEncoding)
        {
            if (size < MinimumBufferSize) {
                throw new ArgumentOutOfRangeException(nameof(size), size, "Buffer size must be at least " + MinimumBufferSize);
            }
            Contract.EndContractBlock();

            Connector = connector;
            Underlying = stream;
            Size = size;
            _buf = new byte[Size];
            TextEncoding = textEncoding;
            _textDecoder = TextEncoding.GetDecoder();
            _tempCharBuf = new char[1024];
            _workspace = new byte[8];
        }
Ejemplo n.º 20
0
        public void TestNotify(NpgsqlConnector context)
        {
            //ZA  Hnotifytest CNOTIFY Z
            //Qlisten notifytest;notify notifytest;
            Stream stm = context.Stream;
//            string uuidString = "uuid" + Guid.NewGuid().ToString("N");
            string uuidString = string.Format("uuid{0:N}", Guid.NewGuid());
            Queue<byte> buffer = new Queue<byte>();
            byte[] convertBuffer = new byte[36];

            PGUtil.WriteStringNullTerminated(stm, "Qlisten {0};notify {0};", uuidString);

            for (;;)
            {
                int newByte = stm.ReadByte();
                if (newByte == -1)
                {
                    throw new EndOfStreamException();
                }
                buffer.Enqueue((byte) newByte);
                if (buffer.Count > 35)
                {
                    buffer.CopyTo(convertBuffer, 0);
                    if (BackendEncoding.UTF8Encoding.GetString(convertBuffer) == uuidString)
                    {
                        for (;;)
                        {
                            switch (stm.ReadByte())
                            {
                                case -1:
                                    throw new EndOfStreamException();
                                case 'Z':
                                    //context.Query(new NpgsqlCommand("UNLISTEN *", context));
                                    NpgsqlCommand.ExecuteBlind(context, "UNLISTEN *");

                                    return;
                            }
                        }
                    }
                    else
                    {
                        buffer.Dequeue();
                    }
                }
            }
        }
		public override IEnumerable<IServerResponseObject> QueryEnum(NpgsqlConnector context, NpgsqlCommand command)
		{
			NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "QueryEnum");


			//String commandText = command.GetCommandText();
			//NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText);

			// Send the query request to backend.

			NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion);

			query.WriteToStream(context.Stream);
			context.Stream.Flush();

			return ProcessBackendResponsesEnum(context);
		}
Ejemplo n.º 22
0
 /// <summary>
 /// Called from NpgsqlState.ProcessBackendResponses upon CopyOutResponse.
 /// If CopyStream is already set, it is used to write data received from server, after which the copy ends.
 /// Otherwise CopyStream is set to a readable NpgsqlCopyOutStream that receives data from server.
 /// </summary>
 protected override void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat)
 {
     _copyFormat = copyFormat;
     Stream userFeed = context.Mediator.CopyStream;
     if (userFeed == null)
     {
         context.Mediator.CopyStream = new NpgsqlCopyOutStream(context);
     }
     else
     {
         byte[] buf;
         while ((buf = GetCopyData(context)) != null)
         {
             userFeed.Write(buf, 0, buf.Length);
         }
         userFeed.Close();
     }
 }
Ejemplo n.º 23
0
        /// <summary>
        /// Special adaptation of ExecuteBlind() that sets statement_timeout.
        /// This exists to prevent Connector.SetBackendCommandTimeout() from calling Command.ExecuteBlind(),
        /// which will cause an endless recursive loop.
        /// </summary>
        /// <param name="connector"></param>
        /// <param name="timeout">Timeout in seconds.</param>
        internal static void ExecuteSetStatementTimeoutBlind(NpgsqlConnector connector, int timeout)
        {
            NpgsqlQuery query;

            // Optimize for a few common timeout values.
            switch (timeout)
            {
                case 10 :
                    query = NpgsqlQuery.SetStmtTimeout10Sec;
                    break;

                case 20 :
                    query = NpgsqlQuery.SetStmtTimeout20Sec;
                    break;

                case 30 :
                    query = NpgsqlQuery.SetStmtTimeout30Sec;
                    break;

                case 60 :
                    query = NpgsqlQuery.SetStmtTimeout60Sec;
                    break;

                case 90 :
                    query = NpgsqlQuery.SetStmtTimeout90Sec;
                    break;

                case 120 :
                    query = NpgsqlQuery.SetStmtTimeout120Sec;
                    break;

                default :
                    query = new NpgsqlQuery(string.Format("SET statement_timeout = {0}", timeout * 1000));
                    break;

            }

            // Write the Query message to the wire.
            connector.Query(query);

            // Flush, and wait for and discard all responses.
            connector.ProcessAndDiscardBackendResponses();
        }
Ejemplo n.º 24
0
        public override void Query( NpgsqlConnector context, NpgsqlCommand command )
        {

            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Query");



            //String commandText = command.GetCommandText();
            //NpgsqlEventLog.LogMsg(resman, "Log_QuerySent", LogLevel.Debug, commandText);

            // Send the query request to backend.

            NpgsqlQuery query = new NpgsqlQuery(command, context.BackendProtocolVersion);

            query.WriteToStream(context.Stream, context.Encoding);
            context.Stream.Flush();

            ProcessBackendResponses(context);

        }
Ejemplo n.º 25
0
		/// <summary>
		/// Called from NpgsqlState.ProcessBackendResponses upon CopyInResponse.
		/// If CopyStream is already set, it is used to read data to push to server, after which the copy is completed.
		/// Otherwise CopyStream is set to a writable NpgsqlCopyInStream that calls SendCopyData each time it is written to.
		/// </summary>
		protected override void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat)
		{
			_copyFormat = copyFormat;
			Stream userFeed = context.Mediator.CopyStream;
			if (userFeed == null)
			{
				context.Mediator.CopyStream = new NpgsqlCopyInStream(context);
			}
			else
			{
				// copy all of user feed to server at once
				int bufsiz = context.Mediator.CopyBufferSize;
				byte[] buf = new byte[bufsiz];
				int len;
				while ((len = userFeed.Read(buf, 0, bufsiz)) > 0)
				{
					SendCopyData(context, buf, 0, len);
				}
				SendCopyDone(context);
			}
		}
Ejemplo n.º 26
0
 internal NpgsqlRawCopyStream(NpgsqlConnector connector, string copyCommand)
 {
     _connector = connector;
     _buf = connector.Buffer;
     _connector.SendSingleMessage(new QueryMessage(copyCommand));
     var msg = _connector.ReadSingleMessage();
     switch (msg.Code)
     {
     case BackendMessageCode.CopyInResponse:
         var copyInResponse = (CopyInResponseMessage) msg;
         IsBinary = copyInResponse.IsBinary;
         _canWrite = true;
         break;
     case BackendMessageCode.CopyOutResponse:
         var copyOutResponse = (CopyOutResponseMessage) msg;
         IsBinary = copyOutResponse.IsBinary;
         _canRead = true;
         break;
     default:
         throw _connector.UnexpectedMessageReceived(msg.Code);
     }
 }
Ejemplo n.º 27
0
        internal NpgsqlDataReader(IEnumerable<IServerResponseObject> dataEnumeration, CommandBehavior behavior,
                                        NpgsqlCommand command, NpgsqlConnector.NotificationThreadBlock threadBlock,
                                        bool preparedStatement = false, NpgsqlRowDescription rowDescription = null)
        {
            _behavior = behavior;
            _connection = (_command = command).Connection;
            _connector = command.Connector;
            _dataEnumerator = dataEnumeration.GetEnumerator();
            _connector.CurrentReader = this;
            _threadBlock = threadBlock;
            _preparedStatement = preparedStatement;
            CurrentDescription = rowDescription;

            // For un-prepared statements, the first response is always a row description.
            // For prepared statements, we may be recycling a row description from a previous Execute.
            if (CurrentDescription == null)
            {
                NextResultInternal();
            }

            UpdateOutputParameters();
        }
Ejemplo n.º 28
0
 internal NpgsqlRawCopyStream(NpgsqlConnector connector, string copyCommand)
 {
     _connector = connector;
     _readBuf = connector.ReadBuffer;
     _writeBuf = connector.WriteBuffer;
     _connector.SendQuery(copyCommand);
     var msg = _connector.ReadMessage(DataRowLoadingMode.NonSequential);
     switch (msg.Code)
     {
     case BackendMessageCode.CopyInResponse:
         var copyInResponse = (CopyInResponseMessage) msg;
         IsBinary = copyInResponse.IsBinary;
         _canWrite = true;
         break;
     case BackendMessageCode.CopyOutResponse:
         var copyOutResponse = (CopyOutResponseMessage) msg;
         IsBinary = copyOutResponse.IsBinary;
         _canRead = true;
         break;
     default:
         throw _connector.UnexpectedMessageReceived(msg.Code);
     }
 }
Ejemplo n.º 29
0
 public virtual void Bind(NpgsqlConnector context, NpgsqlBind bind)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 30
0
 public virtual void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 31
0
 public virtual byte[] GetCopyData(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 32
0
 public virtual void SendCopyFail(NpgsqlConnector context, String message)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 33
0
 ///<summary>
 /// This method is responsible to handle all protocol messages sent from the backend.
 /// It holds all the logic to do it.
 /// To exchange data, it uses a Mediator object from which it reads/writes information
 /// to handle backend requests.
 /// </summary>
 ///
 internal void ProcessBackendResponses(NpgsqlConnector context)
 {
     IterateThroughAllResponses(ProcessBackendResponsesEnum(context, false));
 }
Ejemplo n.º 34
0
 internal void Clear()
 {
     _connector = null;
     Connection = null;
 }
Ejemplo n.º 35
0
 public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
 {
     NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Describe");
     describe.WriteToStream(context.Stream);
     //context.Stream.Flush();
 }
Ejemplo n.º 36
0
        ///<summary>
        /// This method is responsible to handle all protocol messages sent from the backend.
        /// It holds all the logic to do it.
        /// To exchange data, it uses a Mediator object from which it reads/writes information
        /// to handle backend requests.
        /// </summary>
        ///
        internal IEnumerable <IServerResponseObject> ProcessBackendResponsesEnum(
            NpgsqlConnector context,
            bool cancelRequestCalled)
        {
            try
            {
                // Process commandTimeout behavior.

                if ((context.Mediator.CommandTimeout > 0) &&
                    (!CheckForContextSocketAvailability(context, SelectMode.SelectRead)))
                {
                    // If timeout occurs when establishing the session with server then
                    // throw an exception instead of trying to cancel query. This helps to prevent loop as CancelRequest will also try to stablish a connection and sends commands.
                    if (!((this is NpgsqlStartupState || this is NpgsqlConnectedState || cancelRequestCalled)))
                    {
                        try
                        {
                            context.CancelRequest();
                            foreach (IServerResponseObject obj in ProcessBackendResponsesEnum(context, true))
                            {
                                if (obj is IDisposable)
                                {
                                    (obj as IDisposable).Dispose();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                        }
                        //We should have gotten an error from CancelRequest(). Whether we did or not, what we
                        //really have is a timeout exception, and that will be less confusing to the user than
                        //"operation cancelled by user" or similar, so whatever the case, that is what we'll throw.
                        // Changed message again to report about the two possible timeouts: connection or command as the establishment timeout only was confusing users when the timeout was a command timeout.
                    }
                    throw new NpgsqlException(resman.GetString("Exception_ConnectionOrCommandTimeout"));
                }
                switch (context.BackendProtocolVersion)
                {
                case ProtocolVersion.Version2:
                    return(ProcessBackendResponses_Ver_2(context));

                case ProtocolVersion.Version3:
                    return(ProcessBackendResponses_Ver_3(context));

                default:
                    throw new NpgsqlException(resman.GetString("Exception_UnknownProtocol"));
                }
            }

            catch (ThreadAbortException)
            {
                try
                {
                    context.CancelRequest();
                    context.Close();
                }
                catch { }

                throw;
            }
        }
Ejemplo n.º 37
0
 public virtual IEnumerable <IServerResponseObject> SyncEnum(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 38
0
 public virtual void Flush(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 39
0
        protected IEnumerable <IServerResponseObject> ProcessBackendResponses_Ver_2(NpgsqlConnector context)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");

            using (new ContextResetter(context))
            {
                Stream               stream             = context.Stream;
                NpgsqlMediator       mediator           = context.Mediator;
                NpgsqlRowDescription lastRowDescription = null;
                List <NpgsqlError>   errors             = new List <NpgsqlError>();

                for (; ;)
                {
                    // Check the first Byte of response.
                    switch ((BackEndMessageCode)stream.ReadByte())
                    {
                    case BackEndMessageCode.ErrorResponse:
                    {
                        NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion, stream);
                        error.ErrorSql = mediator.SqlSent;

                        errors.Add(error);

                        NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message);
                    }

                        // 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:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AuthenticationRequest");
                        AuthenticationRequestType authType = (AuthenticationRequestType)PGUtil.ReadInt32(stream);
                        switch (authType)
                        {
                        case AuthenticationRequestType.AuthenticationOk:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
                            break;

                        case AuthenticationRequestType.AuthenticationClearTextPassword:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationClearTextRequest", LogLevel.Debug);
                            // Send the PasswordPacket.
                            ChangeState(context, NpgsqlStartupState.Instance);
                            context.Authenticate(context.Password);
                            break;

                        case AuthenticationRequestType.AuthenticationMD5Password:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationMD5Request", LogLevel.Debug);
                            // 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);


                            byte[] saltServer = new byte[4];
                            stream.Read(saltServer, 0, 4);
                            // Send the PasswordPacket.
                            ChangeState(context, NpgsqlStartupState.Instance);


                            // 2.

                            crypt_buf = new byte[prehashbytes.Length + saltServer.Length];
                            prehashbytes.CopyTo(crypt_buf, 0);
                            saltServer.CopyTo(crypt_buf, prehashbytes.Length);

                            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;

                        default:
                            // Only AuthenticationClearTextPassword and AuthenticationMD5Password supported for now.
                            errors.Add(
                                new NpgsqlError(context.BackendProtocolVersion,
                                                String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
                            throw new NpgsqlException(errors);
                        }
                        break;

                    case BackEndMessageCode.RowDescription:
                        yield return(lastRowDescription = new NpgsqlRowDescriptionV2(stream, context.OidToNameMapping, context.CompatVersion));

                        ;
                        break;

                    case BackEndMessageCode.DataRow:
                        yield return(new ForwardsOnlyRow(new StringRowReaderV2(lastRowDescription, stream)));

                        break;

                    case BackEndMessageCode.BinaryRow:
                        throw new NotSupportedException();

                    case BackEndMessageCode.ReadyForQuery:
                        ChangeState(context, NpgsqlReadyState.Instance);
                        if (errors.Count != 0)
                        {
                            throw new NpgsqlException(errors);
                        }
                        yield break;

                    case BackEndMessageCode.BackendKeyData:
                        context.BackEndKeyData = new NpgsqlBackEndKeyData(context.BackendProtocolVersion, stream);
                        break;

                    case BackEndMessageCode.NoticeResponse:
                        context.FireNotice(new NpgsqlError(context.BackendProtocolVersion, stream));
                        break;

                    case BackEndMessageCode.CompletedResponse:
                        yield return(new CompletedResponse(stream));

                        break;

                    case BackEndMessageCode.CursorResponse:
                        // This is the cursor response message.
                        // It is followed by a C NULL terminated string with the name of
                        // the cursor in a FETCH case or 'blank' otherwise.
                        // In this case it should be always 'blank'.
                        // [FIXME] Get another name for this function.
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CursorResponse");

                        String cursorName = PGUtil.ReadString(stream);
                        // Continue waiting for ReadyForQuery message.
                        break;

                    case BackEndMessageCode.EmptyQueryResponse:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "EmptyQueryResponse");
                        PGUtil.ReadString(stream);
                        break;

                    case BackEndMessageCode.NotificationResponse:
                        context.FireNotification(new NpgsqlNotificationEventArgs(stream, false));
                        if (context.IsNotificationThreadRunning)
                        {
                            yield break;
                        }
                        break;

                    case BackEndMessageCode.IO_ERROR:
                        // Connection broken. Mono returns -1 instead of throw 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?
                        throw new DataException("Backend sent unrecognized response type");
                    }
                }
            }
        }
Ejemplo n.º 40
0
        public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Describe");

            describe.WriteToStream(context.Stream);
        }
Ejemplo n.º 41
0
 public void Query(NpgsqlConnector context, NpgsqlCommand command)
 {
     IterateThroughAllResponses(QueryEnum(context, command));
 }
Ejemplo n.º 42
0
        protected IEnumerable <IServerResponseObject> ProcessBackendResponses_Ver_3(NpgsqlConnector context)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "ProcessBackendResponses");

            using (new ContextResetter(context))
            {
                Stream         stream   = context.Stream;
                NpgsqlMediator mediator = context.Mediator;

                NpgsqlRowDescription lastRowDescription = null;

                List <NpgsqlError> errors = new List <NpgsqlError>();

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

                        NpgsqlError error = new NpgsqlError(context.BackendProtocolVersion, stream);
                        error.ErrorSql = mediator.SqlSent;

                        errors.Add(error);

                        NpgsqlEventLog.LogMsg(resman, "Log_ErrorResponse", LogLevel.Debug, error.Message);

                        // 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:

                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "AuthenticationRequest");

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

                        AuthenticationRequestType authType = (AuthenticationRequestType)PGUtil.ReadInt32(stream);
                        switch (authType)
                        {
                        case AuthenticationRequestType.AuthenticationOk:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationOK", LogLevel.Debug);
                            break;

                        case AuthenticationRequestType.AuthenticationClearTextPassword:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationClearTextRequest", LogLevel.Debug);

                            // Send the PasswordPacket.

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

                            break;

                        case AuthenticationRequestType.AuthenticationMD5Password:
                            NpgsqlEventLog.LogMsg(resman, "Log_AuthenticationMD5Request", LogLevel.Debug);
                            // 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.
                            errors.Add(
                                new NpgsqlError(context.BackendProtocolVersion,
                                                String.Format(resman.GetString("Exception_AuthenticationMethodNotSupported"), authType)));
                            throw new NpgsqlException(errors);
                        }
                        break;

                    case BackEndMessageCode.RowDescription:
                        yield return(lastRowDescription = new NpgsqlRowDescriptionV3(stream, context.OidToNameMapping, context.CompatVersion));

                        break;

                    case BackEndMessageCode.ParameterDescription:

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

                        break;

                    case BackEndMessageCode.DataRow:
                        yield return(new ForwardsOnlyRow(new StringRowReaderV3(lastRowDescription, stream)));

                        break;

                    case BackEndMessageCode.ReadyForQuery:

                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "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);
                        stream.ReadByte();

                        ChangeState(context, NpgsqlReadyState.Instance);

                        if (errors.Count != 0)
                        {
                            throw new NpgsqlException(errors);
                        }

                        yield break;

                    case BackEndMessageCode.BackendKeyData:

                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BackendKeyData");
                        // BackendKeyData message.
                        NpgsqlBackEndKeyData backend_keydata = new NpgsqlBackEndKeyData(context.BackendProtocolVersion, stream);
                        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(context.BackendProtocolVersion, stream));
                        break;

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

                        break;

                    case BackEndMessageCode.ParseComplete:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParseComplete");
                        // Just read up the message length.
                        PGUtil.ReadInt32(stream);
                        yield break;

                    case BackEndMessageCode.BindComplete:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "BindComplete");
                        // Just read up the message length.
                        PGUtil.ReadInt32(stream);
                        yield break;

                    case BackEndMessageCode.EmptyQueryResponse:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "EmptyQueryResponse");
                        PGUtil.ReadInt32(stream);
                        break;

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

                    case BackEndMessageCode.ParameterStatus:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParameterStatus");
                        NpgsqlParameterStatus parameterStatus = new NpgsqlParameterStatus(stream);

                        NpgsqlEventLog.LogMsg(resman, "Log_ParameterStatus", LogLevel.Debug, parameterStatus.Parameter,
                                              parameterStatus.ParameterValue);

                        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.
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "ParameterStatus");
                        PGUtil.ReadInt32(stream);
                        break;

                    case BackEndMessageCode.CopyInResponse:
                        // Enter COPY sub protocol and start pushing data to server
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyInResponse");
                        ChangeState(context, NpgsqlCopyInState.Instance);
                        PGUtil.ReadInt32(stream);                                 // length redundant
                        context.CurrentState.StartCopy(context, ReadCopyHeader(stream));
                        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
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyOutResponse");
                        ChangeState(context, NpgsqlCopyOutState.Instance);
                        PGUtil.ReadInt32(stream);                                 // length redundant
                        context.CurrentState.StartCopy(context, ReadCopyHeader(stream));
                        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:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyData");
                        Int32  len = PGUtil.ReadInt32(stream) - 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:
                        NpgsqlEventLog.LogMsg(resman, "Log_ProtocolMessage", LogLevel.Debug, "CopyDone");
                        PGUtil.ReadInt32(stream);                                 // 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));
                    }
                }
            }
        }
Ejemplo n.º 43
0
        /*
         *      /// <summary>
         *      /// Find an available shared connector in the shared pool, or create
         *      /// a new one if none found.
         *      /// </summary>
         *      private NpgsqlConnector GetSharedConnector(NpgsqlConnection Connection)
         *      {
         *          // To be implemented
         *
         *          return null;
         *      }
         */

        /// <summary>
        /// Put a pooled connector into the pool queue.
        /// </summary>
        /// <param name="Connector">Connector to pool</param>
        private void UngetConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
        {
            ConnectorQueue queue;

            // Find the queue.
            // As we are handling all possible queues, we have to lock everything...
            lock (locker)
            {
                PooledConnectors.TryGetValue(Connection.ConnectionString, out queue);
            }


            if (queue == null)
            {
                Connector.Close(); // Release connection to postgres
                return;            // Queue may be emptied by connection problems. See ClearPool below.
            }

            Connector.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
            Connector.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
            Connector.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
            Connector.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

            bool inQueue = false;

            lock (queue)
            {
                inQueue = queue.Busy.ContainsKey(Connector);
                queue.Busy.Remove(Connector);
            }

            if (!Connector.IsInitialized)
            {
                if (Connector.Transaction != null)
                {
                    Connector.Transaction.Cancel();
                }

                Connector.Close();
            }
            else
            {
                if (Connector.Transaction != null)
                {
                    try
                    {
                        Connector.Transaction.Rollback();
                    }
                    catch
                    {
                        Connector.Close();
                    }
                }
            }

            if (Connector.State == ConnectionState.Open)
            {
                //If thread is good
                if ((Thread.CurrentThread.ThreadState & (ThreadState.Aborted | ThreadState.AbortRequested)) == 0)
                {
                    // Release all resources associated with this connector.
                    try
                    {
                        Connector.ReleaseResources();
                    }
                    catch (Exception)
                    {
                        //If the connector fails to release its resources then it is probably broken, so make sure we don't add it to the queue.
                        // Usually it already won't be in the queue as it would of broken earlier
                        inQueue = false;
                    }

                    if (inQueue)
                    {
                        lock (queue)
                        {
                            queue.Available.Enqueue(Connector);
                        }
                    }
                    else
                    {
                        Connector.Close();
                    }
                }
                else
                {
                    //Thread is being aborted, this connection is possibly broken. So kill it rather than returning it to the pool
                    Connector.Close();
                }
            }
        }
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;

            // Try to find a queue.
            if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
            {
                Queue = new ConnectorQueue();
                Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                Queue.MinPoolSize        = Connection.MinPoolSize;
                PooledConnectors[Connection.ConnectionString] = Queue;
            }

            // Fix queue use count. Use count may be dropped below zero if Queue was cleared and there were connections open.
            if (Queue.UseCount < 0)
            {
                Queue.UseCount = 0;
            }


            if (Queue.Count > 0)
            {
                // Found a queue with connectors.  Grab the top one.

                // Check if the connector is still valid.

                Connector = Queue.Dequeue();

                /*try
                 * {
                 *      Connector.TestConnector();
                 *      Connector.RequireReadyForQuery = true;
                 * }
                 * catch //This connector is broken!
                 * {
                 *      try
                 *      {
                 *              Connector.Close();
                 *      }
                 *      catch
                 *      {
                 *              try
                 *              {
                 *                      Connector.Stream.Close();
                 *              }
                 *              catch
                 *              {
                 *              }
                 *      }
                 *      return GetPooledConnector(Connection); //Try again
                 * }*/

                if (!Connector.IsValid())
                {
                    try
                    {
                        Connector.Close();
                    }
                    catch
                    {
                        try
                        {
                            Connector.Stream.Close();
                        }
                        catch
                        {
                        }
                    }
                    return(GetPooledConnector(Connection));                            //Try again
                }
                Queue.UseCount++;
            }
            else if (Queue.Count + Queue.UseCount < Connection.MaxPoolSize)
            {
                Connector = CreateConnector(Connection);

                Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                Connector.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch
                {
                    try
                    {
                        Connector.Close();
                    }
                    catch
                    {
                    }

                    throw;
                }


                Queue.UseCount++;
            }

            // Meet the MinPoolSize requirement if needed.
            if (Connection.MinPoolSize > 0)
            {
                while (Queue.Count + Queue.UseCount < Connection.MinPoolSize)
                {
                    NpgsqlConnector Spare = CreateConnector(Connection);

                    Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                    Spare.Open();

                    Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
                    Spare.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
                    Spare.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
                    Spare.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

                    Queue.Enqueue(Spare);
                }
            }

            return(Connector);
        }
Ejemplo n.º 45
0
 public ContextResetter(NpgsqlConnector connector)
 {
     _connector = connector;
 }
Ejemplo n.º 46
0
 internal GSSPasswordMessageStream(NpgsqlConnector connector)
 {
     _connector = connector;
     _msg       = new PasswordMessage();
 }
Ejemplo n.º 47
0
 ///<summary>
 ///This method is used by the states to change the state of the context.
 /// </summary>
 protected static void ChangeState(NpgsqlConnector context, NpgsqlState newState)
 {
     context.CurrentState = newState;
 }
Ejemplo n.º 48
0
 public NotificationThreadBlock(NpgsqlConnector connector)
 {
     (_connector = connector).StopNotificationThread();
 }
Ejemplo n.º 49
0
 public virtual void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 50
0
 internal NpgsqlContextHolder(NpgsqlConnector connector, NpgsqlState state)
 {
     this.connector = connector;
     this.state     = state;
 }
Ejemplo n.º 51
0
        // COPY methods

        protected virtual void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat)
        {
            throw new InvalidOperationException("Internal Error! " + this);
        }
Ejemplo n.º 52
0
        internal async ValueTask <NpgsqlConnector> AllocateLong(NpgsqlConnection conn, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken)
        {
            Debug.Assert(Monitor.IsEntered(this));
            NpgsqlConnector connector;

            Debug.Assert(Busy <= _max);
            if (Busy == _max)
            {
                // TODO: Async cancellation
                var tcs = new TaskCompletionSource <NpgsqlConnector>();
                _waiting.Enqueue(new WaitingOpenAttempt {
                    TaskCompletionSource = tcs, IsAsync = async
                });
                Monitor.Exit(this);

                try
                {
                    if (async)
                    {
                        if (timeout.IsSet)
                        {
                            var timeLeft = timeout.TimeLeft;
                            if (timeLeft <= TimeSpan.Zero || tcs.Task != await Task.WhenAny(tcs.Task, Task.Delay(timeLeft)))
                            {
                                throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)");
                            }
                        }
                        else
                        {
                            await tcs.Task;
                        }
                    }
                    else
                    {
                        if (timeout.IsSet)
                        {
                            var timeLeft = timeout.TimeLeft;
                            if (timeLeft <= TimeSpan.Zero || !tcs.Task.Wait(timeLeft))
                            {
                                throw new NpgsqlException($"The connection pool has been exhausted, either raise MaxPoolSize (currently {_max}) or Timeout (currently {Settings.Timeout} seconds)");
                            }
                        }
                        else
                        {
                            tcs.Task.Wait();
                        }
                    }
                }
                catch
                {
                    // We're here if the timeout expired or the cancellation token was triggered
                    // Re-lock and check in case the task was set to completed after coming out of the Wait
                    lock (this)
                    {
                        if (!tcs.Task.IsCompleted)
                        {
                            tcs.SetCanceled();
                            throw;
                        }
                    }
                }
                connector            = tcs.Task.Result;
                connector.Connection = conn;
                return(connector);
            }

            // No idle connectors are available, and we're under the pool's maximum capacity.
            IncrementBusy();
            Monitor.Exit(this);

            try
            {
                connector = new NpgsqlConnector(conn)
                {
                    ClearCounter = _clearCounter
                };
                await connector.Open(timeout, async, cancellationToken);

                Counters.NumberOfPooledConnections.Increment();
                EnsureMinPoolSize(conn);
                return(connector);
            }
            catch
            {
                lock (this)
                    DecrementBusy();
                throw;
            }
        }
Ejemplo n.º 53
0
 public virtual void Execute(NpgsqlConnector context, NpgsqlExecute execute)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 54
0
        internal void Release(NpgsqlConnector connector)
        {
            // If Clear/ClearAll has been been called since this connector was first opened,
            // throw it away.
            if (connector.ClearCounter < _clearCounter)
            {
                try
                {
                    connector.Close();
                }
                catch (Exception e)
                {
                    Log.Warn("Exception while closing outdated connector", e, connector.Id);
                }

                lock (this)
                    DecrementBusy();
                Counters.SoftDisconnectsPerSecond.Increment();
                Counters.NumberOfPooledConnections.Decrement();
                return;
            }

            if (connector.IsBroken)
            {
                lock (this)
                    DecrementBusy();
                Counters.NumberOfPooledConnections.Decrement();
                return;
            }

            connector.Reset();
            lock (this)
            {
                // If there are any pending open attempts in progress hand the connector off to
                // them directly.
                while (_waiting.Count > 0)
                {
                    var waitingOpenAttempt = _waiting.Dequeue();
                    var tcs = waitingOpenAttempt.TaskCompletionSource;
                    // Some attempts may be in the queue but in cancelled state, since they've already timed out.
                    // Simply dequeue these and move on.
                    if (tcs.Task.IsCanceled)
                    {
                        continue;
                    }

                    // We have a pending open attempt. "Complete" it, handing off the connector.
                    if (waitingOpenAttempt.IsAsync)
                    {
                        // If the waiting open attempt is asynchronous (i.e. OpenAsync()), we can't simply
                        // call SetResult on its TaskCompletionSource, since it would execute the open's
                        // continuation in our thread (the closing thread). Instead we schedule the completion
                        // to run in the TP

                        // We copy tcs2 and especially connector2 to avoid allocations caused by the closure, see
                        // http://stackoverflow.com/questions/41507166/closure-heap-allocation-happening-at-start-of-method
                        var tcs2       = tcs;
                        var connector2 = connector;

                        Task.Run(() => tcs2.SetResult(connector2));
                    }
                    else
                    {
                        tcs.SetResult(connector);
                    }
                    return;
                }

                Idle.Push(connector);
                DecrementBusy();
                EnsurePruningTimerState();
                Debug.Assert(Idle.Count <= _max);
            }
        }
Ejemplo n.º 55
0
 private void CleanUpConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
 {
     new CleanUpConnectorDel(CleanUpConnectorMethod).BeginInvoke(Connection, Connector, null, null);
 }
Ejemplo n.º 56
0
        /// <summary>
        /// Find an available pooled connector in the non-shared pool, or create
        /// a new one if none found.
        /// </summary>
        private NpgsqlConnector GetPooledConnector(NpgsqlConnection Connection)
        {
            ConnectorQueue  Queue;
            NpgsqlConnector Connector = null;


            // We only need to lock all pools when trying to get one pool or create one.

            lock (locker)
            {
                // Try to find a queue.
                if (!PooledConnectors.TryGetValue(Connection.ConnectionString, out Queue))
                {
                    Queue = new ConnectorQueue();
                    Queue.ConnectionLifeTime = Connection.ConnectionLifeTime;
                    Queue.MinPoolSize        = Connection.MinPoolSize;
                    PooledConnectors[Connection.ConnectionString] = Queue;
                }
            }


            // Now we can simply lock on the pool itself.
            lock (Queue)
            {
                if (Queue.Available.Count > 0)
                {
                    // Found a queue with connectors.  Grab the top one.

                    // Check if the connector is still valid.

                    Connector = Queue.Available.Dequeue();
                    Queue.Busy.Add(Connector, null);
                }
            }

            if (Connector != null)
            {
                if (!Connector.IsValid())
                {
                    lock (Queue)
                    {
                        Queue.Busy.Remove(Connector);
                    }


                    Connector.Close();
                    return(GetPooledConnector(Connection)); //Try again
                }

                return(Connector);
            }


            lock (Queue)
            {
                if (Queue.Available.Count + Queue.Busy.Count < Connection.MaxPoolSize)
                {
                    Connector = new NpgsqlConnector(Connection);
                    Queue.Busy.Add(Connector, null);
                }
            }


            if (Connector != null)
            {
                Connector.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                Connector.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                Connector.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                Connector.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                try
                {
                    Connector.Open();
                }
                catch
                {
                    lock (Queue)
                    {
                        Queue.Busy.Remove(Connector);
                    }

                    Connector.Close();

                    throw;
                }


                // Meet the MinPoolSize requirement if needed.
                if (Connection.MinPoolSize > 1)
                {
                    lock (Queue)
                    {
                        while (Queue.Available.Count + Queue.Busy.Count < Connection.MinPoolSize)
                        {
                            NpgsqlConnector Spare = new NpgsqlConnector(Connection);

                            Spare.ProvideClientCertificatesCallback += Connection.ProvideClientCertificatesCallbackDelegate;
                            Spare.CertificateSelectionCallback      += Connection.CertificateSelectionCallbackDelegate;
                            Spare.CertificateValidationCallback     += Connection.CertificateValidationCallbackDelegate;
                            Spare.PrivateKeySelectionCallback       += Connection.PrivateKeySelectionCallbackDelegate;

                            Spare.Open();

                            Spare.ProvideClientCertificatesCallback -= Connection.ProvideClientCertificatesCallbackDelegate;
                            Spare.CertificateSelectionCallback      -= Connection.CertificateSelectionCallbackDelegate;
                            Spare.CertificateValidationCallback     -= Connection.CertificateValidationCallbackDelegate;
                            Spare.PrivateKeySelectionCallback       -= Connection.PrivateKeySelectionCallbackDelegate;

                            Queue.Available.Enqueue(Spare);
                        }
                    }
                }
            }


            return(Connector);
        }
Ejemplo n.º 57
0
 public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 58
0
 public virtual void Authenticate(NpgsqlConnector context, byte[] password)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
Ejemplo n.º 59
0
        public override void Execute(NpgsqlConnector context, NpgsqlExecute execute)
        {
            NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, "Execute");

            execute.WriteToStream(context.Stream);
        }
Ejemplo n.º 60
0
 public virtual void Parse(NpgsqlConnector context, NpgsqlParse parse)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }