public async Task CanCancelFlushAsyncWithCancelPendingFlushStreamFlushAsyncThrows()
        {
            var stream = new CancelledWritesStream();

            stream.WaitForWriteTask.TrySetResult(null);

            PipeWriter writer = PipeWriter.Create(stream);

            writer.WriteEmpty(10);
            ValueTask <FlushResult> task = writer.FlushAsync();

            Assert.False(task.IsCompleted);

            writer.CancelPendingFlush();

            stream.WaitForFlushTask.TrySetResult(null);

            FlushResult result = await task;

            Assert.True(result.IsCanceled);
            writer.Complete();
        }
        public async Task CanCancelFlushAsyncWithCancellationTokenWhenStreamWriteAsyncThrows()
        {
            var stream = new CancelledWritesStream();

            stream.WaitForFlushTask.TrySetResult(null);

            var        cts    = new CancellationTokenSource();
            PipeWriter writer = PipeWriter.Create(stream);

            writer.WriteEmpty(10);
            ValueTask <FlushResult> task = writer.FlushAsync(cts.Token);

            Assert.False(task.IsCompleted);

            cts.Cancel();

            stream.WaitForWriteTask.TrySetResult(null);

            await Assert.ThrowsAsync <OperationCanceledException>(async() => await task);

            writer.Complete();
        }
示例#3
0
        public async Task WriteMessageAsync_HasCustomCompressionLevel_WriteCompressedDataWithLevel()
        {
            // Arrange
            var mockCompressionProvider = new MockCompressionProvider();

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers[GrpcProtocolConstants.MessageAcceptEncodingHeader] = "Mock";

            var context = HttpContextServerCallContextHelper.CreateServerCallContext(
                httpContext,
                responseCompressionAlgorithm: "Mock",
                responseCompressionLevel: System.IO.Compression.CompressionLevel.Optimal,
                compressionProviders: new List <ICompressionProvider>
            {
                mockCompressionProvider
            });

            context.Initialize();

            var ms         = new MemoryStream();
            var pipeWriter = PipeWriter.Create(ms);

            // Act
            await pipeWriter.WriteMessageAsync(new TestData(new byte[] { 0x10 }), context, TestDataMarshaller.ContextualSerializer, canFlush : true);

            // Assert
            Assert.AreEqual(System.IO.Compression.CompressionLevel.Optimal, mockCompressionProvider.ArgumentCompression);

            var messageData = ms.ToArray();

            Assert.AreEqual(1, messageData[0]);  // compression
            Assert.AreEqual(21, messageData[4]); // message length

            byte[] result = Decompress(mockCompressionProvider, messageData);
            Assert.AreEqual(1, result.Length);
            Assert.AreEqual(0x10, result[0]);
        }
示例#4
0
        public async Task WriteMessageAsync_EmptyMessage_WriteMessageWithNoData()
        {
            // Arrange
            var ms         = new MemoryStream();
            var pipeWriter = PipeWriter.Create(ms);

            // Act
            await pipeWriter.WriteMessageAsync(Array.Empty <byte>(), TestServerCallContext, Marshaller.ContextualSerializer, canFlush : true);

            // Assert
            var messageData = ms.ToArray();

            CollectionAssert.AreEqual(
                new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x00,     // length = 0
            },
                messageData);
        }
示例#5
0
        public async Task SaveMemoryTable(MemoryTable skipList)
        {
            using var fs = System.IO.File.Open(_fileName, System.IO.FileMode.CreateNew);
            var pipeWriter = PipeWriter.Create(fs);

            var iterator = skipList.GetEnumerator();

            if (!iterator.MoveNext())
            {
                throw new ArgumentOutOfRangeException("Empty iterator nothing to save");
            }


            var itemCount = 0;

            WriteBlocks(pipeWriter, iterator, ref itemCount);
            await pipeWriter.FlushAsync();

            WriteTOC(pipeWriter, _metaData.FirstKey.Span, _metaData.LastKey.Span, itemCount);
            await pipeWriter.FlushAsync();

            await pipeWriter.CompleteAsync();
        }
