Flush() private method

private Flush ( ) : void
return void
示例#1
0
        async Task AuthenticateMD5(string username, byte[] salt, bool async, CancellationToken cancellationToken)
        {
            var passwd = Settings.Password;

            if (passwd == null)
            {
                // No password was provided. Attempt to pull the password from the pgpass file.
                var matchingEntry = PgPassFile.LoadDefaultFile()?.GetFirstMatchingEntry(Settings.Host, Settings.Port, Settings.Database, Settings.Username);
                if (matchingEntry != null)
                {
                    Log.UsingPgpassFile();
                    passwd = matchingEntry.Password;
                }
            }

            if (passwd == null)
            {
                throw new NpgsqlException("No password has been provided but the backend requires one (in MD5)");
            }

            await PasswordMessage
            .CreateMD5(passwd, username, salt)
            .Write(WriteBuffer, async, cancellationToken);

            await WriteBuffer.Flush(async);

            await ReadExpecting <AuthenticationRequestMessage>(async);
        }
示例#2
0
        internal async Task WriteSASLInitialResponse(string mechanism, byte[] initialResponse, bool async)
        {
            var len = sizeof(byte) +                                                // Message code
                      sizeof(int) +                                                 // Length
                      PGUtil.UTF8Encoding.GetByteCount(mechanism) + sizeof(byte) +  // Mechanism plus null terminator
                      sizeof(int) +                                                 // Initial response length
                      (initialResponse?.Length ?? 0);                               // Initial response payload

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                await WriteBuffer.Flush(async);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(len - 1);

            WriteBuffer.WriteString(mechanism);
            WriteBuffer.WriteByte(0);   // null terminator
            if (initialResponse == null)
            {
                WriteBuffer.WriteInt32(-1);
            }
            else
            {
                WriteBuffer.WriteInt32(initialResponse.Length);
                WriteBuffer.WriteBytes(initialResponse);
            }
        }
示例#3
0
        async Task FlushAndWrite(WriteBuffer buf, bool async, CancellationToken cancellationToken)
        {
            await buf.Flush(async, cancellationToken);

            Debug.Assert(Length <= buf.WriteSpaceLeft, $"Message of type {GetType().Name} has length {Length} which is bigger than the buffer ({buf.WriteSpaceLeft})");
            WriteFully(buf);
        }
示例#4
0
        /// <summary>
        /// Starts writing a single row, must be invoked before writing any columns.
        /// </summary>
        public void StartRow()
        {
            CheckDisposed();

            if (_column != -1 && _column != NumColumns)
            {
                throw new InvalidOperationException("Row has already been started and must be finished");
            }

            if (_buf.WriteSpaceLeft < 2)
            {
                _buf.Flush();
            }
            _buf.WriteInt16(NumColumns);

            _column = 0;
        }
示例#5
0
        internal sealed override async Task WriteWithLength(object value, WriteBuffer buf, LengthCache lengthCache, NpgsqlParameter parameter,
                                                            bool async, CancellationToken cancellationToken)
        {
            if (value == null || value is DBNull)
            {
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async, cancellationToken);
                }
                buf.WriteInt32(-1);
                return;
            }

            var elementLen = ValidateAndGetLength(value, parameter);

            if (buf.WriteSpaceLeft < 4 + elementLen)
            {
                await buf.Flush(async, cancellationToken);
            }
            buf.WriteInt32(elementLen);
            Write(value, buf, parameter);
        }
