Exemple #1
0
        private void ProcessRequest(DateTime utcNow, PlcRequestContext requestContext)
        {
            if (requestContext.Deadline?.ToUniversalTime() < utcNow)
            {
                this.logger.LogDebug(
                    "Request deadline exceeded, deadline={0:u}, now1={1:u}, now2={2:u}",
                    requestContext.Deadline,
                    utcNow,
                    DateTime.UtcNow);
                requestContext.TaskCompletionSource.SetException(new RpcException(
                                                                     new Status(StatusCode.DeadlineExceeded, string.Empty)));
                return;
            }

            int sequenceNumber = Interlocked.Increment(ref this.sequenceNumberGenerator);

            requestContext.RequestFrame.FrameHeader.SequenceNumber = (uint)sequenceNumber;

            if (!this.requestContextReceivingDictionary.TryAdd(sequenceNumber, requestContext))
            {
                throw new InvalidOperationException();  // Should not happen.
            }

            if (this.logger.IsEnabled(LogLevel.Debug))
            {
                using var stream = new MemoryStream();
                requestContext.RequestFrame.WriteTo(stream);
                this.logger.LogDebug(
                    "Sending {0} to {1}{2}{3}",
                    sequenceNumber,
                    this.RemoteEndPoint,
                    Environment.NewLine,
                    HexUtils.Dump(stream.ToArray()));
                this.OnDebugSending?.Invoke(this, stream.ToArray());

                stream.Seek(0, SeekOrigin.Begin);
                stream.CopyTo(this.tcpClient.GetStream());
            }
            else
            {
                requestContext.RequestFrame.WriteTo(this.tcpClient.GetStream());
            }
        }
        private void ReceivingBackgroundTaskEntryPoint()
        {
            CancellationToken closingCancellationToken = this.closingCancellationTokenSource.Token;

            using var reader = new BinaryReader(this.tcpClient.GetStream(), Encoding.ASCII, true);
            try
            {
                while (!closingCancellationToken.IsCancellationRequested)
                {
                    byte[] headerBytes = reader.ReadBytes(20);
                    if (headerBytes.Length != 20)
                    {
                        throw new IOException("Failed to read frame header");
                    }

                    var header = PlcFrameHeader.Parse(headerBytes);
                    if (header.ContentOffset != 20)
                    {
                        throw new InvalidDataException("Content offset is not 20");
                    }

                    byte[] bodyBytes = reader.ReadBytes(header.ContentLength);
                    if (bodyBytes.Length != header.ContentLength)
                    {
                        throw new IOException("Failed to read frame body");
                    }

                    if (this.logger.IsEnabled(LogLevel.Debug))
                    {
                        byte[] buffer = new byte[headerBytes.Length + bodyBytes.Length];
                        Buffer.BlockCopy(headerBytes, 0, buffer, 0, headerBytes.Length);
                        Buffer.BlockCopy(bodyBytes, 0, buffer, headerBytes.Length, bodyBytes.Length);

                        this.logger.LogDebug(
                            "Received {0} from {1}{2}{3}",
                            header.SequenceNumber,
                            this.RemoteEndPoint,
                            Environment.NewLine,
                            HexUtils.Dump(buffer));
                        this.OnDebugReceiving?.Invoke(this, buffer);
                    }

                    if (this.requestContextReceivingDictionary.TryRemove(
                            (int)header.SequenceNumber,
                            out PlcRequestContext requestContext))
                    {
                        if (header.Crc32cChecksum != 0 &&
                            header.Crc32cChecksum != Crc32C.Crc32CAlgorithm.Compute(bodyBytes))
                        {
                            this.logger.LogWarning(
                                "Received frame crc32c checksum mismatch from {0}",
                                this.RemoteEndPoint);
                            requestContext.TaskCompletionSource.TrySetException(new RpcException(
                                                                                    new Status(StatusCode.Internal, "Data transfer error, checksum mismatch.")));
                        }
                        else
                        {
                            requestContext.TaskCompletionSource.TrySetResult(new PlcFrame
                            {
                                FrameHeader = header,
                                FrameBody   = ByteString.CopyFrom(bodyBytes),
                            });
                        }
                    }
                    else
                    {
                        this.logger.LogWarning("Received unknown sequence number from {0}", this.RemoteEndPoint);
                    }
                }
            }
            catch (IOException e)
            {
                this.logger.LogError(e, "Failed to receiving from {0}", this.RemoteEndPoint);
                this.Close().ConfigureAwait(false).GetAwaiter().GetResult();
            }
            catch (InvalidDataException e)
            {
                this.logger.LogError(e, "Received invalid data from {0}", this.RemoteEndPoint);
                this.Close().ConfigureAwait(false).GetAwaiter().GetResult();
            }
        }