示例#6
0
        public static void WriteMessage <T>(Stream stream, T message, string?compressionEncoding = null, List <ICompressionProvider>?compressionProviders = null) where T : class, IMessage
        {
            compressionProviders = compressionProviders ?? new List <ICompressionProvider>
            {
                new GzipCompressionProvider(CompressionLevel.Fastest)
            };

            var pipeWriter = PipeWriter.Create(stream);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers[GrpcProtocolConstants.MessageAcceptEncodingHeader] = compressionEncoding;

            var serverCallContext = HttpContextServerCallContextHelper.CreateServerCallContext(
                httpContext: httpContext,
                compressionProviders: compressionProviders,
                responseCompressionAlgorithm: compressionEncoding);

            serverCallContext.Initialize();

            pipeWriter.WriteMessageAsync(message, serverCallContext, (r, c) => c.Complete(r.ToByteArray()), canFlush: true).GetAwaiter().GetResult();
            stream.Seek(0, SeekOrigin.Begin);
        }
        public async Task WriteStreamedMessageAsync_OneByteMessage_WriteData()
        {
            // Arrange
            var ms         = new MemoryStream();
            var pipeWriter = PipeWriter.Create(ms);

            // Act
            await pipeWriter.WriteStreamedMessageAsync(new TestData(new byte[] { 0x10 }), HttpContextServerCallContextHelper.CreateServerCallContext(), TestDataMarshaller.ContextualSerializer);

            // Assert
            var messageData = ms.ToArray();

            CollectionAssert.AreEqual(
                new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x01,     // length = 1
                0x10
            },
                messageData);
        }
        public async Task WriteAsyncThrowsDuringMultiSegmentWriteCompleteReturnsAllMemory()
        {
            using (var pool = new DisposeTrackingBufferPool())
            {
                var        stream  = new ThrowAfterNWritesStream(1);
                var        options = new StreamPipeWriterOptions(pool);
                PipeWriter writer  = PipeWriter.Create(stream, options);
                writer.WriteEmpty(pool.MaxBufferSize);
                writer.WriteEmpty(pool.MaxBufferSize);
                writer.WriteEmpty(pool.MaxBufferSize);

                Assert.Equal(3, pool.CurrentlyRentedBlocks);
                Assert.Equal(0, pool.DisposedBlocks);

                await Assert.ThrowsAsync <InvalidOperationException>(async() => await writer.FlushAsync());

                Assert.Equal(2, pool.CurrentlyRentedBlocks);
                Assert.Equal(1, pool.DisposedBlocks);

                writer.Complete();
                Assert.Equal(0, pool.CurrentlyRentedBlocks);
                Assert.Equal(3, pool.DisposedBlocks);
            }
        }
        public async Task WriteMessageAsync_OneByteMessage_WriteData()
        {
            // Arrange
            var ms         = new MemoryStream();
            var pipeWriter = PipeWriter.Create(ms);

            // Act
            await pipeWriter.WriteMessageAsync(new byte[] { 0x10 }, TestServerCallContext, flush : true);

            // Assert
            var messageData = ms.ToArray();

            CollectionAssert.AreEqual(
                new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x01,     // length = 1
                0x10
            },
                messageData);
        }
        public async Task WriteMessageAsync_HasCustomCompressionLevel_WriteCompressedDataWithLevel()
        {
            // Arrange
            var mockCompressionProvider = new MockCompressionProvider();
            var serviceOptions          = new GrpcServiceOptions
            {
                ResponseCompressionAlgorithm = "Mock",
                ResponseCompressionLevel     = System.IO.Compression.CompressionLevel.Optimal,
                CompressionProviders         =
                {
                    mockCompressionProvider
                }
            };

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers[GrpcProtocolConstants.MessageAcceptEncodingHeader] = "Mock";

            var context = HttpContextServerCallContextHelper.CreateServerCallContext(httpContext, serviceOptions);

            context.Initialize();

            var ms         = new MemoryStream();
            var pipeWriter = PipeWriter.Create(ms);

            // Act
            await pipeWriter.WriteMessageAsync(new byte[] { 0x10 }, context, flush : true);

            // Assert
            Assert.AreEqual(System.IO.Compression.CompressionLevel.Optimal, mockCompressionProvider.ArgumentCompression);

            var messageData = ms.ToArray();

            Assert.AreEqual(1, messageData[0]);  // compression
            Assert.AreEqual(21, messageData[4]); // message length
        }
示例#11
0
        public async Task WriteMessageAsync_EmptyMessage_WriteMessageWithNoData()
        {
            // Arrange
            var ms         = new MemoryStream();
            var pipeWriter = new Base64PipeWriter(PipeWriter.Create(ms));

            // Act
            await pipeWriter.WriteMessageAsync(new EchoRequest(), HttpContextServerCallContextHelper.CreateServerCallContext(), MarshallerEchoRequest.ContextualSerializer, canFlush : true);

            // Assert
            var base64      = Encoding.UTF8.GetString(ms.ToArray());
            var messageData = Convert.FromBase64String(base64);

            CollectionAssert.AreEqual(
                new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x00,     // length = 0
            },
                messageData);
        }
