コード例 #1
0
		public override void CancelRequest(NpgsqlConnector context)
		{
			NpgsqlCancelRequest CancelRequestMessage = new NpgsqlCancelRequest(context.BackEndKeyData);


			CancelRequestMessage.WriteToStream(context.Stream);
		}
コード例 #2
0
ファイル: NpgsqlReadyState.cs プロジェクト: dstimac/revenj
		public override void Bind(NpgsqlConnector context, NpgsqlBind bind)
		{
			Stream stream = context.Stream;

			bind.WriteToStream(stream);
			//stream.Flush();
		}
コード例 #3
0
ファイル: NpgsqlStartupState.cs プロジェクト: dstimac/revenj
		public override void Authenticate(NpgsqlConnector context, byte[] password)
		{
			NpgsqlPasswordPacket pwpck = new NpgsqlPasswordPacket(password);
			BufferedStream stream = new BufferedStream(context.Stream);
			pwpck.WriteToStream(stream);
			stream.Flush();
		}
コード例 #4
0
ファイル: NpgsqlReadyState.cs プロジェクト: dstimac/revenj
		public override IEnumerable<IServerResponseObject> QueryEnum(NpgsqlConnector context, NpgsqlCommand command)
		{
			// Send the query request to backend.

			NpgsqlQuery.Send(command, context.Stream);
			context.Stream.Flush();

			return ProcessBackendResponsesEnum(context, false);
		}
コード例 #5
0
ファイル: NpgsqlClosedState.cs プロジェクト: dstimac/revenj
		protected override void Dispose(bool disposing)
		{
			if (!disposing)
			{
				mContext.Close();
				mContext = null;
			}
			base.Dispose(disposing);
		}
コード例 #6
0
ファイル: NpgsqlCopyOutState.cs プロジェクト: dstimac/revenj
		/// <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;
		}
コード例 #7
0
		public override void Startup(NpgsqlConnector context)
		{
			NpgsqlStartupPacket startupPacket = new NpgsqlStartupPacket(296, //Not used.
																		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);
		}
コード例 #8
0
ファイル: NpgsqlCopyOutState.cs プロジェクト: dstimac/revenj
		/// <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();
			}
		}
コード例 #9
0
ファイル: NpgsqlCopyInState.cs プロジェクト: dstimac/revenj
		/// <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);
			}
		}
コード例 #10
0
ファイル: NpgsqlReadyState.cs プロジェクト: zhxjdwh/revenj
 public override void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
 {
     describe.WriteToStream(context.Stream);
     //context.Stream.Flush();
 }
コード例 #11
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public void EmptySync(NpgsqlConnector context)
 {
     Stream stm = context.Stream;
     NpgsqlSync.Send(stm);
     stm.Flush();
     Queue<int> buffer = new Queue<int>();
     //byte[] compareBuffer = new byte[6];
     int newByte;
     for (; ; )
     {
         switch (newByte = stm.ReadByte())
         {
             case -1:
                 throw new EndOfStreamException();
             case 'E':
             case 'I':
             case 'T':
                 if (buffer.Count > 4)
                 {
                     bool match = true;
                     int i = 0;
                     foreach (byte cmp in buffer)
                     {
                         if (cmp != messageSought[i++])
                         {
                             match = false;
                             break;
                         }
                     }
                     if (match)
                     {
                         return;
                     }
                 }
                 break;
             default:
                 buffer.Enqueue(newByte);
                 if (buffer.Count > 5)
                 {
                     buffer.Dequeue();
                 }
                 break;
         }
     }
 }
コード例 #12
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 // COPY methods
 protected virtual void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #13
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(resman.GetString("Exception_ConnectionTimeout"));
                        }

                        socket.EndConnect(result);

                        // connect was successful, leave the loop
                        break;
                    }
                    catch (Exception)
                    {
                        socket.Close();
                    }
                }

                if (socket == null || !socket.Connected)
                {
                    throw new Exception(string.Format(resman.GetString("Exception_FailedConnection"), context.Host));
                }

                Stream stream = new NpgsqlNetworkStream(context, socket, true);

                // If the PostgreSQL server has SSL connectors enabled Open SslClientStream if (response == 'S') {
                if (context.SSL || (context.SslMode == SslMode.Require) || (context.SslMode == SslMode.Prefer))
                {
                    PGUtil.WriteInt32(stream, 8);
                    PGUtil.WriteInt32(stream, 80877103);
                    // Receive response

                    Char response = (Char)stream.ReadByte();
                    if (response == 'S')
                    {
                        //create empty collection
                        X509CertificateCollection clientCertificates = new X509CertificateCollection();

                        //trigger the callback to fetch some certificates
                        context.DefaultProvideClientCertificatesCallback(clientCertificates);

                        stream = new SslClientStream(
                            stream,
                            context.Host,
                            true,
                            SecurityProtocolType.Default,
                            clientCertificates);

                        ((SslClientStream)stream).ClientCertSelectionDelegate =
                            new CertificateSelectionCallback(context.DefaultCertificateSelectionCallback);
                        ((SslClientStream)stream).ServerCertValidationDelegate =
                            new CertificateValidationCallback(context.DefaultCertificateValidationCallback);
                        ((SslClientStream)stream).PrivateKeyCertSelectionDelegate =
                            new PrivateKeySelectionCallback(context.DefaultPrivateKeySelectionCallback);
                    }
                    else if (context.SslMode == SslMode.Require)
                    {
                        throw new InvalidOperationException(resman.GetString("Exception_Ssl_RequestError"));
                    }
                }

                context.Stream = new BufferedStream(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);
            }
        }
