Пример #1
0
        public async Task <TResponse> DeserializeResponseAsync(IResponseFuture inputStream, AsyncOperationInfo operationInfo)
        {
            var sw = Stopwatch.StartNew();
            await ThreadingUtils.ContinueAtThreadPull();

            var       loggedResponseFuture = new LoggingResponseFutureDecorator(inputStream, MAX_AMOUNT_OF_BYTES_INSIDE_LOG_ENTRY);
            TResponse response             = null;

            using (Logger.Indent)
            {
                Logger.LogInfo(null, "Чтение ответа...");
                try
                {
                    response = await deserializeResponseAsync(loggedResponseFuture, operationInfo);

                    logDataRead();
                }
                catch (TimeoutException ex)
                {
                    logError(ex);

                    response = BuildErrorResponse(RequestStatus.READ_TIMEOUT);
                }
                catch (Exception ex)
                {
                    logError(ex);

                    response = BuildErrorResponse(RequestStatus.DESERIALIZATION_ERROR);
                }
            }

            return(response);

            void logDataRead()
            {
                Logger.LogInfo(null, $"Пакет ответа был успешно прочитан{Global.NL}Полная длина: {loggedResponseFuture.ReadCount}, длительность чтения: {sw.Elapsed.TotalMilliseconds.ToString("F2")} мс{getBufferRepresentation()}");
            }

            void logError(Exception ex)
            {
                Logger.LogError(null, $"Ошибка во время чтения/десериализации пакета. Было прочитано: {loggedResponseFuture.ReadCount}, длительность чтения: {sw.Elapsed.TotalMilliseconds.ToString("F2")} мс{getBufferRepresentation()}", ex);
            }

            string getBufferRepresentation()
            {
                var tooManyData = loggedResponseFuture.StorageCount < loggedResponseFuture.ReadCount;

                return($"{Global.NL}Первые {loggedResponseFuture.Capacity} байт из {loggedResponseFuture.ReadCount}".IfOrDefault(tooManyData) +
                       $"{Global.NL}Данные<HEX>:{loggedResponseFuture.Storage.Select(b => b.ToString("X2").PadLeft(3)).Aggregate(" ")}" +
                       $"{Global.NL}Данные<DEC>:{loggedResponseFuture.Storage.Select(b => b.ToString("D3").PadLeft(3)).Aggregate(" ")}");
            }
        }
Пример #2
0
        protected override async Task <SalachovResponse> deserializeResponseAsync(IResponseFuture inputStream, AsyncOperationInfo operationInfo)
        {
            SalachovResponse result = null;
            var answerIterator      = new BackedResponseFutureDecorator(inputStream);

            if (DeviceId == RUSDeviceId.ALL) // If broadcast
            {
                Logger.LogInfo(null, "Чтение ответа не требуется, поскольку запрос не предполагает ответа");

                result = new SalachovResponse(this, RequestStatus.OK, ResponseData.NONE, ResponseData.NONE, ResponseData.NONE);
            }
            else
            {
                var header = await answerIterator.WaitAsync(4, WaitMode.EXACT, operationInfo);

                var headerValid = header.SequenceEqual(_header);
                var length      = _hasLengthField
                    ? bytesToWord(await answerIterator.WaitAsync(2, WaitMode.EXACT, operationInfo))
                    : 0;
                var isLengthValid = _responseFullLength.IsUnknown
                    ? true
                    : (length + _header.Length + 2 /* CRC */ + (_hasLengthField ? 2 : 0)) == _responseFullLength.Length;
                var answerBody = await answerIterator.WaitAsync(length, WaitMode.EXACT, operationInfo);

                var calculatedChecksum = _checksum.ComputeChecksum(answerIterator.Storage);
                var sentChecksum       = bytesToWord(await answerIterator.WaitAsync(2, WaitMode.EXACT, operationInfo));
                var isCRCValid         = calculatedChecksum == sentChecksum;

                if (isCRCValid)
                {
                    if (headerValid)
                    {
                        if (isLengthValid)
                        {
                            result = instantiateResponse(RequestStatus.OK);
                        }
                        else
                        {
                            Logger.LogError(null, $"Некорректная длина. Ожидалась: {_responseFullLength.Length.ToString("X2")}, пришла в пакете: {(_hasLengthField ? length.ToString("X2") : "NONE")}");

                            result = instantiateResponse(RequestStatus.WRONG_LENGTH);
                        }
                    }
                    else
                    {
                        Logger.LogError(null, $"Некорректный заголовок. Ожидалась: {_header.ToHex()}, пришла в пакете: {header.ToHex()}");

                        result = instantiateResponse(RequestStatus.WRONG_HEADER);
                    }
                }
                else
                {
                    Logger.LogError(null, $"CRC не совпадает. Ожидалась: {calculatedChecksum.ToString("X2")}, пришла в пакете: {sentChecksum.ToString("X2")}");

                    result = instantiateResponse(RequestStatus.WRONG_CHECKSUM);
                }

                SalachovResponse instantiateResponse(RequestStatus status)
                {
                    return(new SalachovResponse(this, status,
                                                new InMemoryResponseData(answerIterator.Storage),
                                                new InMemoryResponseData(header),
                                                new InMemoryResponseData(answerBody)));
                }
            }

            return(result);
        }