示例#12
0
        public async Task WriteAsync_BufferHintWriteOptions_DoesNotFlush()
        {
            // Arrange
            var ms = new MemoryStream();

            var httpContext = new DefaultHttpContext();

            httpContext.Features.Set <IHttpResponseBodyFeature>(new TestResponseBodyFeature(PipeWriter.Create(ms)));
            var serverCallContext = HttpContextServerCallContextHelper.CreateServerCallContext(httpContext);
            var writer            = new HttpContextStreamWriter <HelloReply>(serverCallContext, MessageHelpers.ServiceMethod.ResponseMarshaller.ContextualSerializer);

            serverCallContext.WriteOptions = new WriteOptions(WriteFlags.BufferHint);

            // Act 1
            await writer.WriteAsync(new HelloReply
            {
                Message = "Hello world 1"
            });

            // Assert 1
            Assert.AreEqual(0, ms.Length);

            // Act 2
            await writer.WriteAsync(new HelloReply
            {
                Message = "Hello world 2"
            });

            // Assert 2
            Assert.AreEqual(0, ms.Length);

            await httpContext.Response.BodyWriter.FlushAsync();

            ms.Seek(0, SeekOrigin.Begin);
            var pipeReader = PipeReader.Create(ms);

            var writtenMessage1 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.AreEqual("Hello world 1", writtenMessage1 !.Message);
            var writtenMessage2 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.AreEqual("Hello world 2", writtenMessage2 !.Message);
        }
示例#13
0
 public DuplexStreamPipe(Stream stream)
 {
     Input  = PipeReader.Create(stream, s_readerOpts);
     Output = PipeWriter.Create(stream, s_writerOpts);
 }
示例#14
0
        public async Task OperationCancelledExceptionNotSwallowedIfNotThrownFromSpecifiedToken()
        {
            PipeWriter writer = PipeWriter.Create(new ThrowsOperationCanceledExceptionStream());

            await Assert.ThrowsAsync <OperationCanceledException>(async() => await writer.WriteAsync(new byte[1]));
        }
示例#15
0
 public static PipeWriter AsPipeWriter(this Stream stream, StreamPipeWriterOptions?options = null)
 {
     return(PipeWriter.Create(stream, options));
 }
示例#16
0
        public async Task <bool> ConnectAsync()
        {
            try
            {
                Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                {
                    NoDelay = ClientOption.NoDelay
                };
                await Socket.ConnectAsync(new IPEndPoint(IPAddress.Parse(ClientOption.Ip), ClientOption.Port));

                RemoteEndPoint = Socket.RemoteEndPoint;
                LocalEndPoint  = Socket.LocalEndPoint;
                if (ClientOption.Security == SslProtocols.None)
                {
                    Stream = new NetworkStream(Socket, true);
                    Reader = PipeReader.Create(Stream);
                    Writer = PipeWriter.Create(Stream);

                    IsConnected = true;
                    LogHelper.Info($"连接服务器[{ClientOption.Ip}:{ClientOption.Port}]成功");
                    OnConnected?.Invoke(this);
                    ProcessReadAsync();

                    return(true);
                }
                else
                {
                    ClientOption.SslClientAuthenticationOptions.RemoteCertificateValidationCallback = SSLValidationCallback;
                    var sslStream         = new SslStream(new NetworkStream(Socket, true), false);
                    var cancelTokenSource = new CancellationTokenSource();
                    cancelTokenSource.CancelAfter(5000);
                    return(await sslStream.AuthenticateAsClientAsync(ClientOption.SslClientAuthenticationOptions, cancelTokenSource.Token).ContinueWith(t =>
                    {
                        if (sslStream.IsAuthenticated)
                        {
                            Stream = sslStream;
                            Reader = PipeReader.Create(Stream);
                            Writer = PipeWriter.Create(Stream);

                            IsConnected = true;
                            LogHelper.Info($"连接服务器[{ClientOption.Ip}:{ClientOption.Port}]成功");
                            OnConnected?.Invoke(this);
                            ProcessReadAsync();

                            return true;
                        }
                        else
                        {
                            if (t.IsCanceled)
                            {
                                LogHelper.Error($"连接{RemoteEndPoint}证书验证超时,关闭连接");
                            }
                            Close();
                            return false;
                        }
                    }));
                }
            }
            catch (Exception ex)
            {
                if (IsConnected)
                {
                    Close();
                }
                IsConnected = false;
                LogHelper.Error($"客户端异常:{ex}");

                return(false);
            }
        }
