Beispiel #1
0
        public async Task ReadSingleMessageAsync_AdditionalData_ThrowError()
        {
            // Arrange
            var ms = new MemoryStream(new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x01,    // length = 1
                0x10,
                0x10     // additional data
            });

            var pipeReader = PipeReader.Create(ms);

            // Act
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(
                () => pipeReader.ReadSingleMessageAsync(TestServerCallContext, Marshaller.ContextualDeserializer).AsTask()).DefaultTimeout();

            // Assert
            Assert.AreEqual("Additional data after the message received.", ex.Status.Detail);
            Assert.AreEqual(StatusCode.Internal, ex.StatusCode);
        }
Beispiel #2
0
        public async Task ReadStreamMessageAsync_MultipleEmptyMessages_ReturnNoDataMessageThenComplete()
        {
            // Arrange
            var emptyMessage = new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x00     // length = 0
            };
            var ms = new MemoryStream(emptyMessage.Concat(emptyMessage).ToArray());

            var pipeReader = new TestPipeReader(PipeReader.Create(ms));

            // Act 1
            var messageData1 = await pipeReader.ReadStreamMessageAsync(TestServerCallContext, Marshaller.ContextualDeserializer);

            // Assert 1
            Assert.AreEqual(0, messageData1 !.Length);
            Assert.AreEqual(emptyMessage.Length, pipeReader.Consumed);

            // Act 2
            var messageData2 = await pipeReader.ReadStreamMessageAsync(TestServerCallContext, Marshaller.ContextualDeserializer);

            // Assert 2
            Assert.AreEqual(0, messageData2 !.Length);
            Assert.AreEqual(emptyMessage.Length * 2, pipeReader.Consumed);

            // Act 3
            var messageData3 = await pipeReader.ReadStreamMessageAsync(TestServerCallContext, Marshaller.ContextualDeserializer);

            // Assert 3
            Assert.IsNull(messageData3);
            Assert.AreEqual(emptyMessage.Length * 2, pipeReader.Consumed);
        }
    public void Stream_ResultHasCorrectValues(int overload, string contentType, string fileDownloadName, bool enableRangeProcessing, DateTimeOffset lastModified, EntityTagHeaderValue entityTag)
    {
        // Arrange
        var stream = new MemoryStream();

        // Act
        var result = overload switch
        {
            0 => TypedResults.Stream(stream, contentType, fileDownloadName, lastModified, entityTag, enableRangeProcessing),
            1 => TypedResults.Stream(PipeReader.Create(stream), contentType, fileDownloadName, lastModified, entityTag, enableRangeProcessing),
            _ => (IResult)TypedResults.Stream((s) => Task.CompletedTask, contentType, fileDownloadName, lastModified, entityTag)
        };

        // Assert
        switch (overload)
        {
        case <= 1:
            var fileStreamResult = result as FileStreamHttpResult;
            Assert.NotNull(fileStreamResult.FileStream);
            Assert.Equal(contentType ?? "application/octet-stream", fileStreamResult.ContentType);
            Assert.Equal(fileDownloadName, fileStreamResult.FileDownloadName);
            Assert.Equal(enableRangeProcessing, fileStreamResult.EnableRangeProcessing);
            Assert.Equal(lastModified, fileStreamResult.LastModified);
            Assert.Equal(entityTag, fileStreamResult.EntityTag);
            break;

        default:
            var pushStreamResult = result as PushStreamHttpResult;
            Assert.Equal(contentType ?? "application/octet-stream", pushStreamResult.ContentType);
            Assert.Equal(fileDownloadName, pushStreamResult.FileDownloadName);
            Assert.False(pushStreamResult.EnableRangeProcessing);
            Assert.Equal(lastModified, pushStreamResult.LastModified);
            Assert.Equal(entityTag, pushStreamResult.EntityTag);
            break;
        }
    }