Пример #3
0
 Task <IResponse> IRequest.DeserializeResponseAsync(IResponseFuture inputStream, AsyncOperationInfo operationInfo)
 {
     return(DeserializeResponseAsync(inputStream, operationInfo).ThenDo(r => (IResponse)r));
 }
Пример #4
0
 protected abstract Task <TResponse> deserializeResponseAsync(
     IResponseFuture inputStream,
     AsyncOperationInfo operationInfo);
Пример #5
0
 public ResponseFutureProxyBase(IResponseFuture @base)
 {
     _base = @base ?? throw new ArgumentNullException(nameof(@base));
 }
Пример #6
0
        protected override async Task <IResponse> deserializeResponseAsync(IResponseFuture inputStream, AsyncOperationInfo operationInfo)
        {
            IResponse result = null;
            Stream    stream = createReadBuffer();

            var dataRead = new StreamResponseData(stream);

            switch (_responseInfo.ReadMode)
            {
            case ResponseReadMode.TILL_TIMEOUT:
                try
                {
                    var readTimeout = new Timeouter(CHUNK_READ_TIMEOUT);
                    while (true)
                    {
                        var piece = await inputStream.WaitAsync(READ_CHUNK_SIZE, WaitMode.NO_MORE_THAN, operationInfo);

                        await stream.WriteAsync(piece, 0, piece.Length);

                        operationInfo.Progress.AddProgress(piece.Length);
                        if (piece.Length != 0)
                        {
                            readTimeout.Restart();
                        }
                        readTimeout.ThrowIfTimeout();
                    }
                }
                catch (TimeoutException)
                {
                }
                break;

            case ResponseReadMode.CONSTRAINED_BY_ANSWER:
                var max = _responseInfo.ResponseFullLength.IsUnknown
                        ? long.MaxValue
                        : _responseInfo.ResponseFullLength.Length;
                for (long i = 0; i < max; i++)
                {
                    var data = await inputStream.WaitAsync(1, WaitMode.EXACT, operationInfo);

                    stream.WriteByte(data.Single());
                    operationInfo.Progress.AddProgress(1D / max);
                }
                break;

            case ResponseReadMode.READ_BY_TARGET:
                result = await _deviceRequest.DeserializeResponseAsync(inputStream, operationInfo);

                break;

            default:
                throw new NotSupportedException();
            }

            if (result == null)
            {
                if (!_responseInfo.ResponseFullLength.IsUnknown &&
                    _responseInfo.ExpectedAnswer != null &&
                    !stream.AsEnumerable().Take((int)_responseInfo.ResponseFullLength.Length).SequenceEqual(_responseInfo.ExpectedAnswer))
                {
                    result = new FTDIBoxResponse(this, RequestStatus.NOT_EXPECTED_RESPONSE_BYTES, dataRead, null, null);
                }
                else
                {
                    await stream.FlushAsync(operationInfo.CancellationToken);

                    IResponseData serviceSection = null;
                    IResponseData bodySection    = null;
                    switch (Address)
                    {
                    case FTDIBoxRequestAddress.HS_SET_LOW_SPEED_MODE:
                    case FTDIBoxRequestAddress.LS_SET_HIGH_SPEED_MODE:
                    case FTDIBoxRequestAddress.HS_ACTIVATE_CHANNEL4:
                    case FTDIBoxRequestAddress.LS_ACTIVATE_CHANNEL4:
                        break;

                    case FTDIBoxRequestAddress.HS_GET_FLASH_LENGTH:
                    case FTDIBoxRequestAddress.HS_READ_ALL_FLASH:
                        serviceSection = new ResponseDataAreaProxy(dataRead, dataRead.Count - 6, dataRead.Count);
                        bodySection    = new ResponseDataAreaProxy(dataRead, 0, dataRead.Count - 6);
                        break;

                    case FTDIBoxRequestAddress.LS_DEVICE_REQUEST:
                        bodySection = dataRead;
                        break;

                    default:
                        throw new NotSupportedException();
                    }

                    result = new FTDIBoxResponse(this, RequestStatus.OK, dataRead, serviceSection, bodySection);
                }
            }

            return(result);

            Stream createReadBuffer()
            {
                Stream buffer = new MemoryStream();

                if (Address == FTDIBoxRequestAddress.HS_READ_ALL_FLASH)
                {
                    buffer = _scope.TryGetFirstParameter <FlashDumpStreamParameter>()?.Stream;
                    if (buffer == null)
                    {
                        var path = Path.GetTempFileName();
                        buffer = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);

                        Logger.LogInfo(null, $"Создан буфер чтения по пути {path}");
                    }
                    else
                    {
                        Logger.LogInfo(null, $"Буфер чтения предоставлен через параметр");
                    }
                }

                return(buffer);
            }
        }
 public LoggingResponseFutureDecorator(IResponseFuture @base, int storageCapacity) : base(@base)
 {
     Capacity = storageCapacity;
 }
Пример #8
0
 public BackedResponseFutureDecorator(IResponseFuture @base) : base(@base)
 {
 }