示例#17
0
        /// <summary>
        /// 启动服务
        /// </summary>
        /// <returns></returns>
        public virtual Task <bool> StartAysnc()
        {
            return(Task.Run(() =>
            {
                bool isSuccess = false;
                try
                {
                    if (ServerOption == null)
                    {
                        throw new ArgumentException("ServerOption服务配置尚未配置");
                    }
                    IPEndPoint iPEndPoint = new IPEndPoint(ServerOption.Ip == "Any" ? IPAddress.Any : IPAddress.Parse(ServerOption.Ip), ServerOption.Port);
                    if (ServerOption.ProtocolType == ProtocolType.Tcp)
                    {
                        #region TCP
                        Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                        {
                            NoDelay = ServerOption.NoDelay
                        };
                        Socket.Bind(iPEndPoint);
                        //开始监听
                        Socket.Listen(ServerOption.BackLog);
                        //开启一个线程接收客户端连接
                        Task.Run(async() =>
                        {
                            while (true)
                            {
                                var client = await Socket.AcceptAsync();
                                //构造客户端Session
                                var session = new TSession
                                {
                                    Socket = client,

                                    LocalEndPoint = client.LocalEndPoint,
                                    RemoteEndPoint = client.RemoteEndPoint
                                };
                                //非SSL
                                if (ServerOption.Security == SslProtocols.None)
                                {
                                    //Socket转字节流对象
                                    session.Stream = new NetworkStream(session.Socket, true);
                                    //字节流绑定到Pipe管道(高性能缓冲区)
                                    session.Reader = PipeReader.Create(session.Stream); //读取数据端
                                    session.Writer = PipeWriter.Create(session.Stream); //发送数据端

                                    //添加到Session容器
                                    SessionContainer.Add(session);
                                    OnConnected?.Invoke(session);
                                    //开启一个线程异步接收这个连接的数据
                                    ProcessReadAsync(session);
                                }
                                else//SSL
                                {
                                    //绑定SSL认证回调
                                    ServerOption.SslServerAuthenticationOptions.RemoteCertificateValidationCallback = SSLValidationCallback;
                                    //加密传输字节流
                                    var sslStream = new SslStream(new NetworkStream(session.Socket, true), false);
                                    var cancelTokenSource = new CancellationTokenSource();
                                    //SSL认证超时时间为5s
                                    cancelTokenSource.CancelAfter(5000);
                                    await sslStream.AuthenticateAsServerAsync(ServerOption.SslServerAuthenticationOptions, cancelTokenSource.Token).ContinueWith(t =>
                                    {
                                        if (sslStream.IsAuthenticated)
                                        {
                                            //验证成功
                                            session.Stream = sslStream;
                                            //字节流绑定到Pipe管道(高性能缓冲区)
                                            session.Reader = PipeReader.Create(session.Stream); //读取数据端
                                            session.Writer = PipeWriter.Create(session.Stream); //发送数据端

                                            //添加到Session容器
                                            SessionContainer.Add(session);
                                            OnConnected?.Invoke(session);
                                            //开启一个线程异步接收这个连接的数据
                                            ProcessReadAsync(session);
                                        }
                                        else
                                        {
                                            if (t.IsCanceled)
                                            {
                                                LogHelper.Error($"连接{session.RemoteEndPoint}证书验证超时,关闭连接");
                                            }
                                            Close(session);
                                        }
                                    });
                                }
                            }
                        });
                        #endregion
                    }
                    else if (ServerOption.ProtocolType == ProtocolType.Udp)
                    {
                        #region UDP
                        Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                        Socket.Bind(iPEndPoint);
                        EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
                        var session = new TSession
                        {
                            Socket = Socket,
                            LocalEndPoint = Socket.LocalEndPoint
                        };
                        //异步接收这个连接的数据
                        Socket.BeginReceiveFrom(session.Data, 0, session.Data.Length, SocketFlags.None, ref remoteEP, UdpReceiveCallback, session);
                        #endregion
                    }
                    else
                    {
                        throw new Exception("不支持的传输协议");
                    }

                    isSuccess = true;
                }
                catch (Exception ex)
                {
                    LogHelper.Error($"【{ServerOption.Port}】端口启动监听异常:{ex}");
                }

                return isSuccess;
            }));
        }
 public ProtocolWriter(Stream stream) :
     this(PipeWriter.Create(stream))
 {
 }