Beispiel #4
0
        public async Task ReadSingleMessageAsync_ExceedReceiveSize_ReturnData()
        {
            // Arrange
            var context = HttpContextServerCallContextHelper.CreateServerCallContext(maxReceiveMessageSize: 1);
            var ms      = new MemoryStream(new byte[]
            {
                0x00,     // compression = 0
                0x00,
                0x00,
                0x00,
                0x02,     // length = 1
                0x10,
                0x10
            });

            var pipeReader = PipeReader.Create(ms);

            // Act
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => pipeReader.ReadSingleMessageAsync(context, TestDataMarshaller.ContextualDeserializer).AsTask()).DefaultTimeout();

            // Assert
            Assert.AreEqual("Received message exceeds the maximum configured message size.", ex.Status.Detail);
            Assert.AreEqual(StatusCode.ResourceExhausted, ex.StatusCode);
        }
        public async Task InterceptorsExecutedInRegistrationOrder_AndGlobalInterceptorExecutesFirst_DuplexStreaming()
        {
            // Arrange
            var url = Fixture.DynamicGrpc.AddDuplexStreamingMethod <Empty, Empty>((requestStream, responseStream, context) =>
            {
                var items = context.GetHttpContext().Items;
                Assert.AreEqual(3, items[OrderedInterceptor.OrderHeaderKey]);
                return(Task.CompletedTask);
            });

            // Act
            var response = await Fixture.Client.PostAsync(
                url,
                new GrpcStreamContent(new MemoryStream())).DefaultTimeout();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            // Assert
            await MessageHelpers.AssertReadStreamMessageAsync <Empty>(pipeReader).DefaultTimeout();

            response.AssertTrailerStatus();
        }
Beispiel #6
0
        public async Task NewSegmentsAllocatedWhenBufferReachesMinimumReadSize()
        {
            // We're using the pipe here as a way to pump bytes into the reader asynchronously
            var        pipe    = new Pipe();
            var        options = new StreamPipeReaderOptions(pool: new HeapBufferPool(), bufferSize: 10, minimumReadSize: 5);
            PipeReader reader  = PipeReader.Create(pipe.Reader.AsStream(), options);

            pipe.Writer.WriteEmpty(6);
            await pipe.Writer.FlushAsync();

            ReadResult readResult = await reader.ReadAsync();

            Assert.Equal(6, readResult.Buffer.Length);
            Assert.True(readResult.Buffer.IsSingleSegment);
            reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End);

            pipe.Writer.WriteEmpty(4);
            await pipe.Writer.FlushAsync();

            readResult = await reader.ReadAsync();

            Assert.Equal(10, readResult.Buffer.Length);
            Assert.False(readResult.Buffer.IsSingleSegment);
            var segments = 0;

            foreach (ReadOnlyMemory <byte> segment in readResult.Buffer)
            {
                segments++;
            }
            Assert.Equal(2, segments);
            reader.AdvanceTo(readResult.Buffer.End);

            reader.Complete();

            pipe.Writer.Complete();
        }
Beispiel #7
0
        private async Task ConnectToArduinoAsync(SerialPort port)
        {
            OpenPort(port);

            var reader = PipeReader.Create(port.BaseStream);

            Console.WriteLine("Is the port open? " + port.IsOpen);

            using (CancellationTokenSource cancellation = new CancellationTokenSource(1000))
            {
                Console.WriteLine("We are about to try to read stuff...");
                cancellation.Token.Register(() => reader.CompleteAsync());
                var readResult = await reader.ReadAsync(cancellation.Token);

                if (isArduino(readResult))
                {
                    arduinos.Add(port);
                }
                else
                {
                    ClosePort(port);
                }
            }
        }
