public async Task <byte[]> WaitAsync(int count, WaitMode mode, AsyncOperationInfo operationInfo) { throwIfDisposed(); _responseReadTimeout.ThrowIfTimeout(); operationInfo.CancellationToken.ThrowIfCancellationRequested(); byte[] waitResult = null; try { using (_waitTimeout.RestartMode) { switch (mode) { case WaitMode.EXACT: var buffer = new List <byte>(count); while (buffer.Count != count) { _responseReadTimeout.ThrowIfTimeout(); var result = await _pipe.ReadAsync(new PipeReadParameters(count - buffer.Count), _cancellation); if (result.Status.IsOneOf(IOBase.ReadStatus.DONE, IOBase.ReadStatus.PATIALLY_DONE)) { buffer.AddRange(result.Data); } else { throw new NotSupportedException(); } } waitResult = buffer.ToArray(); break; case WaitMode.NO_MORE_THAN: { var result = await _pipe.ReadAsync(new PipeReadParameters(count), _cancellation); if (result.Status.IsOneOf(IOBase.ReadStatus.DONE, IOBase.ReadStatus.PATIALLY_DONE)) { waitResult = result.Data.ToArray(); } else { throw new NotSupportedException(); } } break; default: throw new NotSupportedException(); } } return(waitResult); } finally { await Logger.LogResponseAsync(waitResult ?? new byte[0], count); } }
static async Task <byte[]> readExactAsync (int count, Func <byte[], int, int, object> readFunc, ReadExactInfo info) { var timeouter = new Timeouter(info.MethodTimeout); var buffer = new byte[count]; var offset = 0; var totalBytesRead = 0; var remain = count; while (totalBytesRead != count) { var bytesRead = 0; var readInfo = readFunc(buffer, offset, remain); if (readInfo is Task <int> task) { bytesRead = await task; } else if (readInfo is int read) { bytesRead = read; } else { throw new NotSupportedException(); } totalBytesRead += bytesRead; offset = totalBytesRead; remain = count - totalBytesRead; if (bytesRead == 0 && info.ThrowIfZeroReceived) { throw new ReadExactZeroReceivedException(); } if (info.RetryDelay != 0) { await Task.Delay(info.RetryDelay).ConfigureAwait(false); } if ((info.TimeoutOnlyIfNothingWasRead && totalBytesRead == 0) || (!info.TimeoutOnlyIfNothingWasRead)) { timeouter.ThrowIfTimeout(() => new ReadExactTimeoutException(buffer.Take(totalBytesRead), count)); } } return(buffer); }
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); } }