|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using System.Text;
using System.Globalization;
using System.Runtime;
using System.Buffers;
namespace System.ServiceModel.Channels
{
internal static class DecoderHelper
{
public static void ValidateSize(long size)
{
if (size <= 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(size), size, SR.ValueMustBePositive));
}
}
}
internal struct IntDecoder
{
private int _value;
private short _index;
private const int LastIndex = 4;
public int Value
{
get
{
if (!IsValueDecoded)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _value;
}
}
public bool IsValueDecoded { get; private set; }
public void Reset()
{
_index = 0;
_value = 0;
IsValueDecoded = false;
}
public int Decode(byte[] buffer, int offset, int size)
{
DecoderHelper.ValidateSize(size);
if (IsValueDecoded)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
int bytesConsumed = 0;
while (bytesConsumed < size)
{
int next = buffer[offset];
_value |= (next & 0x7F) << (_index * 7);
bytesConsumed++;
if (_index == LastIndex && (next & 0xF8) != 0)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.FramingSizeTooLarge));
}
_index++;
if ((next & 0x80) == 0)
{
IsValueDecoded = true;
break;
}
offset++;
}
return bytesConsumed;
}
}
internal abstract class StringDecoder
{
private int _encodedSize;
private byte[] _encodedBytes;
private int _bytesNeeded;
private string _value;
private State _currentState;
private IntDecoder _sizeDecoder;
private int _sizeQuota;
private int _valueLengthInBytes;
public StringDecoder(int sizeQuota)
{
_sizeQuota = sizeQuota;
_sizeDecoder = new IntDecoder();
_currentState = State.ReadingSize;
Reset();
}
public bool IsValueDecoded
{
get { return _currentState == State.Done; }
}
public string Value
{
get
{
if (_currentState != State.Done)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _value;
}
}
public int Decode(byte[] buffer, int offset, int size)
{
DecoderHelper.ValidateSize(size);
int bytesConsumed;
switch (_currentState)
{
case State.ReadingSize:
bytesConsumed = _sizeDecoder.Decode(buffer, offset, size);
if (_sizeDecoder.IsValueDecoded)
{
_encodedSize = _sizeDecoder.Value;
if (_encodedSize > _sizeQuota)
{
Exception quotaExceeded = OnSizeQuotaExceeded(_encodedSize);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(quotaExceeded);
}
if (_encodedBytes == null || _encodedBytes.Length < _encodedSize)
{
_encodedBytes = Fx.AllocateByteArray(_encodedSize);
_value = null;
}
_currentState = State.ReadingBytes;
_bytesNeeded = _encodedSize;
}
break;
case State.ReadingBytes:
if (_value != null && _valueLengthInBytes == _encodedSize && _bytesNeeded == _encodedSize &&
size >= _encodedSize && CompareBuffers(_encodedBytes, buffer, offset))
{
bytesConsumed = _bytesNeeded;
OnComplete(_value);
}
else
{
bytesConsumed = _bytesNeeded;
if (size < _bytesNeeded)
{
bytesConsumed = size;
}
Buffer.BlockCopy(buffer, offset, _encodedBytes, _encodedSize - _bytesNeeded, bytesConsumed);
_bytesNeeded -= bytesConsumed;
if (_bytesNeeded == 0)
{
_value = Encoding.UTF8.GetString(_encodedBytes, 0, _encodedSize);
_valueLengthInBytes = _encodedSize;
OnComplete(_value);
}
}
break;
default:
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.InvalidDecoderStateMachine));
}
return bytesConsumed;
}
protected virtual void OnComplete(string value)
{
_currentState = State.Done;
}
private static bool CompareBuffers(byte[] buffer1, byte[] buffer2, int offset)
{
for (int i = 0; i < buffer1.Length; i++)
{
if (buffer1[i] != buffer2[i + offset])
{
return false;
}
}
return true;
}
protected abstract Exception OnSizeQuotaExceeded(int size);
public void Reset()
{
_currentState = State.ReadingSize;
_sizeDecoder.Reset();
}
private enum State
{
ReadingSize,
ReadingBytes,
Done,
}
}
internal class ViaStringDecoder : StringDecoder
{
private Uri _via;
public ViaStringDecoder(int sizeQuota)
: base(sizeQuota)
{
}
protected override Exception OnSizeQuotaExceeded(int size)
{
Exception result = new InvalidDataException(SR.Format(SR.FramingViaTooLong, size));
FramingEncodingString.AddFaultString(result, FramingEncodingString.ViaTooLongFault);
return result;
}
protected override void OnComplete(string value)
{
try
{
_via = new Uri(value);
base.OnComplete(value);
}
catch (UriFormatException exception)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.Format(SR.FramingViaNotUri, value), exception));
}
}
public Uri ValueAsUri
{
get
{
if (!IsValueDecoded)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _via;
}
}
}
internal class FaultStringDecoder : StringDecoder
{
internal const int FaultSizeQuota = 256;
public FaultStringDecoder()
: base(FaultSizeQuota)
{
}
protected override Exception OnSizeQuotaExceeded(int size)
{
return new InvalidDataException(SR.Format(SR.FramingFaultTooLong, size));
}
public static Exception GetFaultException(string faultString, string via, string contentType)
{
if (faultString == FramingEncodingString.EndpointNotFoundFault)
{
return new EndpointNotFoundException(SR.Format(SR.EndpointNotFound, via));
}
else if (faultString == FramingEncodingString.ContentTypeInvalidFault)
{
return new ProtocolException(SR.Format(SR.FramingContentTypeMismatch, contentType, via));
}
else if (faultString == FramingEncodingString.ServiceActivationFailedFault)
{
return new ServiceActivationException(SR.Format(SR.Hosting_ServiceActivationFailed, via));
}
else if (faultString == FramingEncodingString.ConnectionDispatchFailedFault)
{
return new CommunicationException(SR.Format(SR.Sharing_ConnectionDispatchFailed, via));
}
else if (faultString == FramingEncodingString.EndpointUnavailableFault)
{
return new EndpointNotFoundException(SR.Format(SR.Sharing_EndpointUnavailable, via));
}
else if (faultString == FramingEncodingString.MaxMessageSizeExceededFault)
{
Exception inner = new QuotaExceededException(SR.FramingMaxMessageSizeExceeded);
return new CommunicationException(inner.Message, inner);
}
else if (faultString == FramingEncodingString.UnsupportedModeFault)
{
return new ProtocolException(SR.Format(SR.FramingModeNotSupportedFault, via));
}
else if (faultString == FramingEncodingString.UnsupportedVersionFault)
{
return new ProtocolException(SR.Format(SR.FramingVersionNotSupportedFault, via));
}
else if (faultString == FramingEncodingString.ContentTypeTooLongFault)
{
Exception inner = new QuotaExceededException(SR.Format(SR.FramingContentTypeTooLongFault, contentType));
return new CommunicationException(inner.Message, inner);
}
else if (faultString == FramingEncodingString.ViaTooLongFault)
{
Exception inner = new QuotaExceededException(SR.Format(SR.FramingViaTooLongFault, via));
return new CommunicationException(inner.Message, inner);
}
else if (faultString == FramingEncodingString.ServerTooBusyFault)
{
return new ServerTooBusyException(SR.Format(SR.ServerTooBusy, via));
}
else if (faultString == FramingEncodingString.UpgradeInvalidFault)
{
return new ProtocolException(SR.Format(SR.FramingUpgradeInvalid, via));
}
else
{
return new ProtocolException(SR.Format(SR.FramingFaultUnrecognized, faultString));
}
}
}
internal class ContentTypeStringDecoder : StringDecoder
{
public ContentTypeStringDecoder(int sizeQuota)
: base(sizeQuota)
{
}
protected override Exception OnSizeQuotaExceeded(int size)
{
Exception result = new InvalidDataException(SR.Format(SR.FramingContentTypeTooLong, size));
FramingEncodingString.AddFaultString(result, FramingEncodingString.ContentTypeTooLongFault);
return result;
}
public static string GetString(FramingEncodingType type)
{
switch (type)
{
case FramingEncodingType.Soap11Utf8:
return FramingEncodingString.Soap11Utf8;
case FramingEncodingType.Soap11Utf16:
return FramingEncodingString.Soap11Utf16;
case FramingEncodingType.Soap11Utf16FFFE:
return FramingEncodingString.Soap11Utf16FFFE;
case FramingEncodingType.Soap12Utf8:
return FramingEncodingString.Soap12Utf8;
case FramingEncodingType.Soap12Utf16:
return FramingEncodingString.Soap12Utf16;
case FramingEncodingType.Soap12Utf16FFFE:
return FramingEncodingString.Soap12Utf16FFFE;
case FramingEncodingType.MTOM:
return FramingEncodingString.MTOM;
case FramingEncodingType.Binary:
return FramingEncodingString.Binary;
case FramingEncodingType.BinarySession:
return FramingEncodingString.BinarySession;
default:
return "unknown" + ((int)type).ToString(CultureInfo.InvariantCulture);
}
}
}
internal abstract class FramingDecoder
{
protected FramingDecoder()
{
}
protected FramingDecoder(long streamPosition)
{
StreamPosition = streamPosition;
}
protected abstract string CurrentStateAsString { get; }
public long StreamPosition { get; set; }
protected void ValidateFramingMode(FramingMode mode)
{
switch (mode)
{
case FramingMode.Singleton:
case FramingMode.Duplex:
case FramingMode.Simplex:
case FramingMode.SingletonSized:
break;
default:
{
Exception exception = CreateException(new InvalidDataException(SR.Format(
SR.FramingModeNotSupported, mode.ToString())), FramingEncodingString.UnsupportedModeFault);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
}
}
}
protected void ValidateRecordType(FramingRecordType expectedType, FramingRecordType foundType)
{
if (foundType != expectedType)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidRecordTypeException(expectedType, foundType));
}
}
// special validation for Preamble Ack for usability purposes (MB#39593)
protected void ValidatePreambleAck(FramingRecordType foundType)
{
if (foundType != FramingRecordType.PreambleAck)
{
Exception inner = CreateInvalidRecordTypeException(FramingRecordType.PreambleAck, foundType);
string exceptionString;
if (((byte)foundType == 'h') || ((byte)foundType == 'H'))
{
exceptionString = SR.PreambleAckIncorrectMaybeHttp;
}
else
{
exceptionString = SR.PreambleAckIncorrect;
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(exceptionString, inner));
}
}
private Exception CreateInvalidRecordTypeException(FramingRecordType expectedType, FramingRecordType foundType)
{
return new InvalidDataException(SR.Format(SR.FramingRecordTypeMismatch, expectedType.ToString(), foundType.ToString()));
}
protected void ValidateMajorVersion(int majorVersion)
{
if (majorVersion != FramingVersion.Major)
{
Exception exception = CreateException(new InvalidDataException(SR.Format(
SR.FramingVersionNotSupported, majorVersion)), FramingEncodingString.UnsupportedVersionFault);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
}
}
public Exception CreatePrematureEOFException()
{
return CreateException(new InvalidDataException(SR.FramingPrematureEOF));
}
protected Exception CreateException(InvalidDataException innerException, string framingFault)
{
Exception result = CreateException(innerException);
FramingEncodingString.AddFaultString(result, framingFault);
return result;
}
protected Exception CreateException(InvalidDataException innerException)
{
return new ProtocolException(SR.Format(SR.FramingError, StreamPosition, CurrentStateAsString),
innerException);
}
}
internal class SingletonMessageDecoder : FramingDecoder
{
private IntDecoder _sizeDecoder;
private int _chunkBytesNeeded;
private int _chunkSize;
public SingletonMessageDecoder(long streamPosition)
: base(streamPosition)
{
_sizeDecoder = new IntDecoder();
CurrentState = State.ChunkStart;
}
public void Reset()
{
CurrentState = State.ChunkStart;
}
public State CurrentState { get; private set; }
protected override string CurrentStateAsString
{
get { return CurrentState.ToString(); }
}
public int ChunkSize
{
get
{
if (CurrentState < State.ChunkStart)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _chunkSize;
}
}
public int Decode(byte[] bytes, int offset, int size)
{
DecoderHelper.ValidateSize(size);
try
{
int bytesConsumed;
switch (CurrentState)
{
case State.ReadingEnvelopeChunkSize:
bytesConsumed = _sizeDecoder.Decode(bytes, offset, size);
if (_sizeDecoder.IsValueDecoded)
{
_chunkSize = _sizeDecoder.Value;
_sizeDecoder.Reset();
if (_chunkSize == 0)
{
CurrentState = State.EnvelopeEnd;
}
else
{
CurrentState = State.ChunkStart;
_chunkBytesNeeded = _chunkSize;
}
}
break;
case State.ChunkStart:
bytesConsumed = 0;
CurrentState = State.ReadingEnvelopeBytes;
break;
case State.ReadingEnvelopeBytes:
bytesConsumed = size;
if (bytesConsumed > _chunkBytesNeeded)
{
bytesConsumed = _chunkBytesNeeded;
}
_chunkBytesNeeded -= bytesConsumed;
if (_chunkBytesNeeded == 0)
{
CurrentState = State.ChunkEnd;
}
break;
case State.ChunkEnd:
bytesConsumed = 0;
CurrentState = State.ReadingEnvelopeChunkSize;
break;
case State.EnvelopeEnd:
ValidateRecordType(FramingRecordType.End, (FramingRecordType)bytes[offset]);
bytesConsumed = 1;
CurrentState = State.End;
break;
case State.End:
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));
}
}
public enum State
{
ReadingEnvelopeChunkSize,
ChunkStart,
ReadingEnvelopeBytes,
ChunkEnd,
EnvelopeEnd,
End,
}
}
// common set of states used on the client-side.
internal enum ClientFramingDecoderState
{
ReadingUpgradeRecord,
ReadingUpgradeMode,
UpgradeResponse,
ReadingAckRecord,
Start,
ReadingFault,
ReadingFaultString,
Fault,
ReadingEnvelopeRecord,
ReadingEnvelopeSize,
EnvelopeStart,
ReadingEnvelopeBytes,
EnvelopeEnd,
ReadingEndRecord,
End,
}
internal abstract class ClientFramingDecoder : FramingDecoder
{
protected ClientFramingDecoder(long streamPosition)
: base(streamPosition)
{
CurrentState = ClientFramingDecoderState.ReadingUpgradeRecord;
}
public ClientFramingDecoderState CurrentState { get; protected set; }
protected override string CurrentStateAsString
{
get { return CurrentState.ToString(); }
}
public abstract string Fault
{
get;
}
public abstract int Decode(byte[] bytes, int offset, int size);
}
// Pattern:
// (UpgradeResponse, upgrade-bytes)*, (Ack | Fault),
// ((EnvelopeStart, ReadingEnvelopeBytes*, EnvelopeEnd) | Fault)*,
// End
internal class ClientDuplexDecoder : ClientFramingDecoder
{
private IntDecoder _sizeDecoder;
private FaultStringDecoder _faultDecoder;
private int _envelopeBytesNeeded;
private int _envelopeSize;
public ClientDuplexDecoder(long streamPosition)
: base(streamPosition)
{
_sizeDecoder = new IntDecoder();
}
public int EnvelopeSize
{
get
{
if (CurrentState < ClientFramingDecoderState.EnvelopeStart)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _envelopeSize;
}
}
public override string Fault
{
get
{
if (CurrentState < ClientFramingDecoderState.Fault)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _faultDecoder.Value;
}
}
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 = 1;
_faultDecoder = new FaultStringDecoder();
base.CurrentState = ClientFramingDecoderState.ReadingFaultString;
break;
}
ValidateRecordType(FramingRecordType.SizedEnvelope, recordType);
bytesConsumed = 1;
base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeSize;
_sizeDecoder.Reset();
break;
case ClientFramingDecoderState.ReadingEnvelopeSize:
bytesConsumed = _sizeDecoder.Decode(bytes, offset, size);
if (_sizeDecoder.IsValueDecoded)
{
base.CurrentState = ClientFramingDecoderState.EnvelopeStart;
_envelopeSize = _sizeDecoder.Value;
_envelopeBytesNeeded = _envelopeSize;
}
break;
case ClientFramingDecoderState.EnvelopeStart:
bytesConsumed = 0;
base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeBytes;
break;
case ClientFramingDecoderState.ReadingEnvelopeBytes:
bytesConsumed = size;
if (bytesConsumed > _envelopeBytesNeeded)
{
bytesConsumed = _envelopeBytesNeeded;
}
_envelopeBytesNeeded -= bytesConsumed;
if (_envelopeBytesNeeded == 0)
{
base.CurrentState = ClientFramingDecoderState.EnvelopeEnd;
}
break;
case ClientFramingDecoderState.EnvelopeEnd:
bytesConsumed = 0;
base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeRecord;
break;
case ClientFramingDecoderState.ReadingFaultString:
bytesConsumed = _faultDecoder.Decode(bytes, offset, size);
if (_faultDecoder.IsValueDecoded)
{
base.CurrentState = ClientFramingDecoderState.Fault;
}
break;
case ClientFramingDecoderState.Fault:
bytesConsumed = 0;
base.CurrentState = ClientFramingDecoderState.ReadingEndRecord;
break;
case ClientFramingDecoderState.ReadingEndRecord:
ValidateRecordType(FramingRecordType.End, (FramingRecordType)bytes[offset]);
bytesConsumed = 1;
base.CurrentState = ClientFramingDecoderState.End;
break;
case ClientFramingDecoderState.End:
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));
}
}
}
// Pattern:
// (UpgradeResponse, upgrade-bytes)*, (Ack | Fault),
// End
internal class ClientSingletonDecoder : ClientFramingDecoder
{
private FaultStringDecoder _faultDecoder;
public ClientSingletonDecoder(long streamPosition)
: base(streamPosition)
{
}
public override string Fault
{
get
{
if (CurrentState < ClientFramingDecoderState.Fault)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
}
return _faultDecoder.Value;
}
}
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));
}
}
}
}
|