Beispiel #8
0
        public async Task CanUseMultipleMessageReadersOnSameUnderlyingReader()
        {
            var protocol         = new TestProtocol();
            var pipe             = new Pipe();
            var underlyingReader = PipeReader.Create(pipe.Reader.AsStream());

            var reader = new MessagePipeReader(underlyingReader, protocol);

            protocol.WriteMessage(Encoding.ASCII.GetBytes("Hello"), pipe.Writer);
            protocol.WriteMessage(Encoding.ASCII.GetBytes("World"), pipe.Writer);
            await pipe.Writer.FlushAsync();

            var readResult = await reader.ReadAsync();

            Assert.Equal("Hello", Encoding.ASCII.GetString(readResult.Buffer.ToArray()));
            reader.Complete();

            reader     = new MessagePipeReader(underlyingReader, protocol);
            readResult = await reader.ReadAsync();

            Assert.Equal("World", Encoding.ASCII.GetString(readResult.Buffer.ToArray()));

            reader.Complete();
        }
Beispiel #9
0
        public async Task <HttpResponseMessage> GetResponseAsync(HttpRequestMessage request, Stream stream,
                                                                 bool readResponseContent = true, CancellationToken cancellationToken = default)
        {
            reader = PipeReader.Create(stream);

            response       = new HttpResponseMessage();
            contentHeaders = new Dictionary <string, List <string> >(StringComparer.OrdinalIgnoreCase);

            response.RequestMessage = request;

            try
            {
                await ReceiveFirstLineAsync(cancellationToken).ConfigureAwait(false);
                await ReceiveHeadersAsync(cancellationToken).ConfigureAwait(false);
                await ReceiveContentAsync(readResponseContent, cancellationToken).ConfigureAwait(false);
            }
            catch
            {
                response.Dispose();
                throw;
            }

            return(response);
        }
Beispiel #10
0
        public async Task SendCompressedMessage_ServerStreamingEnabledInCall_CompressedMessageReturned()
        {
            async Task ServerStreamingEnableCompression(HelloRequest request, IServerStreamWriter <HelloReply> responseStream, ServerCallContext context)
            {
                var headers = new Metadata {
                    new Metadata.Entry("grpc-internal-encoding-request", "gzip")
                };
                await context.WriteResponseHeadersAsync(headers);

                await responseStream.WriteAsync(new HelloReply { Message = "Hello 1" });

                responseStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
                await responseStream.WriteAsync(new HelloReply { Message = "Hello 2" });
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(ServerStreamingEnableCompression);

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new HelloRequest
            {
                Name = "World"
            });

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Content = new PushStreamContent(
                async s =>
            {
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.FlushAsync().DefaultTimeout();
            });

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest);

            // Assert
            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            Assert.AreEqual("gzip", response.Headers.GetValues("grpc-encoding").Single());

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            ReadResult readResult;

            readResult = await pipeReader.ReadAsync();

            Assert.AreEqual(1, readResult.Buffer.FirstSpan[0]); // Message is compressed
            var greeting1 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader, "gzip").DefaultTimeout();

            Assert.AreEqual($"Hello 1", greeting1.Message);

            readResult = await pipeReader.ReadAsync();

            Assert.AreEqual(0, readResult.Buffer.FirstSpan[0]); // Message is uncompressed
            var greeting2 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader, "gzip").DefaultTimeout();

            Assert.AreEqual($"Hello 2", greeting2.Message);

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

            Assert.IsNull(await finishedTask.DefaultTimeout());
        }