コード例 #14
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual IEnumerable<IServerResponseObject> SyncEnum(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #15
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 ///<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));
 }
コード例 #16
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Bind(NpgsqlConnector context, NpgsqlBind bind)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #17
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #18
0
        /// <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;

            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 = queue.RemoveBusy(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)
                    {
                        queue.EnqueueAvailable(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();
                }
            }
        }
コード例 #19
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public void TestConnector(NpgsqlConnector context)
 {
     EmptySync(context);
 }
コード例 #20
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;

            // 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.AvailableCount > 0)
                {
                    // Found a queue with connectors.  Grab the top one.
                    // Check if the connector is still valid.
                    Connector = Queue.TakeAvailable();
                    Queue.AddBusy(Connector);
                }
            }

            if (Connector != null)
            {
                if (!Connector.IsValid())
                {
                    Queue.RemoveBusy(Connector);

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

                return(Connector);
            }

            lock (Queue)
            {
                if (Queue.AvailableCount + Queue.BusyCount < Connection.MaxPoolSize)
                {
                    Connector = new NpgsqlConnector(Connection);
                    Queue.AddBusy(Connector);
                }
            }

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

                try
                {
                    Connector.Open();
                }
                catch
                {
                    Queue.RemoveBusy(Connector);

                    Connector.Close();

                    throw;
                }

                // Meet the MinPoolSize requirement if needed.
                if (Connection.MinPoolSize > 1)
                {
                    lock (Queue)
                    {
                        while (Queue.AvailableCount + Queue.BusyCount < 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.EnqueueAvailable(Spare);
                        }
                    }
                }
            }

            return(Connector);
        }
コード例 #21
0
 private void CleanUpConnector(NpgsqlConnection Connection, NpgsqlConnector Connector)
 {
     new CleanUpConnectorDel(CleanUpConnectorMethod).BeginInvoke(Connection, Connector, null, null);
 }
コード例 #22
0
 /// <summary>
 /// Created only by NpgsqlCopyOutState.StartCopy()
 /// </summary>
 internal NpgsqlCopyOutStream(NpgsqlConnector context)
 {
     _context = context;
 }
コード例 #23
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #24
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Execute(NpgsqlConnector context, NpgsqlExecute execute)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #25
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void Parse(NpgsqlConnector context, NpgsqlParse parse)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #26
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #27
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void Startup(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #28
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
        // COPY methods

        protected virtual void StartCopy(NpgsqlConnector context, NpgsqlCopyFormat copyFormat)
        {
            throw new InvalidOperationException("Internal Error! " + this);
        }
コード例 #29
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public void TestNotify(NpgsqlConnector context)
 {
     //ZA  Hnotifytest CNOTIFY Z
     //Qlisten notifytest;notify notifytest;
     Stream stm = context.Stream;
     string uuidString = "uuid" + Guid.NewGuid().ToString("N");
     PGUtil.WriteString("Qlisten " + uuidString + ";notify " + uuidString + ";", stm);
     Queue<byte> buffer = new Queue<byte>();
     byte[] convertBuffer = new byte[36];
     for (; ; )
     {
         int newByte = stm.ReadByte();
         if (newByte == -1)
         {
             throw new EndOfStreamException();
         }
         buffer.Enqueue((byte)newByte);
         if (buffer.Count > 35)
         {
             buffer.CopyTo(convertBuffer, 0);
             if (ENCODING_UTF8.GetString(convertBuffer) == uuidString)
             {
                 for (; ; )
                 {
                     switch (stm.ReadByte())
                     {
                         case -1:
                             throw new EndOfStreamException();
                         case 'Z':
                             //context.Query(new NpgsqlCommand("UNLISTEN *", context));
                             using (NpgsqlCommand cmd = new NpgsqlCommand("UNLISTEN *", context))
                             {
                                 context.Query(cmd);
                             }
                             return;
                     }
                 }
             }
             else
             {
                 buffer.Dequeue();
             }
         }
     }
 }
コード例 #30
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual byte[] GetCopyData(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #31
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 ///<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;
 }
コード例 #32
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void SendCopyData(NpgsqlConnector context, byte[] buf, int off, int len)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #33
0
ファイル: NpgsqlReadyState.cs プロジェクト: zhxjdwh/revenj
 public override void Flush(NpgsqlConnector context)
 {
     _flushMessage.WriteToStream(context.Stream);
     context.Stream.Flush();
     ProcessBackendResponses(context);
 }
コード例 #34
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void SendCopyFail(NpgsqlConnector context, String message)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #35
0
ファイル: NpgsqlCopyOut.cs プロジェクト: zhxjdwh/revenj
 /// <summary>
 /// Given command is executed upon Start() and all requested copy data is written to toStream immediately.
 /// </summary>
 public NpgsqlCopyOut(NpgsqlCommand cmd, NpgsqlConnection conn, Stream toStream)
 {
     _context    = conn.Connector;
     _cmd        = cmd;
     _copyStream = toStream;
 }
コード例 #36
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 ///<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;
 }
