< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.ServerSessionDecoder
Assembly: CoreWCF.MSMQ
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.MSMQ/src/CoreWCF/Channels/FramingDecoder.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 123
Coverable lines: 123
Total lines: 1454
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 45
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
Reset()100%110%
Decode(...)0%37370%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.MSMQ/src/CoreWCF/Channels/FramingDecoder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Buffers;
 6using System.Globalization;
 7using System.IO;
 8using System.IO.Pipelines;
 9using System.Text;
 10using System.Threading.Tasks;
 11using CoreWCF.Runtime;
 12using Microsoft.Extensions.Logging;
 13
 14namespace CoreWCF.Channels
 15{
 16    internal static class DecoderHelper
 17    {
 18        public static void ValidateSize(long size)
 19        {
 20            if (size <= 0)
 21            {
 22                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 23                    new ArgumentOutOfRangeException(nameof(size), size, SR.ValueMustBePositive));
 24            }
 25        }
 26    }
 27
 28    internal struct IntDecoder
 29    {
 30        public IntDecoder(ILogger logger)
 31        {
 32            Logger = logger;
 33            IsValueDecoded = false;
 34            _value = 0;
 35            _index = 0;
 36        }
 37
 38        private int _value;
 39        private short _index;
 40        private const int LastIndex = 4;
 41
 42        public int Value
 43        {
 44            get
 45            {
 46                if (!IsValueDecoded)
 47                {
 48                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 49                        new InvalidOperationException(SR.FramingValueNotAvailable));
 50                }
 51
 52                return _value;
 53            }
 54        }
 55
 56        public bool IsValueDecoded { get; private set; }
 57
 58        private ILogger Logger { get; }
 59
 60        public void Reset()
 61        {
 62            _index = 0;
 63            _value = 0;
 64            IsValueDecoded = false;
 65        }
 66
 67        public int Decode(ReadOnlySequence<byte> buffer)
 68        {
 69            DecoderHelper.ValidateSize(buffer.Length);
 70            if (IsValueDecoded)
 71            {
 72                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 73                    new InvalidOperationException(SR.FramingValueNotAvailable));
 74            }
 75
 76            int bytesConsumed = 0;
 77
 78            while (bytesConsumed < buffer.Length)
 79            {
 80                ReadOnlySpan<byte> data = buffer.First.Span;
 81                int next = data[0];
 82                _value |= (next & 0x7F) << (_index * 7);
 83                bytesConsumed++;
 84                if (_index == LastIndex && (next & 0xF8) != 0)
 85                {
 86                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 87                        new InvalidDataException(SR.FramingSizeTooLarge));
 88                }
 89
 90                // Logger.DecodingInt(next, _index,_value);
 91                _index++;
 92                if ((next & 0x80) == 0)
 93                {
 94                    IsValueDecoded = true;
 95                    break;
 96                }
 97
 98                buffer = buffer.Slice(buffer.GetPosition(1));
 99            }
 100
 101            return bytesConsumed;
 102        }
 103    }
 104
 105    internal abstract class StringDecoder
 106    {
 107        private int _encodedSize;
 108        private byte[] _encodedBytes;
 109        private int _bytesNeeded;
 110        private string _value;
 111        private State _currentState;
 112        private IntDecoder _sizeDecoder;
 113        private readonly int _sizeQuota;
 114        private int _valueLengthInBytes;
 115
 116        public StringDecoder(int sizeQuota, ILogger logger)
 117        {
 118            Logger = logger;
 119            _sizeQuota = sizeQuota;
 120            _sizeDecoder = new IntDecoder(logger);
 121            Reset();
 122        }
 123
 124        protected ILogger Logger { get; }
 125
 126        public bool IsValueDecoded
 127        {
 128            get { return CurrentState == State.Done; }
 129        }
 130
 131        public string Value
 132        {
 133            get
 134            {
 135                if (CurrentState != State.Done)
 136                {
 137                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 138                        new InvalidOperationException(SR.FramingValueNotAvailable));
 139                }
 140
 141                return _value;
 142            }
 143        }
 144
 145        public State CurrentState
 146        {
 147            get => _currentState;
 148            private set => _currentState = value;
 149        }
 150
 151        public int Decode(ReadOnlySequence<byte> buffer)
 152        {
 153            DecoderHelper.ValidateSize(buffer.Length);
 154
 155            int bytesConsumed;
 156            // //Logger.LogStartState(this);
 157            switch (CurrentState)
 158            {
 159                case State.ReadingSize:
 160                    bytesConsumed = _sizeDecoder.Decode(buffer);
 161                    if (_sizeDecoder.IsValueDecoded)
 162                    {
 163                        _encodedSize = _sizeDecoder.Value;
 164                        if (_encodedSize > _sizeQuota)
 165                        {
 166                            Exception quotaExceeded = OnSizeQuotaExceeded(_encodedSize);
 167                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(quotaExceeded);
 168                        }
 169
 170                        if (_encodedBytes == null || _encodedBytes.Length < _encodedSize)
 171                        {
 172                            _encodedBytes = Fx.AllocateByteArray(_encodedSize);
 173                            _value = null;
 174                        }
 175
 176                        CurrentState = State.ReadingBytes;
 177                        _bytesNeeded = _encodedSize;
 178                    }
 179
 180                    break;
 181                case State.ReadingBytes:
 182                    if (_value != null && _valueLengthInBytes == _encodedSize && _bytesNeeded == _encodedSize &&
 183                        buffer.Length >= _encodedSize && CompareBuffers(_encodedBytes, buffer))
 184                    {
 185                        bytesConsumed = _bytesNeeded;
 186                        OnComplete(_value);
 187                    }
 188                    else
 189                    {
 190                        bytesConsumed = _bytesNeeded;
 191                        if (buffer.Length < _bytesNeeded)
 192                        {
 193                            bytesConsumed = (int)buffer.Length;
 194                        }
 195
 196                        Span<byte> span = _encodedBytes;
 197                        Span<byte> slicedBytes = span.Slice(_encodedSize - _bytesNeeded, bytesConsumed);
 198                        ReadOnlySequence<byte> tempBuffer = buffer.Slice(0, bytesConsumed);
 199                        tempBuffer.CopyTo(slicedBytes);
 200                        _bytesNeeded -= bytesConsumed;
 201                        if (_bytesNeeded == 0)
 202                        {
 203                            _value = Encoding.UTF8.GetString(_encodedBytes, 0, _encodedSize);
 204                            _valueLengthInBytes = _encodedSize;
 205                            //Logger.StringDecoded(_value);
 206                            OnComplete(_value);
 207                        }
 208                    }
 209
 210                    break;
 211                default:
 212                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 213                        new InvalidDataException(SR.InvalidDecoderStateMachine));
 214            }
 215
 216            //  Logger.LogEndState(this, bytesConsumed);
 217            return bytesConsumed;
 218        }
 219
 220        protected virtual void OnComplete(string value)
 221        {
 222            CurrentState = State.Done;
 223        }
 224
 225        private static bool CompareBuffers(byte[] buffer1, ReadOnlySequence<byte> buffer2)
 226        {
 227            byte[] buff = buffer2.ToArray();
 228            for (int i = 0; i < buffer1.Length; i++)
 229            {
 230                if (buffer1[i] != buff[i])
 231                {
 232                    return false;
 233                }
 234            }
 235
 236            return true;
 237        }
 238
 239        protected abstract Exception OnSizeQuotaExceeded(int size);
 240
 241        public void Reset()
 242        {
 243            CurrentState = State.ReadingSize;
 244            _sizeDecoder.Reset();
 245        }
 246
 247        public enum State
 248        {
 249            ReadingSize,
 250            ReadingBytes,
 251            Done,
 252        }
 253    }
 254
 255    internal class ViaStringDecoder : StringDecoder
 256    {
 257        private Uri _via;
 258
 259        public ViaStringDecoder(int sizeQuota, ILogger logger)
 260            : base(sizeQuota, logger)
 261        {
 262        }
 263
 264        protected override Exception OnSizeQuotaExceeded(int size)
 265        {
 266            Exception result = new InvalidDataException(SR.Format(SR.FramingViaTooLong, size));
 267            FramingEncodingString.AddFaultString(result, FramingEncodingString.ViaTooLongFault);
 268            return result;
 269        }
 270
 271        protected override void OnComplete(string value)
 272        {
 273            try
 274            {
 275                _via = new Uri(value);
 276                base.OnComplete(value);
 277            }
 278            catch (UriFormatException exception)
 279            {
 280                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 281                    new InvalidDataException(SR.Format(SR.FramingViaNotUri, value), exception));
 282            }
 283        }
 284
 285        public Uri ValueAsUri
 286        {
 287            get
 288            {
 289                if (!IsValueDecoded)
 290                {
 291                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 292                        new InvalidOperationException(SR.FramingValueNotAvailable));
 293                }
 294
 295                return _via;
 296            }
 297        }
 298    }
 299
 300    internal class FaultStringDecoder : StringDecoder
 301    {
 302        internal const int FaultSizeQuota = 256;
 303
 304        public FaultStringDecoder(ILogger logger)
 305            : base(FaultSizeQuota, logger)
 306        {
 307        }
 308
 309        protected override Exception OnSizeQuotaExceeded(int size)
 310        {
 311            return new InvalidDataException(SR.Format(SR.FramingFaultTooLong, size));
 312        }
 313
 314        public static Exception GetFaultException(string faultString, string via, string contentType)
 315        {
 316            if (faultString == FramingEncodingString.EndpointNotFoundFault)
 317            {
 318                return new EndpointNotFoundException(SR.Format(SR.EndpointNotFound, via));
 319            }
 320            else if (faultString == FramingEncodingString.ContentTypeInvalidFault)
 321            {
 322                return new ProtocolException(SR.Format(SR.FramingContentTypeMismatch, contentType, via));
 323            }
 324            else if (faultString == FramingEncodingString.ServiceActivationFailedFault)
 325            {
 326                return new ServiceActivationException(SR.Format(SR.Hosting_ServiceActivationFailed, via));
 327            }
 328            else if (faultString == FramingEncodingString.ConnectionDispatchFailedFault)
 329            {
 330                return new CommunicationException(SR.Format(SR.Sharing_ConnectionDispatchFailed, via));
 331            }
 332            else if (faultString == FramingEncodingString.EndpointUnavailableFault)
 333            {
 334                return new EndpointNotFoundException(SR.Format(SR.Sharing_EndpointUnavailable, via));
 335            }
 336            else if (faultString == FramingEncodingString.MaxMessageSizeExceededFault)
 337            {
 338                Exception inner = new QuotaExceededException(SR.FramingMaxMessageSizeExceeded);
 339                return new CommunicationException(inner.Message, inner);
 340            }
 341            else if (faultString == FramingEncodingString.UnsupportedModeFault)
 342            {
 343                return new ProtocolException(SR.Format(SR.FramingModeNotSupportedFault, via));
 344            }
 345            else if (faultString == FramingEncodingString.UnsupportedVersionFault)
 346            {
 347                return new ProtocolException(SR.Format(SR.FramingVersionNotSupportedFault, via));
 348            }
 349            else if (faultString == FramingEncodingString.ContentTypeTooLongFault)
 350            {
 351                Exception inner = new QuotaExceededException(SR.Format(SR.FramingContentTypeTooLongFault, contentType));
 352                return new CommunicationException(inner.Message, inner);
 353            }
 354            else if (faultString == FramingEncodingString.ViaTooLongFault)
 355            {
 356                Exception inner = new QuotaExceededException(SR.Format(SR.FramingViaTooLongFault, via));
 357                return new CommunicationException(inner.Message, inner);
 358            }
 359            else if (faultString == FramingEncodingString.ServerTooBusyFault)
 360            {
 361                return new ServerTooBusyException(SR.Format(SR.ServerTooBusy, via));
 362            }
 363            else if (faultString == FramingEncodingString.UpgradeInvalidFault)
 364            {
 365                return new ProtocolException(SR.Format(SR.FramingUpgradeInvalid, via));
 366            }
 367            else
 368            {
 369                return new ProtocolException(SR.Format(SR.FramingFaultUnrecognized, faultString));
 370            }
 371        }
 372    }
 373
 374    internal class ContentTypeStringDecoder : StringDecoder
 375    {
 376        public ContentTypeStringDecoder(int sizeQuota, ILogger logger)
 377            : base(sizeQuota, logger)
 378        {
 379        }
 380
 381        protected override Exception OnSizeQuotaExceeded(int size)
 382        {
 383            Exception result = new InvalidDataException(SR.Format(SR.FramingContentTypeTooLong, size));
 384            FramingEncodingString.AddFaultString(result, FramingEncodingString.ContentTypeTooLongFault);
 385            return result;
 386        }
 387
 388        public static string GetString(FramingEncodingType type)
 389        {
 390            switch (type)
 391            {
 392                case FramingEncodingType.Soap11Utf8:
 393                    return FramingEncodingString.Soap11Utf8;
 394                case FramingEncodingType.Soap11Utf16:
 395                    return FramingEncodingString.Soap11Utf16;
 396                case FramingEncodingType.Soap11Utf16FFFE:
 397                    return FramingEncodingString.Soap11Utf16FFFE;
 398                case FramingEncodingType.Soap12Utf8:
 399                    return FramingEncodingString.Soap12Utf8;
 400                case FramingEncodingType.Soap12Utf16:
 401                    return FramingEncodingString.Soap12Utf16;
 402                case FramingEncodingType.Soap12Utf16FFFE:
 403                    return FramingEncodingString.Soap12Utf16FFFE;
 404                case FramingEncodingType.MTOM:
 405                    return FramingEncodingString.MTOM;
 406                case FramingEncodingType.Binary:
 407                    return FramingEncodingString.Binary;
 408                case FramingEncodingType.BinarySession:
 409                    return FramingEncodingString.BinarySession;
 410                case FramingEncodingType.ExtendedBinaryGZip:
 411                    return FramingEncodingString.ExtendedBinaryGZip;
 412                case FramingEncodingType.ExtendedBinarySessionGZip:
 413                    return FramingEncodingString.ExtendedBinarySessionGZip;
 414                case FramingEncodingType.ExtendedBinaryDeflate:
 415                    return FramingEncodingString.ExtendedBinaryDeflate;
 416                case FramingEncodingType.ExtendedBinarySessionDeflate:
 417                    return FramingEncodingString.ExtendedBinarySessionDeflate;
 418                default:
 419                    return "unknown" + ((int)type).ToString(CultureInfo.InvariantCulture);
 420            }
 421        }
 422    }
 423
 424    internal abstract class FramingDecoder
 425    {
 426        protected FramingDecoder(ILogger logger) => Logger = logger;
 427
 428        protected abstract string CurrentStateAsString { get; }
 429
 430        public virtual string ContentType
 431        {
 432            get { throw new NotImplementedException(); }
 433        }
 434
 435        protected ILogger Logger { get; }
 436
 437        public virtual Uri Via
 438        {
 439            get { throw new NotImplementedException(); }
 440        }
 441
 442        public abstract int Decode(ReadOnlySequence<byte> buffer);
 443
 444        protected void ValidateFramingMode(FramingMode mode)
 445        {
 446            switch (mode)
 447            {
 448                case FramingMode.Singleton:
 449                case FramingMode.Duplex:
 450                case FramingMode.Simplex:
 451                case FramingMode.SingletonSized:
 452                    break;
 453                default:
 454                    {
 455                        Exception exception = CreateException(new InvalidDataException(SR.Format(
 456                            SR.FramingModeNotSupported, mode.ToString())), FramingEncodingString.UnsupportedModeFault);
 457                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
 458                    }
 459            }
 460        }
 461
 462        protected void ValidateRecordType(FramingRecordType expectedType, FramingRecordType foundType)
 463        {
 464            if (foundType != expectedType)
 465            {
 466                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 467                    CreateInvalidRecordTypeException(expectedType, foundType));
 468            }
 469        }
 470
 471        // special validation for Preamble Ack for usability purposes (MB#39593)
 472        protected void ValidatePreambleAck(FramingRecordType foundType)
 473        {
 474            if (foundType != FramingRecordType.PreambleAck)
 475            {
 476                Exception inner = CreateInvalidRecordTypeException(FramingRecordType.PreambleAck, foundType);
 477                string exceptionString;
 478                if (((byte)foundType == 'h') || ((byte)foundType == 'H'))
 479                {
 480                    exceptionString = SR.PreambleAckIncorrectMaybeHttp;
 481                }
 482                else
 483                {
 484                    exceptionString = SR.PreambleAckIncorrect;
 485                }
 486
 487                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(exceptionString,
 488                    inner));
 489            }
 490        }
 491
 492        private Exception CreateInvalidRecordTypeException(FramingRecordType expectedType, FramingRecordType foundType)
 493        {
 494            return new InvalidDataException(SR.Format(SR.FramingRecordTypeMismatch, expectedType.ToString(),
 495                foundType.ToString()));
 496        }
 497
 498        protected void ValidateMajorVersion(int majorVersion)
 499        {
 500            if (majorVersion != FramingVersion.Major)
 501            {
 502                Exception exception = CreateException(new InvalidDataException(SR.Format(
 503                    SR.FramingVersionNotSupported, majorVersion)), FramingEncodingString.UnsupportedVersionFault);
 504                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
 505            }
 506        }
 507
 508        public Exception CreatePrematureEOFException()
 509        {
 510            return CreateException(new InvalidDataException(SR.FramingPrematureEOF));
 511        }
 512
 513        protected Exception CreateException(InvalidDataException innerException, string framingFault)
 514        {
 515            Exception result = CreateException(innerException);
 516            FramingEncodingString.AddFaultString(result, framingFault);
 517            return result;
 518        }
 519
 520        protected Exception CreateException(InvalidDataException innerException)
 521        {
 522            // TODO: Can the position still be recovered?
 523            return new ProtocolException(SR.Format(SR.FramingError, /*StreamPosition*/ -1, CurrentStateAsString),
 524                innerException);
 525        }
 526    }
 527
 528    // Pattern:
 529    //   Done
 530    internal class ServerModeDecoder : FramingDecoder
 531    {
 532        private int _majorVersion;
 533        private int _minorVersion;
 534        private FramingMode _mode;
 535
 536        public ServerModeDecoder(ILogger logger) : base(logger)
 537        {
 538            Reset();
 539        }
 540
 541        public override int Decode(ReadOnlySequence<byte> buffer)
 542        {
 543            DecoderHelper.ValidateSize(buffer.Length);
 544            ReadOnlySpan<byte> data = buffer.First.Span;
 545
 546            try
 547            {
 548                int bytesConsumed;
 549                //Logger.LogStartState(this);
 550                switch (CurrentState)
 551                {
 552                    case State.ReadingVersionRecord:
 553                        ValidateRecordType(FramingRecordType.Version, (FramingRecordType)data[0]);
 554                        CurrentState = State.ReadingMajorVersion;
 555                        bytesConsumed = 1;
 556                        break;
 557                    case State.ReadingMajorVersion:
 558                        _majorVersion = data[0];
 559                        ValidateMajorVersion(_majorVersion);
 560                        CurrentState = State.ReadingMinorVersion;
 561                        bytesConsumed = 1;
 562                        break;
 563                    case State.ReadingMinorVersion:
 564                        _minorVersion = data[0];
 565                        CurrentState = State.ReadingModeRecord;
 566                        bytesConsumed = 1;
 567                        break;
 568                    case State.ReadingModeRecord:
 569                        ValidateRecordType(FramingRecordType.Mode, (FramingRecordType)data[0]);
 570                        CurrentState = State.ReadingModeValue;
 571                        bytesConsumed = 1;
 572                        break;
 573                    case State.ReadingModeValue:
 574                        _mode = (FramingMode)data[0];
 575                        ValidateFramingMode(_mode);
 576                        CurrentState = State.Done;
 577                        bytesConsumed = 1;
 578                        break;
 579                    default:
 580                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 581                            CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine)));
 582                }
 583
 584                //  Logger.LogEndState(this, bytesConsumed);
 585                return bytesConsumed;
 586            }
 587            catch (InvalidDataException e)
 588            {
 589                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
 590            }
 591        }
 592
 593        public void Reset()
 594        {
 595            CurrentState = State.ReadingVersionRecord;
 596        }
 597
 598        internal async Task<bool> ReadModeAsync(PipeReader inputPipe)
 599        {
 600            ReadOnlySequence<byte> buffer;
 601            while (true)
 602            {
 603                ReadResult readResult = await inputPipe.ReadAsync();
 604                if (readResult.IsCompleted)
 605                {
 606                    return false;
 607                }
 608
 609                buffer = readResult.Buffer;
 610
 611                while (buffer.Length > 0)
 612                {
 613                    int bytesDecoded;
 614                    try
 615                    {
 616                        bytesDecoded = Decode(buffer);
 617                    }
 618                    catch (CommunicationException e)
 619                    {
 620                        // see if we need to send back a framing fault
 621                        if (FramingEncodingString.TryGetFaultString(e, out string framingFault))
 622                        {
 623                            // TODO: Drain the rest of the data and send a fault then close the connection
 624                            //byte[] drainBuffer = new byte[128];
 625                            //InitialServerConnectionReader.SendFault(
 626                            //    Connection, framingFault, drainBuffer, GetRemainingTimeout(),
 627                            //    MaxViaSize + MaxContentTypeSize);
 628                            //base.Close(GetRemainingTimeout());
 629                        }
 630
 631                        throw;
 632                    }
 633
 634                    if (bytesDecoded > 0)
 635                    {
 636                        buffer = buffer.Slice(bytesDecoded);
 637                    }
 638
 639                    if (CurrentState == State.Done)
 640                    {
 641                        inputPipe.AdvanceTo(buffer.Start);
 642                        return true;
 643                    }
 644                }
 645
 646                inputPipe.AdvanceTo(buffer.End);
 647            }
 648        }
 649
 650        public State CurrentState { get; private set; }
 651
 652        protected override string CurrentStateAsString => CurrentState.ToString();
 653
 654        public FramingMode Mode
 655        {
 656            get
 657            {
 658                if (CurrentState != State.Done)
 659                {
 660                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 661                        new InvalidOperationException(SR.FramingValueNotAvailable));
 662                }
 663
 664                return _mode;
 665            }
 666        }
 667
 668        public int MajorVersion
 669        {
 670            get
 671            {
 672                if (CurrentState != State.Done)
 673                {
 674                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 675                        new InvalidOperationException(SR.FramingValueNotAvailable));
 676                }
 677
 678                return _majorVersion;
 679            }
 680        }
 681
 682        public int MinorVersion
 683        {
 684            get
 685            {
 686                if (CurrentState != State.Done)
 687                {
 688                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 689                        new InvalidOperationException(SR.FramingValueNotAvailable));
 690                }
 691
 692                return _minorVersion;
 693            }
 694        }
 695
 696        public enum State
 697        {
 698            ReadingVersionRecord,
 699            ReadingMajorVersion,
 700            ReadingMinorVersion,
 701            ReadingModeRecord,
 702            ReadingModeValue,
 703            Done,
 704        }
 705    }
 706
 707    // Used for Duplex/Simplex
 708    // Pattern:
 709    //   Start,
 710    //   (UpgradeRequest, upgrade-content-type)*,
 711    //   (EnvelopeStart, ReadingEnvelopeBytes*, EnvelopeEnd)*,
 712    //   End
 713    internal class ServerSessionDecoder : FramingDecoder
 714    {
 715        private readonly ViaStringDecoder _viaDecoder;
 716        private readonly StringDecoder _contentTypeDecoder;
 717        private IntDecoder _sizeDecoder;
 718        private string _contentType;
 719        private int _envelopeBytesNeeded;
 720        private int _envelopeSize;
 721        private string _upgrade;
 722
 0723        public ServerSessionDecoder(int maxViaLength, int maxContentTypeLength, ILogger logger) : base(logger)
 724        {
 0725            _viaDecoder = new ViaStringDecoder(maxViaLength, logger);
 0726            _contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength, logger);
 0727            _sizeDecoder = new IntDecoder(logger);
 0728            Reset();
 0729        }
 730
 0731        public State CurrentState { get; private set; }
 732
 0733        protected override string CurrentStateAsString => CurrentState.ToString();
 734
 735        public override string ContentType
 736        {
 737            get
 738            {
 0739                if (CurrentState < State.PreUpgradeStart)
 740                {
 0741                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0742                        new InvalidOperationException(SR.FramingValueNotAvailable));
 743                }
 744
 0745                return _contentType;
 746            }
 747        }
 748
 749        public override Uri Via
 750        {
 751            get
 752            {
 0753                if (CurrentState < State.ReadingContentTypeRecord)
 754                {
 0755                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0756                        new InvalidOperationException(SR.FramingValueNotAvailable));
 757                }
 758
 0759                return _viaDecoder.ValueAsUri;
 760            }
 761        }
 762
 763        public void Reset()
 764        {
 0765            CurrentState = State.ReadingViaRecord;
 0766        }
 767
 768        public string Upgrade
 769        {
 770            get
 771            {
 0772                if (CurrentState != State.UpgradeRequest)
 773                {
 0774                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0775                        new InvalidOperationException(SR.FramingValueNotAvailable));
 776                }
 777
 0778                return _upgrade;
 779            }
 780        }
 781
 782        public int EnvelopeSize
 783        {
 784            get
 785            {
 0786                if (CurrentState < State.EnvelopeStart)
 787                {
 0788                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0789                        new InvalidOperationException(SR.FramingValueNotAvailable));
 790                }
 791
 0792                return _envelopeSize;
 793            }
 794        }
 795
 796        public override int Decode(ReadOnlySequence<byte> buffer)
 797        {
 0798            DecoderHelper.ValidateSize(buffer.Length);
 0799            ReadOnlySpan<byte> data = buffer.First.Span;
 800            try
 801            {
 802                int bytesConsumed;
 803                FramingRecordType recordType;
 804                //Logger.LogStartState(this);
 0805                switch (CurrentState)
 806                {
 807                    case State.ReadingViaRecord:
 0808                        recordType = (FramingRecordType)data[0];
 0809                        ValidateRecordType(FramingRecordType.Via, recordType);
 0810                        bytesConsumed = 1;
 0811                        _viaDecoder.Reset();
 0812                        CurrentState = State.ReadingViaString;
 0813                        break;
 814                    case State.ReadingViaString:
 0815                        bytesConsumed = _viaDecoder.Decode(buffer);
 0816                        if (_viaDecoder.IsValueDecoded)
 817                        {
 0818                            CurrentState = State.ReadingContentTypeRecord;
 819                        }
 820
 0821                        break;
 822                    case State.ReadingContentTypeRecord:
 0823                        recordType = (FramingRecordType)data[0];
 0824                        if (recordType == FramingRecordType.KnownEncoding)
 825                        {
 0826                            bytesConsumed = 1;
 0827                            CurrentState = State.ReadingContentTypeByte;
 828                        }
 829                        else
 830                        {
 0831                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
 0832                            bytesConsumed = 1;
 0833                            _contentTypeDecoder.Reset();
 0834                            CurrentState = State.ReadingContentTypeString;
 835                        }
 836
 0837                        break;
 838                    case State.ReadingContentTypeByte:
 0839                        _contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)data[0]);
 0840                        bytesConsumed = 1;
 0841                        CurrentState = State.PreUpgradeStart;
 0842                        break;
 843                    case State.ReadingContentTypeString:
 0844                        bytesConsumed = _contentTypeDecoder.Decode(buffer);
 0845                        if (_contentTypeDecoder.IsValueDecoded)
 846                        {
 0847                            CurrentState = State.PreUpgradeStart;
 0848                            _contentType = _contentTypeDecoder.Value;
 849                        }
 850
 0851                        break;
 852                    case State.PreUpgradeStart:
 0853                        bytesConsumed = 0;
 0854                        CurrentState = State.ReadingUpgradeRecord;
 0855                        break;
 856                    case State.ReadingUpgradeRecord:
 0857                        recordType = (FramingRecordType)data[0];
 0858                        if (recordType == FramingRecordType.UpgradeRequest)
 859                        {
 0860                            bytesConsumed = 1;
 0861                            _contentTypeDecoder.Reset();
 0862                            CurrentState = State.ReadingUpgradeString;
 863                        }
 864                        else
 865                        {
 0866                            bytesConsumed = 0;
 0867                            CurrentState = State.ReadingPreambleEndRecord;
 868                        }
 869
 0870                        break;
 871                    case State.ReadingUpgradeString:
 0872                        bytesConsumed = _contentTypeDecoder.Decode(buffer);
 0873                        if (_contentTypeDecoder.IsValueDecoded)
 874                        {
 0875                            CurrentState = State.UpgradeRequest;
 0876                            _upgrade = _contentTypeDecoder.Value;
 877                        }
 878
 0879                        break;
 880                    case State.UpgradeRequest:
 0881                        bytesConsumed = 0;
 0882                        CurrentState = State.ReadingUpgradeRecord;
 0883                        break;
 884                    case State.ReadingPreambleEndRecord:
 0885                        recordType = (FramingRecordType)data[0];
 0886                        ValidateRecordType(FramingRecordType.PreambleEnd, recordType);
 0887                        bytesConsumed = 1;
 0888                        CurrentState = State.Start;
 0889                        break;
 890                    case State.Start:
 0891                        bytesConsumed = 0;
 0892                        CurrentState = State.ReadingEndRecord;
 0893                        break;
 894                    case State.ReadingEndRecord:
 0895                        recordType = (FramingRecordType)data[0];
 0896                        if (recordType == FramingRecordType.End)
 897                        {
 0898                            bytesConsumed = 1;
 0899                            CurrentState = State.End;
 900                        }
 901                        else
 902                        {
 0903                            bytesConsumed = 0;
 0904                            CurrentState = State.ReadingEnvelopeRecord;
 905                        }
 906
 0907                        break;
 908                    case State.ReadingEnvelopeRecord:
 0909                        ValidateRecordType(FramingRecordType.SizedEnvelope, (FramingRecordType)data[0]);
 0910                        bytesConsumed = 1;
 0911                        CurrentState = State.ReadingEnvelopeSize;
 0912                        _sizeDecoder.Reset();
 0913                        break;
 914                    case State.ReadingEnvelopeSize:
 0915                        bytesConsumed = _sizeDecoder.Decode(buffer);
 0916                        if (_sizeDecoder.IsValueDecoded)
 917                        {
 0918                            CurrentState = State.EnvelopeStart;
 0919                            _envelopeSize = _sizeDecoder.Value;
 0920                            _envelopeBytesNeeded = _envelopeSize;
 921                        }
 922
 0923                        break;
 924                    case State.EnvelopeStart:
 0925                        bytesConsumed = 0;
 0926                        CurrentState = State.ReadingEnvelopeBytes;
 0927                        break;
 928                    case State.ReadingEnvelopeBytes:
 0929                        bytesConsumed = (int)buffer.Length;
 0930                        if (bytesConsumed > _envelopeBytesNeeded)
 931                        {
 0932                            bytesConsumed = _envelopeBytesNeeded;
 933                        }
 934
 0935                        _envelopeBytesNeeded -= bytesConsumed;
 0936                        if (_envelopeBytesNeeded == 0)
 937                        {
 0938                            CurrentState = State.EnvelopeEnd;
 939                        }
 940
 0941                        break;
 942                    case State.EnvelopeEnd:
 0943                        bytesConsumed = 0;
 0944                        CurrentState = State.ReadingEndRecord;
 0945                        break;
 946                    case State.End:
 0947                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0948                            CreateException(new InvalidDataException(SR.FramingAtEnd)));
 949                    default:
 0950                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 0951                            CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine)));
 952                }
 953
 954                // Logger.LogEndState(this, bytesConsumed);
 0955                return bytesConsumed;
 956            }
 0957            catch (InvalidDataException e)
 958            {
 0959                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
 960            }
 0961        }
 962
 963        public enum State
 964        {
 965            ReadingViaRecord,
 966            ReadingViaString,
 967            ReadingContentTypeRecord,
 968            ReadingContentTypeString,
 969            ReadingContentTypeByte,
 970            PreUpgradeStart,
 971            ReadingUpgradeRecord,
 972            ReadingUpgradeString,
 973            UpgradeRequest,
 974            ReadingPreambleEndRecord,
 975            Start,
 976            ReadingEnvelopeRecord,
 977            ReadingEnvelopeSize,
 978            EnvelopeStart,
 979            ReadingEnvelopeBytes,
 980            EnvelopeEnd,
 981            ReadingEndRecord,
 982            End,
 983        }
 984    }
 985
 986    internal class SingletonMessageDecoder : FramingDecoder
 987    {
 988        private IntDecoder _sizeDecoder;
 989        private int _chunkBytesNeeded;
 990        private int _chunkSize;
 991
 992        public SingletonMessageDecoder(ILogger logger) : base(logger)
 993        {
 994            _sizeDecoder = new IntDecoder(logger);
 995            CurrentState = State.ChunkStart;
 996        }
 997
 998        public void Reset()
 999        {
 1000            CurrentState = State.ChunkStart;
 1001        }
 1002
 1003        public State CurrentState { get; private set; }
 1004
 1005        protected override string CurrentStateAsString => CurrentState.ToString();
 1006
 1007        public int ChunkSize
 1008        {
 1009            get
 1010            {
 1011                if (CurrentState < State.ChunkStart)
 1012                {
 1013                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1014                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1015                }
 1016
 1017                return _chunkSize;
 1018            }
 1019        }
 1020
 1021        public override int Decode(ReadOnlySequence<byte> buffer)
 1022        {
 1023            DecoderHelper.ValidateSize(buffer.Length);
 1024            ReadOnlySpan<byte> data = buffer.First.Span;
 1025            try
 1026            {
 1027                int bytesConsumed;
 1028                //Logger.LogStartState(this);
 1029                switch (CurrentState)
 1030                {
 1031                    case State.ReadingEnvelopeChunkSize:
 1032                        bytesConsumed = _sizeDecoder.Decode(buffer);
 1033                        if (_sizeDecoder.IsValueDecoded)
 1034                        {
 1035                            _chunkSize = _sizeDecoder.Value;
 1036                            _sizeDecoder.Reset();
 1037
 1038                            if (_chunkSize == 0)
 1039                            {
 1040                                CurrentState = State.EnvelopeEnd;
 1041                            }
 1042                            else
 1043                            {
 1044                                CurrentState = State.ChunkStart;
 1045                                _chunkBytesNeeded = _chunkSize;
 1046                            }
 1047                        }
 1048
 1049                        break;
 1050                    case State.ChunkStart:
 1051                        bytesConsumed = 0;
 1052                        CurrentState = State.ReadingEnvelopeBytes;
 1053                        break;
 1054                    case State.ReadingEnvelopeBytes:
 1055                        bytesConsumed = (int)buffer.Length;
 1056                        if (bytesConsumed > _chunkBytesNeeded)
 1057                        {
 1058                            bytesConsumed = _chunkBytesNeeded;
 1059                        }
 1060
 1061                        _chunkBytesNeeded -= bytesConsumed;
 1062                        if (_chunkBytesNeeded == 0)
 1063                        {
 1064                            CurrentState = State.ChunkEnd;
 1065                        }
 1066
 1067                        break;
 1068                    case State.ChunkEnd:
 1069                        bytesConsumed = 0;
 1070                        CurrentState = State.ReadingEnvelopeChunkSize;
 1071                        break;
 1072                    case State.EnvelopeEnd:
 1073                        ValidateRecordType(FramingRecordType.End, (FramingRecordType)data[0]);
 1074                        bytesConsumed = 1;
 1075                        CurrentState = State.End;
 1076                        break;
 1077                    case State.End:
 1078                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1079                            CreateException(new InvalidDataException(SR.FramingAtEnd)));
 1080
 1081                    default:
 1082                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1083                            CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine)));
 1084                }
 1085
 1086                // Logger.LogEndState(this, bytesConsumed);
 1087                return bytesConsumed;
 1088            }
 1089            catch (InvalidDataException e)
 1090            {
 1091                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
 1092            }
 1093        }
 1094
 1095        public enum State
 1096        {
 1097            ReadingEnvelopeChunkSize,
 1098            ChunkStart,
 1099            ReadingEnvelopeBytes,
 1100            ChunkEnd,
 1101            EnvelopeEnd,
 1102            End,
 1103        }
 1104    }
 1105
 1106    // Pattern:
 1107    //   Start,
 1108    //   (UpgradeRequest, upgrade-bytes)*,
 1109    //   EnvelopeStart,
 1110    internal class ServerSingletonDecoder : FramingDecoder
 1111    {
 1112        private readonly ViaStringDecoder _viaDecoder;
 1113        private readonly ContentTypeStringDecoder _contentTypeDecoder;
 1114        private string _contentType;
 1115        private string _upgrade;
 1116
 1117        public ServerSingletonDecoder(int maxViaLength, int maxContentTypeLength, ILogger logger) : base(logger)
 1118        {
 1119            _viaDecoder = new ViaStringDecoder(maxViaLength, logger);
 1120            _contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength, logger);
 1121            Reset();
 1122        }
 1123
 1124        public void Reset()
 1125        {
 1126            CurrentState = State.ReadingViaRecord;
 1127        }
 1128
 1129        public State CurrentState { get; private set; }
 1130
 1131        protected override string CurrentStateAsString => CurrentState.ToString();
 1132
 1133        public override Uri Via
 1134        {
 1135            get
 1136            {
 1137                if (CurrentState < State.ReadingContentTypeRecord)
 1138                {
 1139                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1140                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1141                }
 1142
 1143                return _viaDecoder.ValueAsUri;
 1144            }
 1145        }
 1146
 1147        public override string ContentType
 1148        {
 1149            get
 1150            {
 1151                if (CurrentState < State.PreUpgradeStart)
 1152                {
 1153                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1154                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1155                }
 1156
 1157                return _contentType;
 1158            }
 1159        }
 1160
 1161        public string Upgrade
 1162        {
 1163            get
 1164            {
 1165                if (CurrentState != State.UpgradeRequest)
 1166                {
 1167                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1168                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1169                }
 1170
 1171                return _upgrade;
 1172            }
 1173        }
 1174
 1175        public override int Decode(ReadOnlySequence<byte> buffer)
 1176        {
 1177            DecoderHelper.ValidateSize(buffer.Length);
 1178            ReadOnlySpan<byte> data = buffer.First.Span;
 1179            try
 1180            {
 1181                int bytesConsumed;
 1182                FramingRecordType recordType;
 1183                //Logger.LogStartState(this);
 1184                switch (CurrentState)
 1185                {
 1186                    case State.ReadingViaRecord:
 1187                        recordType = (FramingRecordType)data[0];
 1188                        ValidateRecordType(FramingRecordType.Via, recordType);
 1189                        bytesConsumed = 1;
 1190                        _viaDecoder.Reset();
 1191                        CurrentState = State.ReadingViaString;
 1192                        break;
 1193                    case State.ReadingViaString:
 1194                        bytesConsumed = _viaDecoder.Decode(buffer);
 1195                        if (_viaDecoder.IsValueDecoded)
 1196                        {
 1197                            CurrentState = State.ReadingContentTypeRecord;
 1198                        }
 1199
 1200                        break;
 1201                    case State.ReadingContentTypeRecord:
 1202                        recordType = (FramingRecordType)data[0];
 1203                        if (recordType == FramingRecordType.KnownEncoding)
 1204                        {
 1205                            bytesConsumed = 1;
 1206                            CurrentState = State.ReadingContentTypeByte;
 1207                        }
 1208                        else
 1209                        {
 1210                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
 1211                            bytesConsumed = 1;
 1212                            _contentTypeDecoder.Reset();
 1213                            CurrentState = State.ReadingContentTypeString;
 1214                        }
 1215
 1216                        break;
 1217                    case State.ReadingContentTypeByte:
 1218                        _contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)data[0]);
 1219                        bytesConsumed = 1;
 1220                        CurrentState = State.PreUpgradeStart;
 1221                        break;
 1222                    case State.ReadingContentTypeString:
 1223                        bytesConsumed = _contentTypeDecoder.Decode(buffer);
 1224                        if (_contentTypeDecoder.IsValueDecoded)
 1225                        {
 1226                            CurrentState = State.PreUpgradeStart;
 1227                            _contentType = _contentTypeDecoder.Value;
 1228                        }
 1229
 1230                        break;
 1231                    case State.PreUpgradeStart:
 1232                        bytesConsumed = 0;
 1233                        CurrentState = State.ReadingUpgradeRecord;
 1234                        break;
 1235                    case State.ReadingUpgradeRecord:
 1236                        recordType = (FramingRecordType)data[0];
 1237                        if (recordType == FramingRecordType.UpgradeRequest)
 1238                        {
 1239                            bytesConsumed = 1;
 1240                            _contentTypeDecoder.Reset();
 1241                            CurrentState = State.ReadingUpgradeString;
 1242                        }
 1243                        else
 1244                        {
 1245                            bytesConsumed = 0;
 1246                            CurrentState = State.ReadingPreambleEndRecord;
 1247                        }
 1248
 1249                        break;
 1250                    case State.ReadingUpgradeString:
 1251                        bytesConsumed = _contentTypeDecoder.Decode(buffer);
 1252                        if (_contentTypeDecoder.IsValueDecoded)
 1253                        {
 1254                            CurrentState = State.UpgradeRequest;
 1255                            _upgrade = _contentTypeDecoder.Value;
 1256                        }
 1257
 1258                        break;
 1259                    case State.UpgradeRequest:
 1260                        bytesConsumed = 0;
 1261                        CurrentState = State.ReadingUpgradeRecord;
 1262                        break;
 1263                    case State.ReadingPreambleEndRecord:
 1264                        recordType = (FramingRecordType)data[0];
 1265                        ValidateRecordType(FramingRecordType.PreambleEnd, recordType);
 1266                        bytesConsumed = 1;
 1267                        CurrentState = State.Start;
 1268                        break;
 1269                    case State.Start:
 1270                        bytesConsumed = 0;
 1271                        CurrentState = State.ReadingEnvelopeRecord;
 1272                        break;
 1273                    case State.ReadingEnvelopeRecord:
 1274                        ValidateRecordType(FramingRecordType.UnsizedEnvelope, (FramingRecordType)data[0]);
 1275                        bytesConsumed = 1;
 1276                        CurrentState = State.EnvelopeStart;
 1277                        break;
 1278                    case State.EnvelopeStart:
 1279                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1280                            CreateException(new InvalidDataException(SR.FramingAtEnd)));
 1281                    default:
 1282                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1283                            CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine)));
 1284                }
 1285
 1286                // Logger.LogEndState(this, bytesConsumed);
 1287                return bytesConsumed;
 1288            }
 1289            catch (InvalidDataException e)
 1290            {
 1291                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
 1292            }
 1293        }
 1294
 1295        public enum State
 1296        {
 1297            ReadingViaRecord,
 1298            ReadingViaString,
 1299            ReadingContentTypeRecord,
 1300            ReadingContentTypeString,
 1301            ReadingContentTypeByte,
 1302            PreUpgradeStart,
 1303            ReadingUpgradeRecord,
 1304            ReadingUpgradeString,
 1305            UpgradeRequest,
 1306            ReadingPreambleEndRecord,
 1307            Start,
 1308            ReadingEnvelopeRecord,
 1309            EnvelopeStart,
 1310            ReadingEnvelopeChunkSize,
 1311            ChunkStart,
 1312            ReadingEnvelopeChunk,
 1313            ChunkEnd,
 1314            End,
 1315        }
 1316    }
 1317
 1318    // Pattern:
 1319    //   Start,
 1320    //   EnvelopeStart,
 1321    internal class ServerSingletonSizedDecoder : FramingDecoder
 1322    {
 1323        private readonly ViaStringDecoder _viaDecoder;
 1324        private readonly ContentTypeStringDecoder _contentTypeDecoder;
 1325        private string _contentType;
 1326
 1327        public ServerSingletonSizedDecoder(int maxViaLength, int maxContentTypeLength, ILogger logger) : base(logger)
 1328        {
 1329            _viaDecoder = new ViaStringDecoder(maxViaLength, logger);
 1330            _contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength, logger);
 1331            CurrentState = State.ReadingViaRecord;
 1332        }
 1333
 1334        public override int Decode(ReadOnlySequence<byte> buffer)
 1335        {
 1336            DecoderHelper.ValidateSize(buffer.Length);
 1337            ReadOnlySpan<byte> data = buffer.First.Span;
 1338            try
 1339            {
 1340                int bytesConsumed;
 1341                FramingRecordType recordType;
 1342                //Logger.LogStartState(this);
 1343                switch (CurrentState)
 1344                {
 1345                    case State.ReadingViaRecord:
 1346                        recordType = (FramingRecordType)data[0];
 1347                        ValidateRecordType(FramingRecordType.Via, recordType);
 1348                        bytesConsumed = 1;
 1349                        _viaDecoder.Reset();
 1350                        CurrentState = State.ReadingViaString;
 1351                        break;
 1352                    case State.ReadingViaString:
 1353                        bytesConsumed = _viaDecoder.Decode(buffer);
 1354                        if (_viaDecoder.IsValueDecoded)
 1355                        {
 1356                            CurrentState = State.ReadingContentTypeRecord;
 1357                        }
 1358
 1359                        break;
 1360                    case State.ReadingContentTypeRecord:
 1361                        recordType = (FramingRecordType)data[0];
 1362                        if (recordType == FramingRecordType.KnownEncoding)
 1363                        {
 1364                            bytesConsumed = 1;
 1365                            CurrentState = State.ReadingContentTypeByte;
 1366                        }
 1367                        else
 1368                        {
 1369                            ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
 1370                            bytesConsumed = 1;
 1371                            _contentTypeDecoder.Reset();
 1372                            CurrentState = State.ReadingContentTypeString;
 1373                        }
 1374
 1375                        break;
 1376                    case State.ReadingContentTypeByte:
 1377                        _contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)data[0]);
 1378                        bytesConsumed = 1;
 1379                        CurrentState = State.Start;
 1380                        break;
 1381                    case State.ReadingContentTypeString:
 1382                        bytesConsumed = _contentTypeDecoder.Decode(buffer);
 1383                        if (_contentTypeDecoder.IsValueDecoded)
 1384                        {
 1385                            CurrentState = State.Start;
 1386                            _contentType = _contentTypeDecoder.Value;
 1387                        }
 1388
 1389                        break;
 1390                    case State.Start:
 1391                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1392                            CreateException(new InvalidDataException(SR.FramingAtEnd)));
 1393                    default:
 1394                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1395                            CreateException(new InvalidDataException(SR.InvalidDecoderStateMachine)));
 1396                }
 1397
 1398                //  Logger.LogEndState(this, bytesConsumed);
 1399                return bytesConsumed;
 1400            }
 1401            catch (InvalidDataException e)
 1402            {
 1403                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
 1404            }
 1405        }
 1406
 1407        public void Reset(long streamPosition)
 1408        {
 1409            CurrentState = State.ReadingViaRecord;
 1410        }
 1411
 1412        public State CurrentState { get; private set; }
 1413
 1414        protected override string CurrentStateAsString => CurrentState.ToString();
 1415
 1416        public override Uri Via
 1417        {
 1418            get
 1419            {
 1420                if (CurrentState < State.ReadingContentTypeRecord)
 1421                {
 1422                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1423                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1424                }
 1425
 1426                return _viaDecoder.ValueAsUri;
 1427            }
 1428        }
 1429
 1430        public override string ContentType
 1431        {
 1432            get
 1433            {
 1434                if (CurrentState < State.Start)
 1435                {
 1436                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 1437                        new InvalidOperationException(SR.FramingValueNotAvailable));
 1438                }
 1439
 1440                return _contentType;
 1441            }
 1442        }
 1443
 1444        public enum State
 1445        {
 1446            ReadingViaRecord,
 1447            ReadingViaString,
 1448            ReadingContentTypeRecord,
 1449            ReadingContentTypeString,
 1450            ReadingContentTypeByte,
 1451            Start,
 1452        }
 1453    }
 1454}