Beispiel #11
0
 public DuplexStreamPipe(Stream stream)
 {
     Input  = PipeReader.Create(stream, s_readerOpts);
     Output = PipeWriter.Create(stream, s_writerOpts);
 }
        public static void Run()
        {
            Console.WriteLine("Testing streaming messages");

            string appId       = "NetStreamingMessages";
            int    port        = 20002;
            int    clientCount = 10;

            var serverThread = new Thread(() =>
            {
                var config = new NetPeerConfiguration(appId)
                {
                    AcceptIncomingConnections = true,
                    Port          = port,
                    AutoExpandMTU = true,
                };
                config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
                var server = new NetServer(config);

                void Server_ErrorMessage(NetPeer sender, NetLogLevel level, in NetLogMessage message)
                {
                    Console.WriteLine("Server " + level + ": " + message.Code);

                    if (level > NetLogLevel.Debug)
                    {
                        Console.WriteLine(message.Exception);
                    }
                    else
                    {
                        Console.WriteLine();
                    }
                }
                server.DebugMessage   += Server_ErrorMessage;
                server.WarningMessage += Server_ErrorMessage;
                server.ErrorMessage   += Server_ErrorMessage;
                server.Start();

                Task.Run(() =>
                {
                    while (server.Status == NetPeerStatus.Running)
                    {
                        Console.WriteLine("Server Incoming: " +
                                          server.Statistics.IncomingRecycled + " / " +
                                          server.Statistics.IncomingAllocated);

                        Thread.Sleep(500);
                    }
                });

                int count = clientCount;
                while (count > 0 && server.TryReadMessage(60000 * 2, out var message))
                {
                    switch (message.MessageType)
                    {
                    case NetIncomingMessageType.ConnectionApproval:
                        message.SenderConnection?.Approve(server.CreateMessage("approved!"));
                        break;

                    case NetIncomingMessageType.StatusChanged:
                        Console.WriteLine("Server Status: " + message.ReadEnum <NetConnectionStatus>());
                        break;

                    case NetIncomingMessageType.Data:
                        Console.WriteLine("Server Data: " + message.ByteLength + " bytes");

                        var resp = server.CreateMessage("received " + count);
                        message.SenderConnection?.SendMessage(resp, NetDeliveryMethod.ReliableOrdered, 0);
                        count--;
                        break;

                    case NetIncomingMessageType.DataStream:
                        if (message.SenderConnection !.TryDequeueDataStream(out PipeReader? reader))
                        {
                            Task.Run(async() =>
                            {
                                Stream stream = reader.AsStream();
                                byte[] buffer = new byte[1024 * 1024];

                                //using (var fs = new FileStream("receivedfile", FileMode.Create))
                                var fs = Stream.Null;
                                {
                                    int read;
                                    while ((read = await stream.ReadAsync(buffer)) > 0)
                                    {
                                        //Console.WriteLine("READ " + read + " FROM CLIENT STREAM");
                                        fs.Write(buffer.AsSpan(0, read));
                                    }
                                }

                                Console.WriteLine("CLIENT STREAM COMPLETED ON SERVER");
                            });
                        }
                        break;

                    default:
                        Console.WriteLine("Server " + message.MessageType);
                        break;
                    }
                }

                List <NetConnection> connections = new();
                server.GetConnections(connections);
                foreach (var con in connections)
                {
                    var msg = server.CreateMessage("this is library");
                    con.Disconnect(msg);
                }

                Console.WriteLine("Server finished waiting");
                var shutMsg = server.CreateMessage("this is not library anymore");
                server.Shutdown(shutMsg);
            });

            Thread[] clientThreads = new Thread[clientCount];

            for (int t = 0; t < clientThreads.Length; t++)
            {
                int tt = t;
                clientThreads[t] = new Thread(() =>
                {
                    var config = new NetPeerConfiguration(appId)
                    {
                        AcceptIncomingConnections = false,
                        AutoExpandMTU             = true,
                        SendBufferSize            = 1024 * 1024
                    };
                    var client = new NetClient(config);

                    void Client_ErrorMessage(NetPeer sender, NetLogLevel level, in NetLogMessage message)
                    {
                        if (message.Code == NetLogCode.SocketWouldBlock)
                        {
                            return;
                        }

                        Console.WriteLine("Client " + level + ": " + message.Code);

                        if (level > NetLogLevel.Debug)
                        {
                            Console.WriteLine(message.Exception);
                        }
                        else
                        {
                            Console.WriteLine();
                        }
                    }
                    client.DebugMessage   += Client_ErrorMessage;
                    client.WarningMessage += Client_ErrorMessage;
                    client.ErrorMessage   += Client_ErrorMessage;
                    client.Start();

                    Task.Run(() =>
                    {
                        while (client.ConnectionStatus != NetConnectionStatus.Connected)
                        {
                            Thread.Sleep(1);
                        }

                        while (client.ConnectionStatus == NetConnectionStatus.Connected)
                        {
                            Console.WriteLine("Client " + tt + " Outgoing: " +
                                              client.Statistics.OutgoingRecycled + " / " +
                                              client.Statistics.OutgoingAllocated);

                            Thread.Sleep(500);
                        }
                    });

                    NetConnection connection = client.Connect(new IPEndPoint(IPAddress.Loopback, port));

                    bool stop = false;
                    void Connection_StatusChanged(NetConnection connection, NetConnectionStatus status, NetOutgoingMessage? reason)
                    {
                        string print = "Client Status: " + status;
                        if (reason != null)
                        {
                            print += " #" + reason.MessageType;
                            if (reason.BitLength != 0)
                            {
                                if (status == NetConnectionStatus.Disconnected)
                                {
                                    print += " (" + reason?.ReadString() + ")";
                                    stop   = true;
                                }
                                else if (status == NetConnectionStatus.Connected)
                                {
                                    print += " (" + connection?.RemoteHailMessage?.ReadString() + ")";
                                }
                            }
                        }
                        Console.WriteLine(print);
                    }
                    connection.StatusChanged += Connection_StatusChanged;

                    while (connection.Status != NetConnectionStatus.Connected)
                    {
                        if (connection.Status == NetConnectionStatus.Disconnected)
                        {
                            if (client.TryReadMessage(out var msg))
                            {
                                if (msg.MessageType == NetIncomingMessageType.StatusChanged)
                                {
                                    Console.WriteLine(msg.ReadEnum <NetConnectionStatus>() + ": " + msg.ReadString());
                                }
                            }
                            return;
                        }
                        Thread.Sleep(1);
                    }

                    Task.Run(async() =>
                    {
                        try
                        {
                            var fs            = new FakeReadStream(1024 * 1024 * 10);
                            PipeReader reader = PipeReader.Create(fs);
                            await connection.StreamMessageAsync(reader, 0);

                            Console.WriteLine("FINISHED SENDING FILE from thread " + tt);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                        }
                    });

                    while (!stop && client.TryReadMessage(60000, out var message))
                    {
                        switch (message.MessageType)
                        {
                        case NetIncomingMessageType.Data:
                            Console.WriteLine("Client Data: " + message.ReadString());
                            client.Shutdown();
                            stop = true;
                            break;

                        default:
                            Console.WriteLine("Client " + message.MessageType);
                            break;
                        }

                        client.Recycle(message);
                    }
                });
            }

            serverThread.Start();
            for (int i = 0; i < clientThreads.Length; i++)
            {
                clientThreads[i].Start();
            }

            serverThread.Join();
            for (int i = 0; i < clientThreads.Length; i++)
            {
                clientThreads[i].Join();
            }

            Thread.Sleep(500);
        }