コード例 #37
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void Describe(NpgsqlConnector context, NpgsqlDescribe describe)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #38
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 ///<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));
 }
コード例 #39
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void Execute(NpgsqlConnector context, NpgsqlExecute execute)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #40
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
        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;
                SCRAM scram = 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
                        case AuthenticationRequestType.AuthenticationSASL:
                            var saslAuthMechanism = PGUtil.ReadString(stream, queue);
                            if (saslAuthMechanism == "SCRAM-SHA-256")
                            {
                                stream.ReadByte();
                                scram = new SCRAM(saslAuthMechanism, context.UserName);

                                stream.WriteByte((byte)FrontEndMessageCode.SASL);
                                var schemeBytes             = Encoding.UTF8.GetBytes(scram.Scheme);
                                var clientFirstMessageBytes = Encoding.UTF8.GetBytes(scram.getClientFirstMessage());
                                PGUtil.WriteInt32(stream, 9 + schemeBytes.Length + clientFirstMessageBytes.Length);
                                stream.Write(schemeBytes, 0, schemeBytes.Length);
                                stream.WriteByte(0);
                                PGUtil.WriteInt32(stream, clientFirstMessageBytes.Length);
                                stream.Write(clientFirstMessageBytes, 0, clientFirstMessageBytes.Length);
                                stream.Flush();
                            }
                            else
                            {
                                throw new NpgsqlException("Only Scram SHA 256 is supported");
                            }
                            break;

                        case AuthenticationRequestType.AuthenticationSASLContinue:
                            if (scram == null)
                            {
                                throw new NpgsqlException("Invalid authentication message");
                            }
                            var continueData = new byte[authDataLength];
                            PGUtil.CheckedStreamRead(stream, continueData, 0, authDataLength);
                            scram.parseServerFirstMessage(Encoding.UTF8.GetString(continueData));
                            scram.Password = Encoding.UTF8.GetString(context.Password);
                            var mesageBytes = Encoding.UTF8.GetBytes(scram.getClientFinalMessage());
                            stream.WriteByte((byte)FrontEndMessageCode.SASL);
                            PGUtil.WriteInt32(stream, 4 + mesageBytes.Length);
                            stream.Write(mesageBytes, 0, mesageBytes.Length);
                            stream.Flush();
                            break;

                        case AuthenticationRequestType.AuthenticationSASLFinal:
                            if (scram == null)
                            {
                                throw new NpgsqlException("Invalid authentication message");
                            }
                            var finalData = new byte[authDataLength];
                            PGUtil.CheckedStreamRead(stream, finalData, 0, authDataLength);
                            scram.verifyServerSignature(Encoding.UTF8.GetString(finalData));
                            break;

                        default:
                            // Only AuthenticationClearTextPassword, AuthenticationMD5Password and AuthenticationSASL supported for now.
                            if (errors == null)
                            {
                                errors = new List <NpgsqlError>();
                            }
                            errors.Add(
                                new NpgsqlError(String.Format("Only AuthenticationClearTextPassword, AuthenticationMD5Password and AuthenticationSASL supported for now. Received: {0}", 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;
            }
        }
コード例 #41
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual byte[] GetCopyData(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #42
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Authenticate(NpgsqlConnector context, byte[] password)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #43
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public void Query(NpgsqlConnector context, NpgsqlCommand command)
 {
     IterateThroughAllResponses(QueryEnum(context, command));
 }
コード例 #44
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public void Query(NpgsqlConnector context, NpgsqlCommand command)
 {
     IterateThroughAllResponses(QueryEnum(context, command));
 }
コード例 #45
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public virtual void SendCopyFail(NpgsqlConnector context, String message)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #46
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void FunctionCall(NpgsqlConnector context, NpgsqlCommand command)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #47
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public NpgsqlRowDescription Sync(NpgsqlConnector context)
 {
     NpgsqlRowDescription lastDescription = null;
     foreach (IServerResponseObject obj in SyncEnum(context))
     {
         if (obj is NpgsqlRowDescription)
         {
             lastDescription = obj as NpgsqlRowDescription;
         }
         else
         {
             if (obj is IDisposable)
             {
                 (obj as IDisposable).Dispose();
             }
         }
     }
     return lastDescription;
 }
コード例 #48
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Parse(NpgsqlConnector context, NpgsqlParse parse)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #49
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public void TestConnector(NpgsqlConnector context)
 {
     EmptySync(context);
 }
コード例 #50
0
ファイル: NpgsqlReadyState.cs プロジェクト: zhxjdwh/revenj
 public override IEnumerable <IServerResponseObject> SyncEnum(NpgsqlConnector context)
 {
     _syncMessage.WriteToStream(context.Stream);
     context.Stream.Flush();
     return(ProcessBackendResponsesEnum(context, false));
 }
コード例 #51
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
        /// <summary>
        /// Checks for context socket availability.
        /// Socket.Poll supports integer as microseconds parameter.
        /// This limits the usable command timeout value
        /// to 2,147 seconds: (2,147 x 1,000,000 < max_int).
        /// In order to bypass this limit, the availability of
        /// the socket is checked in 2,147 seconds cycles
        /// </summary>
        /// <returns><c>true</c>, if for context socket availability was checked, <c>false</c> otherwise.</returns>
        /// <param name="context">Context.</param>
        /// <param name="selectMode">Select mode.</param>
        internal bool CheckForContextSocketAvailability(NpgsqlConnector context, SelectMode selectMode)
        {
            /* Socket.Poll supports integer as microseconds parameter.
             * This limits the usable command timeout value
             * to 2,147 seconds: (2,147 x 1,000,000 < max_int).
             */
            const int limitOfSeconds = 2147;

            bool socketPoolResponse = false;
            int secondsToWait = context.Mediator.CommandTimeout;

            /* In order to bypass this limit, the availability of
             * the socket is checked in 2,147 seconds cycles
             */
            while ((secondsToWait > limitOfSeconds) && (!socketPoolResponse))
            {    //
                socketPoolResponse = context.Socket.Poll(1000000 * limitOfSeconds, selectMode);
                secondsToWait -= limitOfSeconds;
            }

            return socketPoolResponse || context.Socket.Poll(1000000 * secondsToWait, selectMode);
        }
コード例 #52
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual IEnumerable <IServerResponseObject> SyncEnum(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #53
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
        ///<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
                        {
                        }
                        //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"));
                }
                return ProcessBackendResponses_Ver_3(context);

            }

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

                throw;
            }
        }