示例#19
0
        /// <summary>
        /// 异步处理Socket SSL握手
        /// </summary>
        /// <param name="socket"></param>
        private async void ProcessSocketAsync(Socket socket)
        {
            await Task.Run(() =>
            {
                try
                {
                    TSession session = new TSession()
                    {
                        Server = this,
                        Socket = socket,
                        Remote = socket.RemoteEndPoint.ToString(),
                        Local  = socket.LocalEndPoint.ToString()
                    };

                    // Create a PipeReader over the network stream
                    if (ServerOption.Security == SslProtocols.None)
                    {
                        session.Stream = new NetworkStream(session.Socket, true);

                        session.Reader = PipeReader.Create(session.Stream);
                        session.Writer = PipeWriter.Create(session.Stream);

                        m_sessionManager.Add(session);
                        OnConnected?.Invoke(session);
                        ProcessReadAsync(session);
                    }
                    else
                    {
                        ServerOption.SslServerAuthenticationOptions.RemoteCertificateValidationCallback = SSLValidationCallback;
                        var sslStream         = new SslStream(new NetworkStream(session.Socket, true), false);
                        var cancelTokenSource = new CancellationTokenSource();
                        cancelTokenSource.CancelAfter(5000);
                        _ = sslStream.AuthenticateAsServerAsync(ServerOption.SslServerAuthenticationOptions, cancelTokenSource.Token).ContinueWith(t =>
                        {
                            if (sslStream.IsAuthenticated)
                            {
                                session.Stream = sslStream;

                                session.Reader = PipeReader.Create(session.Stream);
                                session.Writer = PipeWriter.Create(session.Stream);

                                m_sessionManager.Add(session);
                                OnConnected?.Invoke(session);
                                ProcessReadAsync(session);
                            }
                            else
                            {
                                if (t.IsCanceled)
                                {
                                    HandleLog.WriteLine($"连接{session.Remote}证书验证超时,关闭连接");
                                }
                                session.Close();
                            }
                        });
                    }
                }
                catch (Exception ex)
                {
                    HandleLog.WriteLine($"【{ServerOption.Port}】服务端口处理连接异常:{ex}");
                    socket?.Close();
                }
            });
        }
示例#20
0
 public DuplexPipeStreamAdapter(IDuplexPipe duplexPipe, StreamPipeReaderOptions readerOptions, StreamPipeWriterOptions writerOptions, Func <Stream, TStream> createStream) : base(duplexPipe.Input, duplexPipe.Output)
 {
     Stream = createStream(this);
     Input  = PipeReader.Create(Stream, readerOptions);
     Output = PipeWriter.Create(Stream, writerOptions);
 }
示例#21
0
        private async Task <Stream> HandleInitialMessage(Stream stream, MessageBuilder messageBuilder)
        {
            var reader = PipeReader.Create(stream);
            var writer = PipeWriter.Create(stream);

            var streamToUse = stream;

            var messageReader = new MessageReader();

            var initialMessage = await messageReader.ReadInitialMessage(reader, _token);

            if (initialMessage is SSLRequest)
            {
                if (_serverCertificate == null)
                {
                    await writer.WriteAsync(messageBuilder.SSLResponse(false), _token);

                    initialMessage = await messageReader.ReadInitialMessage(reader, _token);
                }
                else
                {
                    await writer.WriteAsync(messageBuilder.SSLResponse(true), _token);

                    var sslStream = new SslStream(stream, false, (sender, certificate, chain, errors) => true);

                    await sslStream.AuthenticateAsServerAsync(new SslServerAuthenticationOptions
                    {
                        ServerCertificate         = _serverCertificate,
                        ClientCertificateRequired = false
                    }, _token);

                    streamToUse = sslStream;

                    var encryptedReader = PipeReader.Create(sslStream);
                    initialMessage = await messageReader.ReadInitialMessage(encryptedReader, _token);
                }
            }

            switch (initialMessage)
            {
            case StartupMessage startupMessage:
                _clientOptions = startupMessage.ClientOptions;
                break;

            case SSLRequest:
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ProtocolViolation,
                                            "SSLRequest received twice"), _token);

                break;

            case Cancel cancel:
                // TODO: Support Cancel message
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.FeatureNotSupported,
                                            "Cancel message support not implemented."), _token);

                break;

            default:
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ProtocolViolation,
                                            "Invalid first message received"), _token);

                break;
            }

            return(streamToUse);
        }