Beispiel #13
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);
            }
        }
Beispiel #14
0
 public EventStreamChannel(IEventStreamReader eventStreamReader, Stream stream, CancellationToken cancellationToken = default)
 {
     _eventStreamReader = eventStreamReader;
     _pipeReader        = PipeReader.Create(stream);
     _ = Task.Run(async() => await ReceivePacketsAsync(_pipeReader, cancellationToken), cancellationToken);
 }
Beispiel #15
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();
                }
            });
        }
 public void NullStreamThrows()
 {
     Assert.Throws <ArgumentNullException>(() => PipeReader.Create(null));
 }
Beispiel #17
0
        public async Task WriteUntilDeadline_SuccessResponsesStreamed_CoreAsync(ServerStreamingServerMethod <HelloRequest, HelloReply> callHandler)
        {
            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(callHandler);

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Headers.Add(GrpcProtocolConstants.TimeoutHeader, "200m");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            var messageCount = 0;

            var readTask = Task.Run(async() =>
            {
                while (true)
                {
                    var greeting = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout();

                    if (greeting != null)
                    {
                        Assert.AreEqual($"How are you World? {messageCount}", greeting.Message);
                        messageCount++;
                    }
                    else
                    {
                        break;
                    }
                }
            });

            await readTask.DefaultTimeout();

            Assert.AreNotEqual(0, messageCount);

            response.AssertTrailerStatus(StatusCode.DeadlineExceeded, "Deadline Exceeded");

            Assert.True(HasLog(LogLevel.Debug, "DeadlineExceeded", "Request with timeout of 00:00:00.2000000 has exceeded its deadline."));

            await TestHelpers.AssertIsTrueRetryAsync(
                () => HasLog(LogLevel.Trace, "DeadlineStopped", "Request deadline stopped."),
                "Missing deadline stopped log.").DefaultTimeout();
        }
