FramingDecoders.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / FramingDecoders.cs / 1 / FramingDecoders.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Globalization;
    using System.ServiceModel; 
    using System.IO; 
    using System.Text;
 
    static class DecoderHelper
    {
        public static void ValidateSize(int size)
        { 
            if (size <= 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("size", size, SR.GetString( 
                    SR.ValueMustBePositive)));
            } 
        }
    }

    struct IntDecoder 
    {
        int value; 
        short index; 
        bool isValueDecoded;
        const int LastIndex = 4; 

        public int Value
        {
            get 
            {
                if (!isValueDecoded) 
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return value; 
            }
        }

        public bool IsValueDecoded 
        {
            get { return isValueDecoded; } 
        } 

        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.GetString(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.GetString(SR.FramingSizeTooLarge))); 
                }
                index++; 
                if ((next & 0x80) == 0) 
                {
                    isValueDecoded = true; 
                    break;
                }
                offset++;
            } 
            return bytesConsumed;
        } 
    } 

    abstract class StringDecoder 
    {
        int encodedSize;
        byte[] encodedBytes;
        int bytesNeeded; 
        string value;
        State currentState; 
        IntDecoder sizeDecoder; 
        int sizeQuota;
        int valueLengthInBytes; 

        public StringDecoder(int sizeQuota)
        {
            this.sizeQuota = sizeQuota; 
            this.sizeDecoder = new IntDecoder();
            this.currentState = State.ReadingSize; 
            Reset(); 
        }
 
        public bool IsValueDecoded
        {
            get { return currentState == State.Done; }
        } 

        public string Value 
        { 
            get
            { 
                if (currentState != State.Done)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(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 = DiagnosticUtility.Utility.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.GetString(SR.InvalidDecoderStateMachine)));
            } 

            return bytesConsumed; 
        } 

        protected virtual void OnComplete(string value) 
        {
            this.currentState = State.Done;
        }
 
        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(); 
        }
 
        enum State 
        {
            ReadingSize, 
            ReadingBytes,
            Done,
        }
    } 

    class ViaStringDecoder : StringDecoder 
    { 
        Uri via;
 
        public ViaStringDecoder(int sizeQuota) : base(sizeQuota)
        {
        }
 
        protected override Exception OnSizeQuotaExceeded(int size)
        { 
            Exception result = new InvalidDataException(SR.GetString(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.GetString(SR.FramingViaNotUri, value), exception));
            } 
        }
 
        public Uri ValueAsUri 
        {
            get 
            {
                if (!IsValueDecoded)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return via;
            } 
        } 
    }
 
    class FaultStringDecoder : StringDecoder
    {
        internal const int FaultSizeQuota = 256;
 
        public FaultStringDecoder()
            : base(FaultSizeQuota) 
        { 
        }
 
        protected override Exception OnSizeQuotaExceeded(int size)
        {
            return new InvalidDataException(SR.GetString(SR.FramingFaultTooLong, size));
        } 

        public static Exception GetFaultException(string faultString, string via, string contentType) 
        { 
            if (faultString == FramingEncodingString.EndpointNotFoundFault)
            { 
                return new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, via));
            }
            else if (faultString == FramingEncodingString.ContentTypeInvalidFault)
            { 
                return new ProtocolException(SR.GetString(SR.FramingContentTypeMismatch, contentType, via));
            } 
            else if (faultString == FramingEncodingString.ServiceActivationFailedFault) 
            {
                return new ServiceActivationException(SR.GetString(SR.Hosting_ServiceActivationFailed, via)); 
            }
            else if (faultString == FramingEncodingString.ConnectionDispatchFailedFault)
            {
                return new CommunicationException(SR.GetString(SR.Sharing_ConnectionDispatchFailed, via)); 
            }
            else if (faultString == FramingEncodingString.EndpointUnavailableFault) 
            { 
                return new EndpointNotFoundException(SR.GetString(SR.Sharing_EndpointUnavailable, via));
            } 
            else if (faultString == FramingEncodingString.MaxMessageSizeExceededFault)
            {
                Exception inner = new QuotaExceededException(SR.GetString(SR.FramingMaxMessageSizeExceeded));
                return new CommunicationException(inner.Message, inner); 
            }
            else if (faultString == FramingEncodingString.UnsupportedModeFault) 
            { 
                return new ProtocolException(SR.GetString(SR.FramingModeNotSupportedFault, via));
            } 
            else if (faultString == FramingEncodingString.UnsupportedVersionFault)
            {
                return new ProtocolException(SR.GetString(SR.FramingVersionNotSupportedFault, via));
            } 
            else if (faultString == FramingEncodingString.ContentTypeTooLongFault)
            { 
                Exception inner = new QuotaExceededException(SR.GetString(SR.FramingContentTypeTooLongFault, contentType)); 
                return new CommunicationException(inner.Message, inner);
            } 
            else if (faultString == FramingEncodingString.ViaTooLongFault)
            {
                Exception inner = new QuotaExceededException(SR.GetString(SR.FramingViaTooLongFault, via));
                return new CommunicationException(inner.Message, inner); 
            }
            else if (faultString == FramingEncodingString.ServerTooBusyFault) 
            { 
                return new ServerTooBusyException(SR.GetString(SR.ServerTooBusy, via));
            } 
            else if (faultString == FramingEncodingString.UpgradeInvalidFault)
            {
                return new ProtocolException(SR.GetString(SR.FramingUpgradeInvalid, via));
            } 
            else
            { 
                return new ProtocolException(SR.GetString(SR.FramingFaultUnrecognized, faultString)); 
            }
        } 
    }

    class ContentTypeStringDecoder : StringDecoder
    { 
        public ContentTypeStringDecoder(int sizeQuota) : base(sizeQuota)
        { 
        } 

        protected override Exception OnSizeQuotaExceeded(int size) 
        {
            Exception result = new InvalidDataException(SR.GetString(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);
            } 
        }
    } 
 
    abstract class FramingDecoder
    { 
        long streamPosition;

        protected FramingDecoder()
        { 
        }
 
        protected FramingDecoder(long streamPosition) 
        {
            this.streamPosition = streamPosition; 
        }

        protected abstract string CurrentStateAsString { get; }
 
        public long StreamPosition
        { 
            get { return streamPosition; } 
            set { streamPosition = value; }
        } 

        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.GetString( 
                            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.GetString(SR.PreambleAckIncorrectMaybeHttp);
                }
                else
                { 
                    exceptionString = SR.GetString(SR.PreambleAckIncorrect);
                } 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(exceptionString, inner)); 
            }
        } 

        Exception CreateInvalidRecordTypeException(FramingRecordType expectedType, FramingRecordType foundType)
        {
            return new InvalidDataException(SR.GetString(SR.FramingRecordTypeMismatch, expectedType.ToString(), foundType.ToString())); 
        }
 
        protected void ValidateMajorVersion(int majorVersion) 
        {
            if (majorVersion != FramingVersion.Major) 
            {
                Exception exception = CreateException(new InvalidDataException(SR.GetString(
                    SR.FramingVersionNotSupported, majorVersion)), FramingEncodingString.UnsupportedVersionFault);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception); 
            }
        } 
 
        public Exception CreatePrematureEOFException()
        { 
            return CreateException(new InvalidDataException(SR.GetString(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.GetString(SR.FramingError, StreamPosition, CurrentStateAsString), 
                innerException);
        } 
   } 

    // Pattern: 
    //   Done
    class ServerModeDecoder : FramingDecoder
    {
        State currentState; 
        int majorVersion;
        int minorVersion; 
        FramingMode mode; 

        public ServerModeDecoder() 
        {
            currentState = State.ReadingVersionRecord;
        }
 
        public int Decode(byte[] bytes, int offset, int size)
        { 
            DecoderHelper.ValidateSize(size); 

            try 
            {
                int bytesConsumed;
                switch (currentState)
                { 
                    case State.ReadingVersionRecord:
                        ValidateRecordType(FramingRecordType.Version, (FramingRecordType)bytes[offset]); 
                        currentState = State.ReadingMajorVersion; 
                        bytesConsumed = 1;
                        break; 
                    case State.ReadingMajorVersion:
                        majorVersion = bytes[offset];
                        ValidateMajorVersion(majorVersion);
                        currentState = State.ReadingMinorVersion; 
                        bytesConsumed = 1;
                        break; 
                    case State.ReadingMinorVersion: 
                        minorVersion = bytes[offset];
                        currentState = State.ReadingModeRecord; 
                        bytesConsumed = 1;
                        break;
                    case State.ReadingModeRecord:
                        ValidateRecordType(FramingRecordType.Mode, (FramingRecordType)bytes[offset]); 
                        currentState = State.ReadingModeValue;
                        bytesConsumed = 1; 
                        break; 
                    case State.ReadingModeValue:
                        mode = (FramingMode)bytes[offset]; 
                        ValidateFramingMode(mode);
                        currentState = State.Done;
                        bytesConsumed = 1;
                        break; 
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }
 
                StreamPosition += bytesConsumed;
                return bytesConsumed;
            }
            catch (InvalidDataException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e)); 
            } 
        }
 
        public void Reset()
        {
            StreamPosition = 0;
            currentState = State.ReadingVersionRecord; 
        }
 
        public State CurrentState 
        {
            get { return currentState; } 
        }

        protected override string CurrentStateAsString
        { 
            get { return currentState.ToString(); }
        } 
 
        public FramingMode Mode
        { 
            get
            {
                if (currentState != State.Done)
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return mode; 
            } 
        }
 
        public int MajorVersion
        {
            get
            { 
                if (currentState != State.Done)
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return majorVersion;
            } 
        }

        public int MinorVersion
        { 
            get
            { 
                if (currentState != State.Done) 
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return minorVersion;
            }
        }
 
        public enum State
        { 
            ReadingVersionRecord, 
            ReadingMajorVersion,
            ReadingMinorVersion, 
            ReadingModeRecord,
            ReadingModeValue,
            Done,
        } 
    }
 
    // Used for Duplex/Simplex 
    // Pattern:
    //   Start, 
    //   (UpgradeRequest, upgrade-content-type)*,
    //   (EnvelopeStart, ReadingEnvelopeBytes*, EnvelopeEnd)*,
    //   End
    class ServerSessionDecoder : FramingDecoder 
    {
        ViaStringDecoder viaDecoder; 
        StringDecoder contentTypeDecoder; 
        IntDecoder sizeDecoder;
        State currentState; 
        string contentType;
        int envelopeBytesNeeded;
        int envelopeSize;
        string upgrade; 

        public ServerSessionDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength) : base(streamPosition) 
        { 
            this.viaDecoder = new ViaStringDecoder(maxViaLength);
            this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength); 
            this.sizeDecoder = new IntDecoder();
            this.currentState = State.ReadingViaRecord;
        }
 
        public State CurrentState
        { 
            get { return currentState; } 
        }
 
        protected override string CurrentStateAsString
        {
            get { return currentState.ToString(); }
        } 

        public string ContentType 
        { 
            get
            { 
                if (currentState < State.PreUpgradeStart)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return contentType; 
            }
        } 
 
        public Uri Via
        { 
            get
            {
                if (currentState < State.ReadingContentTypeRecord)
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return viaDecoder.ValueAsUri; 
            } 
        }
 
        public void Reset(long streamPosition)
        {
            this.StreamPosition = streamPosition;
            this.currentState = State.ReadingViaRecord; 
        }
 
        public string Upgrade 
        {
            get 
            {
                if (currentState != State.UpgradeRequest)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return upgrade;
            } 
        } 

        public int EnvelopeSize 
        {
            get
            {
                if (currentState < State.EnvelopeStart) 
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return envelopeSize; 
            }
        } 

        public int Decode(byte[] bytes, int offset, int size)
        {
            DecoderHelper.ValidateSize(size); 

            try 
            { 
                int bytesConsumed;
                FramingRecordType recordType; 
                switch (currentState)
                {
                    case State.ReadingViaRecord:
                        recordType = (FramingRecordType)bytes[offset]; 
                        ValidateRecordType(FramingRecordType.Via, recordType);
                        bytesConsumed = 1; 
                        viaDecoder.Reset(); 
                        currentState = State.ReadingViaString;
                        break; 
                    case State.ReadingViaString:
                        bytesConsumed = viaDecoder.Decode(bytes, offset, size);
                        if (viaDecoder.IsValueDecoded)
                        { 
                            currentState = State.ReadingContentTypeRecord;
                        } 
                        break; 
                    case State.ReadingContentTypeRecord:
                        recordType = (FramingRecordType)bytes[offset]; 
                        if (recordType == FramingRecordType.KnownEncoding)
                        {
                            bytesConsumed = 1;
                            currentState = State.ReadingContentTypeByte; 
                        }
                        else 
                        { 
                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
                            bytesConsumed = 1; 
                            contentTypeDecoder.Reset();
                            currentState = State.ReadingContentTypeString;
                        }
                        break; 
                    case State.ReadingContentTypeByte:
                        contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]); 
                        bytesConsumed = 1; 
                        currentState = State.PreUpgradeStart;
                        break; 
                    case State.ReadingContentTypeString:
                        bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
                        if (contentTypeDecoder.IsValueDecoded)
                        { 
                            currentState = State.PreUpgradeStart;
                            contentType = contentTypeDecoder.Value; 
                        } 
                        break;
                    case State.PreUpgradeStart: 
                        bytesConsumed = 0;
                        currentState = State.ReadingUpgradeRecord;
                        break;
                    case State.ReadingUpgradeRecord: 
                        recordType = (FramingRecordType)bytes[offset];
                        if (recordType == FramingRecordType.UpgradeRequest) 
                        { 
                            bytesConsumed = 1;
                            contentTypeDecoder.Reset(); 
                            currentState = State.ReadingUpgradeString;
                        }
                        else
                        { 
                            bytesConsumed = 0;
                            currentState = State.ReadingPreambleEndRecord; 
                        } 
                        break;
                    case State.ReadingUpgradeString: 
                        bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
                        if (contentTypeDecoder.IsValueDecoded)
                        {
                            currentState = State.UpgradeRequest; 
                            upgrade = contentTypeDecoder.Value;
                        } 
                        break; 
                    case State.UpgradeRequest:
                        bytesConsumed = 0; 
                        currentState = State.ReadingUpgradeRecord;
                        break;
                    case State.ReadingPreambleEndRecord:
                        recordType = (FramingRecordType)bytes[offset]; 
                        ValidateRecordType(FramingRecordType.PreambleEnd, recordType);
                        bytesConsumed = 1; 
                        currentState = State.Start; 
                        break;
                    case State.Start: 
                        bytesConsumed = 0;
                        currentState = State.ReadingEndRecord;
                        break;
                    case State.ReadingEndRecord: 
                        recordType = (FramingRecordType)bytes[offset];
                        if (recordType == FramingRecordType.End) 
                        { 
                            bytesConsumed = 1;
                            currentState = State.End; 
                        }
                        else
                        {
                            bytesConsumed = 0; 
                            currentState = State.ReadingEnvelopeRecord;
                        } 
                        break; 
                    case State.ReadingEnvelopeRecord:
                        ValidateRecordType(FramingRecordType.SizedEnvelope, (FramingRecordType)bytes[offset]); 
                        bytesConsumed = 1;
                        currentState = State.ReadingEnvelopeSize;
                        sizeDecoder.Reset();
                        break; 
                    case State.ReadingEnvelopeSize:
                        bytesConsumed = sizeDecoder.Decode(bytes, offset, size); 
                        if (sizeDecoder.IsValueDecoded) 
                        {
                            currentState = State.EnvelopeStart; 
                            envelopeSize = sizeDecoder.Value;
                            envelopeBytesNeeded = envelopeSize;
                        }
                        break; 
                    case State.EnvelopeStart:
                        bytesConsumed = 0; 
                        currentState = State.ReadingEnvelopeBytes; 
                        break;
                    case State.ReadingEnvelopeBytes: 
                        bytesConsumed = size;
                        if (bytesConsumed > envelopeBytesNeeded)
                            bytesConsumed = envelopeBytesNeeded;
                        envelopeBytesNeeded -= bytesConsumed; 
                        if (envelopeBytesNeeded == 0)
                            currentState = State.EnvelopeEnd; 
                        break; 
                    case State.EnvelopeEnd:
                        bytesConsumed = 0; 
                        currentState = State.ReadingEndRecord;
                        break;
                    case State.End:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
                    default: 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
                } 

                StreamPosition += bytesConsumed;
                return bytesConsumed;
            } 
            catch (InvalidDataException e)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e)); 
            }
        } 

        public enum State
        {
            ReadingViaRecord, 
            ReadingViaString,
            ReadingContentTypeRecord, 
            ReadingContentTypeString, 
            ReadingContentTypeByte,
            PreUpgradeStart, 
            ReadingUpgradeRecord,
            ReadingUpgradeString,
            UpgradeRequest,
            ReadingPreambleEndRecord, 
            Start,
            ReadingEnvelopeRecord, 
            ReadingEnvelopeSize, 
            EnvelopeStart,
            ReadingEnvelopeBytes, 
            EnvelopeEnd,
            ReadingEndRecord,
            End,
        } 
    }
 
    class SingletonMessageDecoder : FramingDecoder 
    {
        IntDecoder sizeDecoder; 
        int chunkBytesNeeded;
        int chunkSize;
        State currentState;
 
        public SingletonMessageDecoder(long streamPosition)
            : base(streamPosition) 
        { 
            this.sizeDecoder = new IntDecoder();
            this.currentState = State.ChunkStart; 
        }

        public void Reset()
        { 
            this.currentState = State.ChunkStart;
        } 
 
        public State CurrentState
        { 
            get { return currentState; }
        }

        protected override string CurrentStateAsString 
        {
            get { return currentState.ToString(); } 
        } 

        public int ChunkSize 
        {
            get
            {
                if (currentState < State.ChunkStart) 
                {
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                }
 
                return this.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) 
                        {
                            this.chunkSize = sizeDecoder.Value; 
                            sizeDecoder.Reset();

                            if (this.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.GetString(SR.FramingAtEnd))));
 
                    default: 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }

                StreamPosition += bytesConsumed;
                return bytesConsumed; 
            }
            catch (InvalidDataException e) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
            } 
        }

        public enum State
        { 
            ReadingEnvelopeChunkSize,
            ChunkStart, 
            ReadingEnvelopeBytes, 
            ChunkEnd,
            EnvelopeEnd, 
            End,
        }
    }
 
    // Pattern:
    //   Start, 
    //   (UpgradeRequest, upgrade-bytes)*, 
    //   EnvelopeStart,
    class ServerSingletonDecoder : FramingDecoder 
    {
        ViaStringDecoder viaDecoder;
        ContentTypeStringDecoder contentTypeDecoder;
        State currentState; 
        string contentType;
        string upgrade; 
 
        public ServerSingletonDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength)
            : base(streamPosition) 
        {
            this.viaDecoder = new ViaStringDecoder(maxViaLength);
            this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength);
            this.currentState = State.ReadingViaRecord; 
        }
 
        public void Reset() 
        {
            this.currentState = State.ReadingViaRecord; 
        }

        public State CurrentState
        { 
            get { return currentState; }
        } 
 
        protected override string CurrentStateAsString
        { 
            get { return currentState.ToString(); }
        }

        public Uri Via 
        {
            get 
            { 
                if (currentState < State.ReadingContentTypeRecord)
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return viaDecoder.ValueAsUri;
            }
        } 

        public string ContentType 
        { 
            get
            { 
                if (currentState < State.PreUpgradeStart)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return contentType; 
            }
        } 
 
        public string Upgrade
        { 
            get
            {
                if (currentState != State.UpgradeRequest)
#pragma warning suppress 56503 // [....], not a publicly accessible API 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return upgrade; 
            } 
        }
 
        public int Decode(byte[] bytes, int offset, int size)
        {
            DecoderHelper.ValidateSize(size);
 
            try
            { 
                int bytesConsumed; 
                FramingRecordType recordType;
                switch (currentState) 
                {
                    case State.ReadingViaRecord:
                        recordType = (FramingRecordType)bytes[offset];
                        ValidateRecordType(FramingRecordType.Via, recordType); 
                        bytesConsumed = 1;
                        viaDecoder.Reset(); 
                        currentState = State.ReadingViaString; 
                        break;
                    case State.ReadingViaString: 
                        bytesConsumed = viaDecoder.Decode(bytes, offset, size);
                        if (viaDecoder.IsValueDecoded)
                        {
                            currentState = State.ReadingContentTypeRecord; 
                        }
                        break; 
                    case State.ReadingContentTypeRecord: 
                        recordType = (FramingRecordType)bytes[offset];
                        if (recordType == FramingRecordType.KnownEncoding) 
                        {
                            bytesConsumed = 1;
                            currentState = State.ReadingContentTypeByte;
                        } 
                        else
                        { 
                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType); 
                            bytesConsumed = 1;
                            contentTypeDecoder.Reset(); 
                            currentState = State.ReadingContentTypeString;
                        }
                        break;
                    case State.ReadingContentTypeByte: 
                        contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]);
                        bytesConsumed = 1; 
                        currentState = State.PreUpgradeStart; 
                        break;
                    case State.ReadingContentTypeString: 
                        bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
                        if (contentTypeDecoder.IsValueDecoded)
                        {
                            currentState = State.PreUpgradeStart; 
                            contentType = contentTypeDecoder.Value;
                        } 
                        break; 
                    case State.PreUpgradeStart:
                        bytesConsumed = 0; 
                        currentState = State.ReadingUpgradeRecord;
                        break;
                    case State.ReadingUpgradeRecord:
                        recordType = (FramingRecordType)bytes[offset]; 
                        if (recordType == FramingRecordType.UpgradeRequest)
                        { 
                            bytesConsumed = 1; 
                            contentTypeDecoder.Reset();
                            currentState = State.ReadingUpgradeString; 
                        }
                        else
                        {
                            bytesConsumed = 0; 
                            currentState = State.ReadingPreambleEndRecord;
                        } 
                        break; 
                    case State.ReadingUpgradeString:
                        bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size); 
                        if (contentTypeDecoder.IsValueDecoded)
                        {
                            currentState = State.UpgradeRequest;
                            upgrade = contentTypeDecoder.Value; 
                        }
                        break; 
                    case State.UpgradeRequest: 
                        bytesConsumed = 0;
                        currentState = State.ReadingUpgradeRecord; 
                        break;
                    case State.ReadingPreambleEndRecord:
                        recordType = (FramingRecordType)bytes[offset];
                        ValidateRecordType(FramingRecordType.PreambleEnd, recordType); 
                        bytesConsumed = 1;
                        currentState = State.Start; 
                        break; 
                    case State.Start:
                        bytesConsumed = 0; 
                        currentState = State.ReadingEnvelopeRecord;
                        break;
                    case State.ReadingEnvelopeRecord:
                        ValidateRecordType(FramingRecordType.UnsizedEnvelope, (FramingRecordType)bytes[offset]); 
                        bytesConsumed = 1;
                        currentState = State.EnvelopeStart; 
                        break; 
                    case State.EnvelopeStart:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }
 
                StreamPosition += bytesConsumed; 
                return bytesConsumed;
            } 
            catch (InvalidDataException e)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
            } 
        }
 
        public enum State 
        {
            ReadingViaRecord, 
            ReadingViaString,
            ReadingContentTypeRecord,
            ReadingContentTypeString,
            ReadingContentTypeByte, 
            PreUpgradeStart,
            ReadingUpgradeRecord, 
            ReadingUpgradeString, 
            UpgradeRequest,
            ReadingPreambleEndRecord, 
            Start,
            ReadingEnvelopeRecord,
            EnvelopeStart,
            ReadingEnvelopeChunkSize, 
            ChunkStart,
            ReadingEnvelopeChunk, 
            ChunkEnd, 
            End,
        } 
    }

    // Pattern:
    //   Start, 
    //   EnvelopeStart,
    class ServerSingletonSizedDecoder : FramingDecoder 
    { 
        ViaStringDecoder viaDecoder;
        ContentTypeStringDecoder contentTypeDecoder; 
        State currentState;
        string contentType;

        public ServerSingletonSizedDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength) 
            : base(streamPosition)
        { 
            this.viaDecoder = new ViaStringDecoder(maxViaLength); 
            this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength);
            this.currentState = State.ReadingViaRecord; 
        }

        public int Decode(byte[] bytes, int offset, int size)
        { 
            DecoderHelper.ValidateSize(size);
 
            try 
            {
                int bytesConsumed; 
                FramingRecordType recordType;
                switch (currentState)
                {
                    case State.ReadingViaRecord: 
                        recordType = (FramingRecordType)bytes[offset];
                        ValidateRecordType(FramingRecordType.Via, recordType); 
                        bytesConsumed = 1; 
                        viaDecoder.Reset();
                        currentState = State.ReadingViaString; 
                        break;
                    case State.ReadingViaString:
                        bytesConsumed = viaDecoder.Decode(bytes, offset, size);
                        if (viaDecoder.IsValueDecoded) 
                            currentState = State.ReadingContentTypeRecord;
                        break; 
                    case State.ReadingContentTypeRecord: 
                        recordType = (FramingRecordType)bytes[offset];
                        if (recordType == FramingRecordType.KnownEncoding) 
                        {
                            bytesConsumed = 1;
                            currentState = State.ReadingContentTypeByte;
                        } 
                        else
                        { 
                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType); 
                            bytesConsumed = 1;
                            contentTypeDecoder.Reset(); 
                            currentState = State.ReadingContentTypeString;
                        }
                        break;
                    case State.ReadingContentTypeByte: 
                        contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]);
                        bytesConsumed = 1; 
                        currentState = State.Start; 
                        break;
                    case State.ReadingContentTypeString: 
                        bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
                        if (contentTypeDecoder.IsValueDecoded)
                        {
                            currentState = State.Start; 
                            contentType = contentTypeDecoder.Value;
                        } 
                        break; 
                    case State.Start:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }
 
                StreamPosition += bytesConsumed; 
                return bytesConsumed;
            } 
            catch (InvalidDataException e)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
            } 
        }
 
        public void Reset(long streamPosition) 
        {
            this.StreamPosition = streamPosition; 
            this.currentState = State.ReadingViaRecord;
        }

        public State CurrentState 
        {
            get { return currentState; } 
        } 

        protected override string CurrentStateAsString 
        {
            get { return currentState.ToString(); }
        }
 
        public Uri Via
        { 
            get 
            {
                if (currentState < State.ReadingContentTypeRecord) 
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
                return viaDecoder.ValueAsUri;
            } 
        }
 
        public string ContentType 
        {
            get 
            {
                if (currentState < State.Start)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return contentType;
            } 
        } 

        public enum State 
        {
            ReadingViaRecord,
            ReadingViaString,
            ReadingContentTypeRecord, 
            ReadingContentTypeString,
            ReadingContentTypeByte, 
            Start, 
        }
    } 

    // common set of states used on the client-side.
    enum ClientFramingDecoderState
    { 
        ReadingUpgradeRecord,
        ReadingUpgradeMode, 
        UpgradeResponse, 
        ReadingAckRecord,
        Start, 
        ReadingFault,
        ReadingFaultString,
        Fault,
        ReadingEnvelopeRecord, 
        ReadingEnvelopeSize,
        EnvelopeStart, 
        ReadingEnvelopeBytes, 
        EnvelopeEnd,
        ReadingEndRecord, 
        End,
    }

    abstract class ClientFramingDecoder : FramingDecoder 
    {
        ClientFramingDecoderState currentState; 
 
        protected ClientFramingDecoder(long streamPosition)
            : base(streamPosition) 
        {
            this.currentState = ClientFramingDecoderState.ReadingUpgradeRecord;
        }
 
        public ClientFramingDecoderState CurrentState
        { 
            get 
            {
                return this.currentState; 
            }

            protected set
            { 
                this.currentState = value;
            } 
        } 

        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 
    class ClientDuplexDecoder : ClientFramingDecoder
    { 
        IntDecoder sizeDecoder;
        FaultStringDecoder faultDecoder;
        int envelopeBytesNeeded;
        int envelopeSize; 

        public ClientDuplexDecoder(long streamPosition) 
            : base(streamPosition) 
        {
            sizeDecoder = new IntDecoder(); 
        }

        public int EnvelopeSize
        { 
            get
            { 
                if (CurrentState < ClientFramingDecoderState.EnvelopeStart) 
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable))); 
                return envelopeSize;
            }
        }
 
        public override string Fault
        { 
            get 
            {
                if (CurrentState < ClientFramingDecoderState.Fault) 
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(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.GetString(SR.FramingAtEnd)))); 
                    default: 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }

                StreamPosition += bytesConsumed;
                return bytesConsumed; 
            }
            catch (InvalidDataException e) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
            } 
        }
    }

    // Pattern: 
    //   (UpgradeResponse, upgrade-bytes)*, (Ack | Fault),
    //   End 
    class ClientSingletonDecoder : ClientFramingDecoder 
    {
        FaultStringDecoder faultDecoder; 

        public ClientSingletonDecoder(long streamPosition)
            : base(streamPosition)
        { 
        }
 
        public override string Fault 
        {
            get 
            {
                if (CurrentState < ClientFramingDecoderState.Fault)
#pragma warning suppress 56503 // [....], not a publicly accessible API
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(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.GetString(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.GetString(SR.FramingAtEnd)))); 
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                            CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)))); 
                }
 
                StreamPosition += bytesConsumed;
                return bytesConsumed;
            }
            catch (InvalidDataException e) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e)); 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK