public static async Task DecodeFramingFaultAsync(ClientFramingDecoder decoder, IConnection connection, Uri via, string contentType, TimeoutHelper timeoutHelper) { ValidateReadingFaultString(decoder); int offset = 0; byte[] faultBuffer = Fx.AllocateByteArray(FaultStringDecoder.FaultSizeQuota); int size = await connection.ReadAsync(0, Math.Min(FaultStringDecoder.FaultSizeQuota, connection.AsyncReadBufferSize), timeoutHelper.RemainingTime()); while (size > 0) { int bytesDecoded = decoder.Decode(connection.AsyncReadBuffer, offset, size); offset += bytesDecoded; size -= bytesDecoded; if (decoder.CurrentState == ClientFramingDecoderState.Fault) { ConnectionUtilities.CloseNoThrow(connection, timeoutHelper.RemainingTime()); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( FaultStringDecoder.GetFaultException(decoder.Fault, via.ToString(), contentType)); } else { if (decoder.CurrentState != ClientFramingDecoderState.ReadingFaultString) { throw Fx.AssertAndThrow("invalid framing client state machine"); } if (size == 0) { offset = 0; size = await connection.ReadAsync(0, Math.Min(FaultStringDecoder.FaultSizeQuota, connection.AsyncReadBufferSize), timeoutHelper.RemainingTime()); } } } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException()); }
public override int Decode(byte[] bytes, int offset, int size) { DecoderHelper.ValidateSize(size); try { int bytesConsumed; FramingRecordType recordType; switch (CurrentState) { case ClientFramingDecoderState.ReadingUpgradeRecord: recordType = (FramingRecordType)bytes[offset]; if (recordType == FramingRecordType.UpgradeResponse) { bytesConsumed = 1; base.CurrentState = ClientFramingDecoderState.UpgradeResponse; } else { bytesConsumed = 0; base.CurrentState = ClientFramingDecoderState.ReadingAckRecord; } break; case ClientFramingDecoderState.UpgradeResponse: bytesConsumed = 0; base.CurrentState = ClientFramingDecoderState.ReadingUpgradeRecord; break; case ClientFramingDecoderState.ReadingAckRecord: recordType = (FramingRecordType)bytes[offset]; if (recordType == FramingRecordType.Fault) { bytesConsumed = 1; _faultDecoder = new FaultStringDecoder(); base.CurrentState = ClientFramingDecoderState.ReadingFaultString; break; } ValidatePreambleAck(recordType); bytesConsumed = 1; base.CurrentState = ClientFramingDecoderState.Start; break; case ClientFramingDecoderState.Start: bytesConsumed = 0; base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeRecord; break; case ClientFramingDecoderState.ReadingEnvelopeRecord: recordType = (FramingRecordType)bytes[offset]; if (recordType == FramingRecordType.End) { bytesConsumed = 1; base.CurrentState = ClientFramingDecoderState.End; break; } else if (recordType == FramingRecordType.Fault) { bytesConsumed = 0; base.CurrentState = ClientFramingDecoderState.ReadingFault; break; } ValidateRecordType(FramingRecordType.UnsizedEnvelope, recordType); bytesConsumed = 1; base.CurrentState = ClientFramingDecoderState.EnvelopeStart; break; case ClientFramingDecoderState.EnvelopeStart: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( CreateException(new InvalidDataException(SR.FramingAtEnd))); case ClientFramingDecoderState.ReadingFault: recordType = (FramingRecordType)bytes[offset]; ValidateRecordType(FramingRecordType.Fault, recordType); bytesConsumed = 1; _faultDecoder = new FaultStringDecoder(); base.CurrentState = ClientFramingDecoderState.ReadingFaultString; break; case ClientFramingDecoderState.ReadingFaultString: bytesConsumed = _faultDecoder.Decode(bytes, offset, size); if (_faultDecoder.IsValueDecoded) { base.CurrentState = ClientFramingDecoderState.Fault; } break; case ClientFramingDecoderState.Fault: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( CreateException(new InvalidDataException(SR.FramingAtEnd))); default: throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine))); } StreamPosition += bytesConsumed; return(bytesConsumed); } catch (InvalidDataException e) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e)); } }