Beispiel #18
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);
        }
Beispiel #19
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
                }
            }
        }
Beispiel #20
0
        public async IAsyncEnumerable <object[]> ReadRowsAsync(Func <int, object[], bool> predicate, bool includeMemo = false, bool includeDeleted = false)
        {
            using (var fs = dbf.OpenReadOnlyAsync())
            {
                int recordLength = dbfHeader.RecordLength;
                fs.Position = dbfHeader.HeaderSize;
                var rdr = PipeReader.Create(fs);
                if (includeMemo && (dbfHeader.Flags & DbfHeaderFlags.Memo) != 0)
                {
                    using (var memofs = dbf.OpenMemo())
                    {
                        memofs.Position = 6;
                        var memoBlocksize = memofs.ReadShort(bigEndian: true);
                        for (var index = 0; index < dbfHeader.RecordCount;)
                        {
                            var readRes = await rdr.ReadAsync();

                            var buffer = readRes.Buffer;
                            while (index < dbfHeader.RecordCount && TryReadRecord(recordLength, ref buffer, out var record))
                            {
                                if (record.FirstSpan[0] == 0x2A && !includeDeleted)
                                {
                                    index++;
                                    continue; // Entry is marked Deleted(*)
                                }
                                var rowData = ReadRowSequenceMemo(record, index, memofs, memoBlocksize);

                                if (predicate(index, rowData))
                                {
                                    yield return(rowData);
                                }
                                index++;
                            }
                            rdr.AdvanceTo(buffer.Start, buffer.End);
                            if (readRes.IsCompleted)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    for (var index = 0; index < dbfHeader.RecordCount;)
                    {
                        var readRes = await rdr.ReadAsync();

                        var buffer = readRes.Buffer;
                        while (index < dbfHeader.RecordCount && TryReadRecord(recordLength, ref buffer, out var record))
                        {
                            if (record.FirstSpan[0] == 0x2A && !includeDeleted)
                            {
                                index++;
                                continue; // Entry is marked Deleted(*)
                            }
                            var rowData = ReadRowSequence(record, index);
                            if (predicate(index, rowData))
                            {
                                yield return(rowData);
                            }
                            index++;
                        }
                        rdr.AdvanceTo(buffer.Start, buffer.End);
                        if (readRes.IsCompleted)
                        {
                            break;
                        }
                    }
                }
            }
        }
Beispiel #21
0
 public void NullMessageReaderThrows()
 {
     Assert.Throws <ArgumentNullException>(() => new MessagePipeReader(PipeReader.Create(Stream.Null), null));
 }
Beispiel #22
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);
            }
        }
Beispiel #23
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));
 }