示例#22
0
        /// <summary>
        /// 连接TCP服务
        /// </summary>
        /// <returns></returns>
        public async Task <bool> ConnectAsync()
        {
            try
            {
                if (ClientOption == null)
                {
                    throw new ArgumentException("ClientOption客户端配置尚未配置");
                }
                Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                {
                    NoDelay = ClientOption.NoDelay
                };
                //异步连接
                await Socket.ConnectAsync(new IPEndPoint(IPAddress.Parse(ClientOption.Ip), ClientOption.Port));

                RemoteEndPoint = Socket.RemoteEndPoint;
                LocalEndPoint  = Socket.LocalEndPoint;
                //非SSL
                if (ClientOption.Security == SslProtocols.None)
                {
                    //Socket转字节流对象
                    Stream = new NetworkStream(Socket, true);
                    //字节流绑定到Pipe管道(高性能缓冲区)
                    Reader = PipeReader.Create(Stream); //读取数据端
                    Writer = PipeWriter.Create(Stream); //发送数据端

                    IsConnected = true;
                    LogHelper.Info($"连接服务器[{ClientOption.Ip}:{ClientOption.Port}]成功");
                    OnConnected?.Invoke(this);
                    //开始异步接收数据
                    ProcessReadAsync();

                    return(true);
                }
                else
                {
                    //SSL回调
                    ClientOption.SslClientAuthenticationOptions.RemoteCertificateValidationCallback = SSLValidationCallback;
                    //加密传输字节流
                    var sslStream         = new SslStream(new NetworkStream(Socket, true), false);
                    var cancelTokenSource = new CancellationTokenSource();
                    //SSL认证超时时间为5s
                    cancelTokenSource.CancelAfter(5000);
                    return(await sslStream.AuthenticateAsClientAsync(ClientOption.SslClientAuthenticationOptions, cancelTokenSource.Token).ContinueWith(t =>
                    {
                        if (sslStream.IsAuthenticated)
                        {
                            //验证成功
                            Stream = sslStream;
                            //字节流绑定到Pipe管道(高性能缓冲区)
                            Reader = PipeReader.Create(Stream); //读取数据端
                            Writer = PipeWriter.Create(Stream); //发送数据端

                            IsConnected = true;
                            LogHelper.Info($"连接服务器[{ClientOption.Ip}:{ClientOption.Port}]成功");
                            OnConnected?.Invoke(this);
                            //开始异步接收数据
                            ProcessReadAsync();

                            return true;
                        }
                        else
                        {
                            //验证失败
                            if (t.IsCanceled)
                            {
                                LogHelper.Error($"连接{RemoteEndPoint}证书验证超时,关闭连接");
                            }
                            //关闭连接
                            Close();
                            return false;
                        }
                    }));
                }
            }
            catch (Exception ex)
            {
                //处理异常直接关闭客户端
                if (IsConnected)
                {
                    Close();
                }
                IsConnected = false;
                LogHelper.Error($"客户端异常:{ex}");

                return(false);
            }
        }
        public async Task TestRoundtrip(string filename)
        {
            // Load
            byte[] decompressed = await File.ReadAllBytesAsync(filename);

            if (filename.EndsWith(".fse", StringComparison.OrdinalIgnoreCase))
            {
                var ms = new MemoryStream();
                await PipeHelper.DecompressAsync(PipeReader.Create(new MemoryStream(decompressed)), PipeWriter.Create(new NoDisposableStream(ms)));

                decompressed = ms.ToArray();
            }

            // Compress
            var compressedStream = new MemoryStream();
            await PipeHelper.CompressAsync(PipeReader.Create(new MemoryStream(decompressed)), PipeWriter.Create(new NoDisposableStream(compressedStream)));

            // Decompress
            compressedStream.Seek(0, SeekOrigin.Begin);
            var decompressedStream = new MemoryStream();
            await PipeHelper.DecompressAsync(PipeReader.Create(compressedStream), PipeWriter.Create(new NoDisposableStream(decompressedStream)));

            // Compare
            decompressedStream.ToArray().AsSpan().SequenceCompareTo(decompressed);
        }
        public async Task WriteAsync_DefaultWriteOptions_Flushes()
        {
            // Arrange
            var ms = new MemoryStream();

            var httpContext = new DefaultHttpContext();

            httpContext.Features.Set <IResponseBodyPipeFeature>(new TestResponseBodyPipeFeature(PipeWriter.Create(ms)));
            var serverCallContext = HttpContextServerCallContextHelper.CreateServerCallContext(httpContext);
            var writer            = new HttpContextStreamWriter <HelloReply>(serverCallContext, (message) => message.ToByteArray());

            // Act 1
            await writer.WriteAsync(new HelloReply
            {
                Message = "Hello world 1"
            });

            // Assert 1
            Assert.AreEqual(20, ms.Length);

            // Act 2
            await writer.WriteAsync(new HelloReply
            {
                Message = "Hello world 2"
            });

            // Assert 2
            Assert.AreEqual(40, ms.Length);

            ms.Seek(0, SeekOrigin.Begin);
            var pipeReader = PipeReader.Create(ms);

            var writtenMessage1 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.AreEqual("Hello world 1", writtenMessage1 !.Message);
            var writtenMessage2 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.AreEqual("Hello world 2", writtenMessage2 !.Message);
        }
