private async Task WriteUnifiedFrameContent( AsyncBinaryWriter writer, int streamId, UnifiedFrameContent unifiedFrameContent) { if (this.logger.IsEnabled(LogLevel.Debug)) { using var memoryStream = new MemoryStream(); using var memoryWriter = new AsyncBinaryWriter(memoryStream, Encoding.ASCII, false); await WriteFrame(memoryWriter, 2, 0, streamId, unifiedFrameContent.ToByteArray()) .ConfigureAwait(false); byte[] sendingBytes = memoryStream.ToArray(); this.logger.LogDebug( "Sending to {0} with streamId={1}:" + Environment.NewLine + "{2}", unifiedFrameContent.Header.Path, streamId, HexUtils.Dump(new ReadOnlyMemory <byte>(sendingBytes))); await writer.WriteAsync(sendingBytes).ConfigureAwait(false); } else { await WriteFrame(writer, 2, 0, streamId, unifiedFrameContent.ToByteArray()) .ConfigureAwait(false); } }
private async Task <TResponse> InvokeAsync <TRequest, TResponse>( string path, TRequest request, MessageParser <TResponse> responseParser, DateTime?deadline = null, CancellationToken cancellationToken = default) where TRequest : IMessage <TRequest> where TResponse : IMessage <TResponse> { var promise = new TaskCompletionSource <UnifiedFrameContent>(); await this.requestQueue .SendAsync( new RequestContext { Path = path, Message = request, Deadline = deadline, CancellationToken = cancellationToken, TaskCompletionSource = promise, }, cancellationToken) .ConfigureAwait(false); return(await promise.Task .ContinueWith( future => { if (future.IsFaulted) { throw new RpcException(new Status( StatusCode.Internal, future.Exception.ToString())); } if (future.IsCanceled) { throw new RpcException(Status.DefaultCancelled); } UnifiedFrameContent frame = future.Result; if (frame.Header.Status == 0) { return responseParser.ParseFrom(frame.Payload); } else { throw new RpcException(new Status( (StatusCode)frame.Header.Status, frame.Header.StatusMessage)); } }, cancellationToken, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default) .ConfigureAwait(false)); }
private static async Task <TcpClient> StartPlcAsync(ILogger logger, string hostname, int port) { var fakePlc = new TcpClient(hostname, port); logger.LogInformation("Fake PLC connected."); NetworkStream networkStream = fakePlc.GetStream(); using var reader = new AsyncBinaryReader(networkStream, Encoding.ASCII, true); using var writer = new AsyncBinaryWriter(networkStream, Encoding.ASCII, true); logger.LogDebug("Receiving TestRequest frame..."); byte[] receivedBytes = await reader.ReadBytesAsync(0x53).ConfigureAwait(false); logger.LogInformation("Received {0} bytes.", 0x53); byte[] sendingPayload = new UnifiedFrameContent { Header = new Header { Status = 0 }, Payload = new TestResponse { A = 42, B = 3.1415926F, C = "Hello World!", D = Timestamp.FromDateTimeOffset(DateTimeOffset.Parse("2019-10-29T21:42:13.00000+8:00", CultureInfo.InvariantCulture)), }.ToByteString(), }.ToByteArray(); var sendingHeader = new FrameHeader( version: 1, type: 2, sequenceNumber: 0, streamId: 1, contentOffset: 20, contentLength: (ushort)sendingPayload.Length, contentChecksum: Crc32C.Crc32CAlgorithm.Compute(sendingPayload)); logger.LogDebug("Sending TestResponse frame header..."); await sendingHeader.WriteTo(writer).ConfigureAwait(false); logger.LogDebug("Sending TestResponse frame body..."); await writer.WriteAsync(sendingPayload).ConfigureAwait(false); logger.LogInformation("Sent TestResponse."); return(fakePlc); }
private async Task DrainSendingRequestContexts(AsyncBinaryWriter binaryWriter) { while (this.requestQueue.TryReceive(out RequestContext requestContext)) { if (requestContext.CancellationToken.IsCancellationRequested || DateTime.Now > requestContext.Deadline) { requestContext.TaskCompletionSource.SetResult(new UnifiedFrameContent { Header = new Header { Status = (int)StatusCode.DeadlineExceeded, StatusMessage = Status.DefaultCancelled.Detail, }, }); } var unifiedFrameContent = new UnifiedFrameContent() { Header = new Header() { Path = requestContext.Path, }, Payload = requestContext.Message.ToByteString(), }; int streamId = Interlocked.Increment(ref this.counter); await this.WriteUnifiedFrameContent(binaryWriter, streamId, unifiedFrameContent) .ConfigureAwait(false); if (!this.receivingContexts.TryAdd(streamId, requestContext)) { throw new InvalidOperationException("Impossible"); } this.logger.LogDebug("Request recorded as streamId={0}: {1}", streamId, requestContext.Message); } }