Beispiel #24
0
 public BinaryObjectPipeReader(Stream stream, BinaryObjectDictionary typeDictionary) :
     this(PipeReader.Create(stream), typeDictionary)
 {
 }
        public async Task OperationCancelledExceptionNotSwallowedIfNotThrownFromSpecifiedToken()
        {
            PipeReader reader = PipeReader.Create(new ThrowsOperationCanceledExceptionStream());

            await Assert.ThrowsAsync <OperationCanceledException>(async() => await reader.ReadAsync());
        }
        public async Task MoveNext_TokenCancelledDuringMoveNext_CancelTask()
        {
            // Arrange
            var ms = new SyncPointMemoryStream();

            var httpContext = new DefaultHttpContext();

            httpContext.Features.Set <IRequestBodyPipeFeature>(new TestRequestBodyPipeFeature(PipeReader.Create(ms)));
            var serverCallContext = HttpContextServerCallContextHelper.CreateServerCallContext(httpContext);
            var reader            = new HttpContextStreamReader <HelloReply>(serverCallContext, MessageHelpers.ServiceMethod.ResponseMarshaller.ContextualDeserializer);

            var cts = new CancellationTokenSource();

            var nextTask = reader.MoveNext(cts.Token);

            Assert.IsFalse(nextTask.IsCompleted);
            Assert.IsFalse(nextTask.IsCanceled);

            cts.Cancel();

            try
            {
                await nextTask;
                Assert.Fail();
            }
            catch (TaskCanceledException)
            {
            }

            Assert.IsTrue(nextTask.IsCompleted);
            Assert.IsTrue(nextTask.IsCanceled);
        }
Beispiel #27
0
        public static Task <T?> AssertReadStreamMessageAsync <T>(Stream stream, string?compressionEncoding = null, List <ICompressionProvider>?compressionProviders = null) where T : class, IMessage, new()
        {
            var pipeReader = PipeReader.Create(stream);

            return(AssertReadStreamMessageAsync <T>(pipeReader, compressionEncoding, compressionProviders));
        }
Beispiel #28
0
 protected override void SetPipeReaderOptions(MemoryPool <byte>?pool = null, int bufferSize = -1)
 {
     _pipeReader = PipeReader.Create(Pipe.Reader.AsStream(), new StreamPipeReaderOptions(pool, bufferSize));
 }
        public async Task MultipleMessagesFromOneClient_SuccessResponses()
        {
            // Arrange
            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new ChatMessage
            {
                Name    = "John",
                Message = "Hello Jill"
            });

            var streamingContent = new StreamingContent();
            var httpRequest      = GrpcHttpHelper.Create("Chat.Chatter/Chat");

            httpRequest.Content = streamingContent;

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for first message from client");

            var requestStream = await streamingContent.GetRequestStreamAsync().DefaultTimeout();

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            await requestStream.FlushAsync().DefaultTimeout();

            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            var message1Task = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);
            var message1     = await message1Task.DefaultTimeout();

            Assert.AreEqual("John", message1.Name);
            Assert.AreEqual("Hello Jill", message1.Message);

            var message2Task = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);

            Assert.IsFalse(message2Task.IsCompleted, "Server is waiting for messages from client");

            ms = new MemoryStream();
            MessageHelpers.WriteMessage(ms, new ChatMessage
            {
                Name    = "Jill",
                Message = "Hello John"
            });

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            await requestStream.FlushAsync().DefaultTimeout();

            var message2 = await message2Task.DefaultTimeout();

            Assert.AreEqual("Jill", message2.Name);
            Assert.AreEqual("Hello John", message2.Message);

            var finishedTask = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);

            Assert.IsFalse(finishedTask.IsCompleted, "Server is waiting for client to end streaming");

            // Complete request stream
            streamingContent.Complete();

            await finishedTask.DefaultTimeout();

            response.AssertTrailerStatus();
        }
        static PipeReader CreatePipeReader(string text)
        {
            var stream = new MemoryStream(Encoding.ASCII.GetBytes(text));

            return(PipeReader.Create(stream));
        }