示例#6
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            CheckDisposed();
            if (!CanWrite)
            {
                throw new InvalidOperationException("Stream not open for writing");
            }

            if (count == 0)
            {
                return;
            }

            EnsureDataMessage();

            if (count <= _writeBuf.WriteSpaceLeft)
            {
                _writeBuf.WriteBytes(buffer, offset, count);
                return;
            }

            try {
                // Value is too big. Flush whatever is in the buffer, then write a new CopyData
                // directly with the buffer.
                Flush();

                _writeBuf.WriteByte((byte)BackendMessageCode.CopyData);
                _writeBuf.WriteInt32(count + 4);
                _writeBuf.Flush();
                _writeBuf.DirectWrite(buffer, offset, count);
                EnsureDataMessage();
            } catch {
                _connector.Break();
                Cleanup();
                throw;
            }
        }
        async Task AuthenticateCleartext(bool async, CancellationToken cancellationToken)
        {
            var passwd = GetPassword();

            if (passwd == null)
            {
                throw new NpgsqlException("No password has been provided but the backend requires one (in cleartext)");
            }

            await PasswordMessage
            .CreateClearText(passwd)
            .Write(WriteBuffer, async, cancellationToken);

            await WriteBuffer.Flush(async);

            await ReadExpecting <AuthenticationRequestMessage>(async);
        }
        async Task AuthenticateMD5(string username, byte[] salt, bool async, CancellationToken cancellationToken)
        {
            var passwd = GetPassword();

            if (passwd == null)
            {
                throw new NpgsqlException("No password has been provided but the backend requires one (in MD5)");
            }

            await PasswordMessage
            .CreateMD5(passwd, username, salt)
            .Write(WriteBuffer, async, cancellationToken);

            await WriteBuffer.Flush(async);

            await ReadExpecting <AuthenticationRequestMessage>(async);
        }
示例#9
0
        internal async Task WritePassword(byte[] payload, int offset, int count, bool async)
        {
            if (WriteBuffer.WriteSpaceLeft < sizeof(byte) + sizeof(int))
            {
                await WriteBuffer.Flush(async);
            }
            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(sizeof(int) + count);

            if (count <= WriteBuffer.WriteSpaceLeft)
            {
                // The entire array fits in our WriteBuffer, copy it into the WriteBuffer as usual.
                WriteBuffer.WriteBytes(payload, offset, count);
                return;
            }

            await WriteBuffer.Flush(async);

            await WriteBuffer.DirectWrite(payload, offset, count, async);
        }
示例#10
0
        internal async Task WritePassword(byte[] payload, int offset, int count, bool async, CancellationToken cancellationToken = default)
        {
            if (WriteBuffer.WriteSpaceLeft < sizeof(byte) + sizeof(int))
            {
                await WriteBuffer.Flush(async, cancellationToken);
            }
            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(sizeof(int) + count);

            if (count <= WriteBuffer.WriteSpaceLeft)
            {
                // The entire array fits in our WriteBuffer, copy it into the WriteBuffer as usual.
                WriteBuffer.WriteBytes(payload, offset, count);
                return;
            }

            await WriteBuffer.Flush(async, cancellationToken);

            await WriteBuffer.DirectWrite(new ReadOnlyMemory <byte>(payload, offset, count), async, cancellationToken);
        }
        async Task AuthenticateSASL(List <string> mechanisms, bool async, CancellationToken cancellationToken)
        {
            // At the time of writing PostgreSQL only supports SCRAM-SHA-256
            if (!mechanisms.Contains("SCRAM-SHA-256"))
            {
                throw new NpgsqlException("No supported SASL mechanism found (only SCRAM-SHA-256 is supported for now). " +
                                          "Mechanisms received from server: " + string.Join(", ", mechanisms));
            }
            var mechanism = "SCRAM-SHA-256";

            var passwd = GetPassword() ??
                         throw new NpgsqlException($"No password has been provided but the backend requires one (in SASL/{mechanism})");

            // Assumption: the write buffer is big enough to contain all our outgoing messages
            var clientNonce = GetNonce();

            await new SASLInitialResponseMessage(mechanism, PGUtil.UTF8Encoding.GetBytes("n,,n=*,r=" + clientNonce))
            .Write(WriteBuffer, async, cancellationToken);
            await WriteBuffer.Flush(async, cancellationToken);

            var saslContinueMsg = await ReadExpecting <AuthenticationSASLContinueMessage>(async);

            if (saslContinueMsg.AuthRequestType != AuthenticationRequestType.AuthenticationSASLContinue)
            {
                throw new NpgsqlException("[SASL] AuthenticationSASLFinal message expected");
            }
            var firstServerMsg = new AuthenticationSCRAMServerFirstMessage(saslContinueMsg.Payload);

            if (!firstServerMsg.Nonce.StartsWith(clientNonce))
            {
                throw new InvalidOperationException("[SCRAM] Malformed SCRAMServerFirst message: server nonce doesn't start with client nonce");
            }

            var scramFinalClientMsg = new SCRAMClientFinalMessage(passwd, firstServerMsg.Nonce, firstServerMsg.Salt, firstServerMsg.Iteration, clientNonce);
            await scramFinalClientMsg.Write(WriteBuffer, async, cancellationToken);

            await WriteBuffer.Flush(async, cancellationToken);

            var saslFinalServerMsg = await ReadExpecting <AuthenticationSASLFinalMessage>(async);

            if (saslFinalServerMsg.AuthRequestType != AuthenticationRequestType.AuthenticationSASLFinal)
            {
                throw new NpgsqlException("[SASL] AuthenticationSASLFinal message expected");
            }
            var scramFinalServerMsg = new AuthenticationSCRAMServerFinalMessage(saslFinalServerMsg.Payload);

            if (scramFinalServerMsg.ServerSignature != Convert.ToBase64String(scramFinalClientMsg.ServerSignature))
            {
                throw new NpgsqlException("[SCRAM] Unable to verify server signature");
            }

            var okMsg = await ReadExpecting <AuthenticationRequestMessage>(async);

            if (okMsg.AuthRequestType != AuthenticationRequestType.AuthenticationOk)
            {
                throw new NpgsqlException("[SASL] Expected AuthenticationOK message");
            }

            string GetNonce()
            {
                var nonceLength = 18;
                var rncProvider = RandomNumberGenerator.Create();
                var nonceBytes  = new byte[nonceLength];

                rncProvider.GetBytes(nonceBytes);
                return(Convert.ToBase64String(nonceBytes));
            }
        }