コード例 #54
0
 public override void Close(NpgsqlConnector context)
 {
     //DO NOTHING.
 }
コード例 #55
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
        protected IEnumerable<IServerResponseObject> ProcessBackendResponses_Ver_3(NpgsqlConnector context)
        {
            using (new ContextResetter(context))
            {
                Stream stream = context.Stream;
                NpgsqlMediator mediator = context.Mediator;

                NpgsqlRowDescription lastRowDescription = null;

                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 lastRowDescription = new NpgsqlRowDescription(stream, context.OidToNameMapping, context.CompatVersion, buffer, queue);
                            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 new ForwardsOnlyRow(new StringRowReader(lastRowDescription, stream, buffer, queue));
                            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));
                    }
                }
            }
        }
コード例 #56
0
 public NotificationThreadBlock(NpgsqlConnector connector)
 {
     (_connector = connector).StopNotificationThread();
 }
コード例 #57
0
ファイル: NpgsqlState.cs プロジェクト: instant-hrvoje/revenj
 public ContextResetter(NpgsqlConnector connector)
 {
     _connector = connector;
 }
コード例 #58
0
 internal NpgsqlContextHolder(NpgsqlConnector connector, NpgsqlState state)
 {
     this.connector = connector;
     this.state     = state;
 }
コード例 #59
0
ファイル: NpgsqlState.cs プロジェクト: mskalnik/revenj
 public virtual void Flush(NpgsqlConnector context)
 {
     throw new InvalidOperationException("Internal Error! " + this);
 }
コード例 #60
0
 public NpgsqlNetworkStream(NpgsqlConnector context, Socket socket, Boolean owner)
     : base(socket, owner)
 {
     mContext = context;
 }