示例#25
0
        public override async ValueTask <byte[]> ResolveAsync(byte[] Query)
        {
            using var Socket = new Socket(SocketType.Stream, ProtocolType.Tcp)
                  {
                      ReceiveTimeout = (int)Options.CurrentValue.Timeout.TotalMilliseconds,
                      SendTimeout    = (int)Options.CurrentValue.Timeout.TotalMilliseconds
                  };

            //await Socket.ConnectAsync(Options.CurrentValue.IPv4EndPoint);

            //var Prefix = new byte[2];

            //BinaryPrimitives.WriteUInt16BigEndian(Prefix, (ushort)Query.Length);

            //await Socket.SendAsync(Prefix, SocketFlags.None);

            //await Socket.SendAsync(Query, SocketFlags.None);

            //await Socket.ReceiveAsync(Prefix, SocketFlags.None);

            //var Size = BinaryPrimitives.ReadUInt16BigEndian(Prefix);

            //var Buffer = new byte[Size];

            //await Socket.ReliableReceiveAsync(Buffer);

            //return Buffer;

            await Socket.ConnectAsync(Options.CurrentValue.IPv4EndPoint);

            var Stream = new NetworkStream(Socket);

            var Reader = PipeReader.Create(Stream);

            var Writer = PipeWriter.Create(Stream);

            var CancellationTokenSource = new CancellationTokenSource(Options.CurrentValue.Timeout);

            var Prefix = new byte[2];

            BinaryPrimitives.WriteUInt16BigEndian(Prefix, (ushort)Query.Length);

            await Writer.WriteAsync(Prefix, CancellationTokenSource.Token);

            await Writer.WriteAsync(Query, CancellationTokenSource.Token);

            await Writer.FlushAsync(CancellationTokenSource.Token);

            while (true)
            {
                var Result = await Reader.ReadAsync(CancellationTokenSource.Token);

                if (Result.IsCompleted)
                {
                    var Size = BinaryPrimitives.ReadUInt16BigEndian(Result.Buffer.FirstSpan.Slice(0, 2));

                    return(Result.Buffer.FirstSpan.Slice(2, Size).ToArray());
                }

                await Task.Delay(100, CancellationTokenSource.Token);
            }
        }
示例#26
0
        public async Task WriteAsync_WriteInProgress_Error()
        {
            // Arrange
            var tcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            var httpContext = new DefaultHttpContext();

            httpContext.Features.Set <IHttpResponseBodyFeature>(new TestResponseBodyFeature(PipeWriter.Create(new MemoryStream()), startAsyncTask: tcs.Task));
            var serverCallContext = HttpContextServerCallContextHelper.CreateServerCallContext(httpContext);
            var writer            = new HttpContextStreamWriter <HelloReply>(serverCallContext, MessageHelpers.ServiceMethod.ResponseMarshaller.ContextualSerializer);

            // Act
            _ = writer.WriteAsync(new HelloReply
            {
                Message = "Hello world 1"
            });

            var ex = await ExceptionAssert.ThrowsAsync <InvalidOperationException>(() =>
            {
                return(writer.WriteAsync(new HelloReply
                {
                    Message = "Hello world 2"
                }));
            });

            // Assert
            Assert.AreEqual("Can't write the message because the previous write is in progress.", ex.Message);
        }