示例#12
0
        void DoWrite <T>(TypeHandler handler, [CanBeNull] T value)
        {
            try
            {
                if (_buf.WriteSpaceLeft < 4)
                {
                    FlushAndStartDataMessage();
                }

                var asObject = (object)value;  // TODO: Implement boxless writing in the future
                if (asObject == null)
                {
                    _buf.WriteInt32(-1);
                    _column++;
                    return;
                }

                _dummyParam.ConvertedValue = null;

                var asSimple = handler as ISimpleTypeHandler;
                if (asSimple != null)
                {
                    var len = asSimple.ValidateAndGetLength(asObject, _dummyParam);
                    _buf.WriteInt32(len);
                    if (_buf.WriteSpaceLeft < len)
                    {
                        Contract.Assume(_buf.Size >= len);
                        FlushAndStartDataMessage();
                    }
                    asSimple.Write(asObject, _buf, _dummyParam);
                    _column++;
                    return;
                }

                var asChunking = handler as IChunkingTypeHandler;
                if (asChunking != null)
                {
                    _lengthCache.Clear();
                    var len = asChunking.ValidateAndGetLength(asObject, ref _lengthCache, _dummyParam);
                    _buf.WriteInt32(len);

                    // If the type handler used the length cache, rewind it to skip the first position:
                    // it contains the entire value length which we already have in len.
                    if (_lengthCache.Position > 0)
                    {
                        _lengthCache.Rewind();
                        _lengthCache.Position++;
                    }

                    asChunking.PrepareWrite(asObject, _buf, _lengthCache, _dummyParam);
                    var directBuf = new DirectBuffer();
                    while (!asChunking.Write(ref directBuf))
                    {
                        Flush();

                        // The following is an optimization hack for writing large byte arrays without passing
                        // through our buffer
                        if (directBuf.Buffer != null)
                        {
                            len = directBuf.Size == 0 ? directBuf.Buffer.Length : directBuf.Size;
                            _buf.WritePosition = 1;
                            _buf.WriteInt32(len + 4);
                            _buf.Flush();
                            _writingDataMsg = false;
                            _buf.DirectWrite(directBuf.Buffer, directBuf.Offset, len);
                            directBuf.Buffer = null;
                            directBuf.Size   = 0;
                        }
                        EnsureDataMessage();
                    }
                    _column++;
                    return;
                }

                throw PGUtil.ThrowIfReached();
            }
            catch
            {
                _connector.Break();
                Cleanup();
                throw;
            }
        }
示例#13
0
 internal Task Flush(bool async) => WriteBuffer.Flush(async);
示例#14
0
 internal void Flush() => WriteBuffer.Flush(false).GetAwaiter().GetResult();
示例#15
0
 public override void Flush()
 {
     CheckDisposed();
     _writeBuf.Flush();
 }
示例#16
0
 internal Task Flush(bool async, CancellationToken cancellationToken = default) => WriteBuffer.Flush(async, cancellationToken);