示例#27
0
 internal StreamDuplexPipe(Stream stream)
 {
     this.stream = stream;
     this.Input  = PipeReader.Create(stream, new StreamPipeReaderOptions(leaveOpen: true));
     this.Output = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
 }
示例#28
0
 public async Task CanDoMultipleAsyncWritesToStream()
 {
     var        pipe   = new Pipe(new PipeOptions(readerScheduler: PipeScheduler.Inline));
     PipeWriter writer = PipeWriter.Create(pipe.Writer.AsStream());
示例#29
0
        public async Task Run()
        {
            using var _ = _client;
            using var messageBuilder = new MessageBuilder();

            Stream stream = _client.GetStream();

            stream = await HandleInitialMessage(stream, messageBuilder);

            var reader = PipeReader.Create(stream);
            var writer = PipeWriter.Create(stream);

            if (_clientOptions == null) //TODO pfyasu maybe unused when cancel message will be implemented
            {
                return;
            }

            if (_clientOptions.TryGetValue("database", out string databaseName) == false)
            {
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ConnectionFailure,
                                            "Failed to connect to database",
                                            "Missing database name in the connection string"), _token);

                return;
            }

            var database = await _databasesLandlord.TryGetOrCreateResourceStore(databaseName);

            if (database == null)
            {
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            PgErrorCodes.ConnectionFailure,
                                            "Failed to connect to database",
                                            $"Database '{databaseName}' does not exist"), _token);

                return;
            }

            string username = null;

            try
            {
                username = _clientOptions["user"];

                using var transaction = new PgTransaction(database, new MessageReader(), username);

                if (_serverCertificate != null)
                {
                    // Authentication is required only when running in secured mode

                    await writer.WriteAsync(messageBuilder.AuthenticationCleartextPassword(), _token);

                    var authMessage = await transaction.MessageReader.GetUninitializedMessage(reader, _token);

                    await authMessage.Init(transaction.MessageReader, reader, _token);

                    await authMessage.Handle(transaction, messageBuilder, reader, writer, _token);
                }
                else
                {
                    await writer.WriteAsync(messageBuilder.AuthenticationOk(), _token);
                }

                await writer.WriteAsync(messageBuilder.ParameterStatusMessages(PgConfig.ParameterStatusList), _token);

                await writer.WriteAsync(messageBuilder.BackendKeyData(_processId, _identifier), _token);

                await writer.WriteAsync(messageBuilder.ReadyForQuery(transaction.State), _token);

                while (_token.IsCancellationRequested == false)
                {
                    var message = await transaction.MessageReader.GetUninitializedMessage(reader, _token);

                    try
                    {
                        await message.Init(transaction.MessageReader, reader, _token);

                        await message.Handle(transaction, messageBuilder, reader, writer, _token);
                    }
                    catch (PgErrorException e)
                    {
                        await message.HandleError(e, transaction, messageBuilder, writer, _token);
                    }
                }
            }
            catch (PgFatalException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"{e.Message} (fatal pg error code {e.ErrorCode}). {GetSourceConnectionDetails(username)}", e);
                }

                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Fatal,
                                            e.ErrorCode,
                                            e.Message,
                                            e.ToString()), _token);
            }
            catch (PgErrorException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"{e.Message} (pg error code {e.ErrorCode}). {GetSourceConnectionDetails(username)}", e);
                }

                // Shouldn't get to this point, PgErrorExceptions shouldn't be fatal
                await writer.WriteAsync(messageBuilder.ErrorResponse(
                                            PgSeverity.Error,
                                            e.ErrorCode,
                                            e.Message,
                                            e.ToString()), _token);
            }
            catch (PgTerminateReceivedException)
            {
                // Terminate silently
            }
            catch (QueryParser.ParseException e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Invalid RQL query", e);
                }

                try
                {
                    await writer.WriteAsync(messageBuilder.ErrorResponse(
                                                PgSeverity.Error,
                                                PgErrorCodes.InvalidSqlStatementName,
                                                e.ToString()), _token);
                }
                catch (Exception)
                {
                    // ignored
                }
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Unexpected internal pg error. {GetSourceConnectionDetails(username)}", e);
                }

                try
                {
                    await writer.WriteAsync(messageBuilder.ErrorResponse(
                                                PgSeverity.Fatal,
                                                PgErrorCodes.InternalError,
                                                e.ToString()), _token);
                }
                catch (Exception)
                {
                    // ignored
                }
            }
        }
示例#30
0
 private static PipeWriter CreateFakePipeWriter()
 {
     return(PipeWriter.Create(Stream.Null));
 }