1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
4 namespace System.ServiceModel.Channels
6 using System.Globalization;
7 using System.ServiceModel;
11 static class DecoderHelper
13 public static void ValidateSize(int size)
17 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("size", size, SR.GetString(
18 SR.ValueMustBePositive)));
28 const int LastIndex = 4;
35 #pragma warning suppress 56503 // [....], not a publicly accessible API
36 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
41 public bool IsValueDecoded
43 get { return isValueDecoded; }
50 isValueDecoded = false;
53 public int Decode(byte[] buffer, int offset, int size)
55 DecoderHelper.ValidateSize(size);
58 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
60 int bytesConsumed = 0;
61 while (bytesConsumed < size)
63 int next = buffer[offset];
64 value |= (next & 0x7F) << (index * 7);
66 if (index == LastIndex && (next & 0xF8) != 0)
68 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.FramingSizeTooLarge)));
71 if ((next & 0x80) == 0)
73 isValueDecoded = true;
82 abstract class StringDecoder
89 IntDecoder sizeDecoder;
91 int valueLengthInBytes;
93 public StringDecoder(int sizeQuota)
95 this.sizeQuota = sizeQuota;
96 this.sizeDecoder = new IntDecoder();
97 this.currentState = State.ReadingSize;
101 public bool IsValueDecoded
103 get { return currentState == State.Done; }
110 if (currentState != State.Done)
111 #pragma warning suppress 56503 // [....], not a publicly accessible API
112 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
117 public int Decode(byte[] buffer, int offset, int size)
119 DecoderHelper.ValidateSize(size);
122 switch (currentState)
124 case State.ReadingSize:
125 bytesConsumed = sizeDecoder.Decode(buffer, offset, size);
126 if (sizeDecoder.IsValueDecoded)
128 encodedSize = sizeDecoder.Value;
129 if (encodedSize > sizeQuota)
131 Exception quotaExceeded = OnSizeQuotaExceeded(encodedSize);
132 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(quotaExceeded);
134 if (encodedBytes == null || encodedBytes.Length < encodedSize)
136 encodedBytes = DiagnosticUtility.Utility.AllocateByteArray(encodedSize);
139 currentState = State.ReadingBytes;
140 bytesNeeded = encodedSize;
143 case State.ReadingBytes:
144 if (value != null && valueLengthInBytes == encodedSize && bytesNeeded == encodedSize &&
145 size >= encodedSize && CompareBuffers(encodedBytes, buffer, offset))
147 bytesConsumed = bytesNeeded;
152 bytesConsumed = bytesNeeded;
153 if (size < bytesNeeded)
154 bytesConsumed = size;
155 Buffer.BlockCopy(buffer, offset, encodedBytes, encodedSize - bytesNeeded, bytesConsumed);
156 bytesNeeded -= bytesConsumed;
157 if (bytesNeeded == 0)
159 value = Encoding.UTF8.GetString(encodedBytes, 0, encodedSize);
160 valueLengthInBytes = encodedSize;
166 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine)));
169 return bytesConsumed;
172 protected virtual void OnComplete(string value)
174 this.currentState = State.Done;
177 static bool CompareBuffers(byte[] buffer1, byte[] buffer2, int offset)
179 for (int i = 0; i < buffer1.Length; i++)
181 if (buffer1[i] != buffer2[i + offset])
189 protected abstract Exception OnSizeQuotaExceeded(int size);
193 currentState = State.ReadingSize;
205 class ViaStringDecoder : StringDecoder
209 public ViaStringDecoder(int sizeQuota)
214 protected override Exception OnSizeQuotaExceeded(int size)
216 Exception result = new InvalidDataException(SR.GetString(SR.FramingViaTooLong, size));
217 FramingEncodingString.AddFaultString(result, FramingEncodingString.ViaTooLongFault);
221 protected override void OnComplete(string value)
225 via = new Uri(value);
226 base.OnComplete(value);
228 catch (UriFormatException exception)
230 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.GetString(SR.FramingViaNotUri, value), exception));
234 public Uri ValueAsUri
239 #pragma warning suppress 56503 // [....], not a publicly accessible API
240 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
246 class FaultStringDecoder : StringDecoder
248 internal const int FaultSizeQuota = 256;
250 public FaultStringDecoder()
251 : base(FaultSizeQuota)
255 protected override Exception OnSizeQuotaExceeded(int size)
257 return new InvalidDataException(SR.GetString(SR.FramingFaultTooLong, size));
260 public static Exception GetFaultException(string faultString, string via, string contentType)
262 if (faultString == FramingEncodingString.EndpointNotFoundFault)
264 return new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, via));
266 else if (faultString == FramingEncodingString.ContentTypeInvalidFault)
268 return new ProtocolException(SR.GetString(SR.FramingContentTypeMismatch, contentType, via));
270 else if (faultString == FramingEncodingString.ServiceActivationFailedFault)
272 return new ServiceActivationException(SR.GetString(SR.Hosting_ServiceActivationFailed, via));
274 else if (faultString == FramingEncodingString.ConnectionDispatchFailedFault)
276 return new CommunicationException(SR.GetString(SR.Sharing_ConnectionDispatchFailed, via));
278 else if (faultString == FramingEncodingString.EndpointUnavailableFault)
280 return new EndpointNotFoundException(SR.GetString(SR.Sharing_EndpointUnavailable, via));
282 else if (faultString == FramingEncodingString.MaxMessageSizeExceededFault)
284 Exception inner = new QuotaExceededException(SR.GetString(SR.FramingMaxMessageSizeExceeded));
285 return new CommunicationException(inner.Message, inner);
287 else if (faultString == FramingEncodingString.UnsupportedModeFault)
289 return new ProtocolException(SR.GetString(SR.FramingModeNotSupportedFault, via));
291 else if (faultString == FramingEncodingString.UnsupportedVersionFault)
293 return new ProtocolException(SR.GetString(SR.FramingVersionNotSupportedFault, via));
295 else if (faultString == FramingEncodingString.ContentTypeTooLongFault)
297 Exception inner = new QuotaExceededException(SR.GetString(SR.FramingContentTypeTooLongFault, contentType));
298 return new CommunicationException(inner.Message, inner);
300 else if (faultString == FramingEncodingString.ViaTooLongFault)
302 Exception inner = new QuotaExceededException(SR.GetString(SR.FramingViaTooLongFault, via));
303 return new CommunicationException(inner.Message, inner);
305 else if (faultString == FramingEncodingString.ServerTooBusyFault)
307 return new ServerTooBusyException(SR.GetString(SR.ServerTooBusy, via));
309 else if (faultString == FramingEncodingString.UpgradeInvalidFault)
311 return new ProtocolException(SR.GetString(SR.FramingUpgradeInvalid, via));
315 return new ProtocolException(SR.GetString(SR.FramingFaultUnrecognized, faultString));
320 class ContentTypeStringDecoder : StringDecoder
322 public ContentTypeStringDecoder(int sizeQuota)
327 protected override Exception OnSizeQuotaExceeded(int size)
329 Exception result = new InvalidDataException(SR.GetString(SR.FramingContentTypeTooLong, size));
330 FramingEncodingString.AddFaultString(result, FramingEncodingString.ContentTypeTooLongFault);
334 public static string GetString(FramingEncodingType type)
338 case FramingEncodingType.Soap11Utf8:
339 return FramingEncodingString.Soap11Utf8;
340 case FramingEncodingType.Soap11Utf16:
341 return FramingEncodingString.Soap11Utf16;
342 case FramingEncodingType.Soap11Utf16FFFE:
343 return FramingEncodingString.Soap11Utf16FFFE;
344 case FramingEncodingType.Soap12Utf8:
345 return FramingEncodingString.Soap12Utf8;
346 case FramingEncodingType.Soap12Utf16:
347 return FramingEncodingString.Soap12Utf16;
348 case FramingEncodingType.Soap12Utf16FFFE:
349 return FramingEncodingString.Soap12Utf16FFFE;
350 case FramingEncodingType.MTOM:
351 return FramingEncodingString.MTOM;
352 case FramingEncodingType.Binary:
353 return FramingEncodingString.Binary;
354 case FramingEncodingType.BinarySession:
355 return FramingEncodingString.BinarySession;
357 return "unknown" + ((int)type).ToString(CultureInfo.InvariantCulture);
362 abstract class FramingDecoder
366 protected FramingDecoder()
370 protected FramingDecoder(long streamPosition)
372 this.streamPosition = streamPosition;
375 protected abstract string CurrentStateAsString { get; }
377 public long StreamPosition
379 get { return streamPosition; }
380 set { streamPosition = value; }
383 protected void ValidateFramingMode(FramingMode mode)
387 case FramingMode.Singleton:
388 case FramingMode.Duplex:
389 case FramingMode.Simplex:
390 case FramingMode.SingletonSized:
394 Exception exception = CreateException(new InvalidDataException(SR.GetString(
395 SR.FramingModeNotSupported, mode.ToString())), FramingEncodingString.UnsupportedModeFault);
396 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
401 protected void ValidateRecordType(FramingRecordType expectedType, FramingRecordType foundType)
403 if (foundType != expectedType)
405 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidRecordTypeException(expectedType, foundType));
409 // special validation for Preamble Ack for usability purposes (MB#39593)
410 protected void ValidatePreambleAck(FramingRecordType foundType)
412 if (foundType != FramingRecordType.PreambleAck)
414 Exception inner = CreateInvalidRecordTypeException(FramingRecordType.PreambleAck, foundType);
415 string exceptionString;
416 if (((byte)foundType == 'h') || ((byte)foundType == 'H'))
418 exceptionString = SR.GetString(SR.PreambleAckIncorrectMaybeHttp);
422 exceptionString = SR.GetString(SR.PreambleAckIncorrect);
424 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(exceptionString, inner));
428 Exception CreateInvalidRecordTypeException(FramingRecordType expectedType, FramingRecordType foundType)
430 return new InvalidDataException(SR.GetString(SR.FramingRecordTypeMismatch, expectedType.ToString(), foundType.ToString()));
433 protected void ValidateMajorVersion(int majorVersion)
435 if (majorVersion != FramingVersion.Major)
437 Exception exception = CreateException(new InvalidDataException(SR.GetString(
438 SR.FramingVersionNotSupported, majorVersion)), FramingEncodingString.UnsupportedVersionFault);
439 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
443 public Exception CreatePrematureEOFException()
445 return CreateException(new InvalidDataException(SR.GetString(SR.FramingPrematureEOF)));
448 protected Exception CreateException(InvalidDataException innerException, string framingFault)
450 Exception result = CreateException(innerException);
451 FramingEncodingString.AddFaultString(result, framingFault);
455 protected Exception CreateException(InvalidDataException innerException)
457 return new ProtocolException(SR.GetString(SR.FramingError, StreamPosition, CurrentStateAsString),
464 class ServerModeDecoder : FramingDecoder
471 public ServerModeDecoder()
473 currentState = State.ReadingVersionRecord;
476 public int Decode(byte[] bytes, int offset, int size)
478 DecoderHelper.ValidateSize(size);
483 switch (currentState)
485 case State.ReadingVersionRecord:
486 ValidateRecordType(FramingRecordType.Version, (FramingRecordType)bytes[offset]);
487 currentState = State.ReadingMajorVersion;
490 case State.ReadingMajorVersion:
491 majorVersion = bytes[offset];
492 ValidateMajorVersion(majorVersion);
493 currentState = State.ReadingMinorVersion;
496 case State.ReadingMinorVersion:
497 minorVersion = bytes[offset];
498 currentState = State.ReadingModeRecord;
501 case State.ReadingModeRecord:
502 ValidateRecordType(FramingRecordType.Mode, (FramingRecordType)bytes[offset]);
503 currentState = State.ReadingModeValue;
506 case State.ReadingModeValue:
507 mode = (FramingMode)bytes[offset];
508 ValidateFramingMode(mode);
509 currentState = State.Done;
513 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
514 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
517 StreamPosition += bytesConsumed;
518 return bytesConsumed;
520 catch (InvalidDataException e)
522 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
529 currentState = State.ReadingVersionRecord;
532 public State CurrentState
534 get { return currentState; }
537 protected override string CurrentStateAsString
539 get { return currentState.ToString(); }
542 public FramingMode Mode
546 if (currentState != State.Done)
547 #pragma warning suppress 56503 // [....], not a publicly accessible API
548 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
553 public int MajorVersion
557 if (currentState != State.Done)
558 #pragma warning suppress 56503 // [....], not a publicly accessible API
559 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
564 public int MinorVersion
568 if (currentState != State.Done)
569 #pragma warning suppress 56503 // [....], not a publicly accessible API
570 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
577 ReadingVersionRecord,
586 // Used for Duplex/Simplex
589 // (UpgradeRequest, upgrade-content-type)*,
590 // (EnvelopeStart, ReadingEnvelopeBytes*, EnvelopeEnd)*,
592 class ServerSessionDecoder : FramingDecoder
594 ViaStringDecoder viaDecoder;
595 StringDecoder contentTypeDecoder;
596 IntDecoder sizeDecoder;
599 int envelopeBytesNeeded;
603 public ServerSessionDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength)
604 : base(streamPosition)
606 this.viaDecoder = new ViaStringDecoder(maxViaLength);
607 this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength);
608 this.sizeDecoder = new IntDecoder();
609 this.currentState = State.ReadingViaRecord;
612 public State CurrentState
614 get { return currentState; }
617 protected override string CurrentStateAsString
619 get { return currentState.ToString(); }
622 public string ContentType
626 if (currentState < State.PreUpgradeStart)
627 #pragma warning suppress 56503 // [....], not a publicly accessible API
628 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
637 if (currentState < State.ReadingContentTypeRecord)
638 #pragma warning suppress 56503 // [....], not a publicly accessible API
639 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
640 return viaDecoder.ValueAsUri;
644 public void Reset(long streamPosition)
646 this.StreamPosition = streamPosition;
647 this.currentState = State.ReadingViaRecord;
650 public string Upgrade
654 if (currentState != State.UpgradeRequest)
655 #pragma warning suppress 56503 // [....], not a publicly accessible API
656 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
661 public int EnvelopeSize
665 if (currentState < State.EnvelopeStart)
666 #pragma warning suppress 56503 // [....], not a publicly accessible API
667 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
672 public int Decode(byte[] bytes, int offset, int size)
674 DecoderHelper.ValidateSize(size);
679 FramingRecordType recordType;
680 switch (currentState)
682 case State.ReadingViaRecord:
683 recordType = (FramingRecordType)bytes[offset];
684 ValidateRecordType(FramingRecordType.Via, recordType);
687 currentState = State.ReadingViaString;
689 case State.ReadingViaString:
690 bytesConsumed = viaDecoder.Decode(bytes, offset, size);
691 if (viaDecoder.IsValueDecoded)
693 currentState = State.ReadingContentTypeRecord;
696 case State.ReadingContentTypeRecord:
697 recordType = (FramingRecordType)bytes[offset];
698 if (recordType == FramingRecordType.KnownEncoding)
701 currentState = State.ReadingContentTypeByte;
705 ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
707 contentTypeDecoder.Reset();
708 currentState = State.ReadingContentTypeString;
711 case State.ReadingContentTypeByte:
712 contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]);
714 currentState = State.PreUpgradeStart;
716 case State.ReadingContentTypeString:
717 bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
718 if (contentTypeDecoder.IsValueDecoded)
720 currentState = State.PreUpgradeStart;
721 contentType = contentTypeDecoder.Value;
724 case State.PreUpgradeStart:
726 currentState = State.ReadingUpgradeRecord;
728 case State.ReadingUpgradeRecord:
729 recordType = (FramingRecordType)bytes[offset];
730 if (recordType == FramingRecordType.UpgradeRequest)
733 contentTypeDecoder.Reset();
734 currentState = State.ReadingUpgradeString;
739 currentState = State.ReadingPreambleEndRecord;
742 case State.ReadingUpgradeString:
743 bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
744 if (contentTypeDecoder.IsValueDecoded)
746 currentState = State.UpgradeRequest;
747 upgrade = contentTypeDecoder.Value;
750 case State.UpgradeRequest:
752 currentState = State.ReadingUpgradeRecord;
754 case State.ReadingPreambleEndRecord:
755 recordType = (FramingRecordType)bytes[offset];
756 ValidateRecordType(FramingRecordType.PreambleEnd, recordType);
758 currentState = State.Start;
762 currentState = State.ReadingEndRecord;
764 case State.ReadingEndRecord:
765 recordType = (FramingRecordType)bytes[offset];
766 if (recordType == FramingRecordType.End)
769 currentState = State.End;
774 currentState = State.ReadingEnvelopeRecord;
777 case State.ReadingEnvelopeRecord:
778 ValidateRecordType(FramingRecordType.SizedEnvelope, (FramingRecordType)bytes[offset]);
780 currentState = State.ReadingEnvelopeSize;
783 case State.ReadingEnvelopeSize:
784 bytesConsumed = sizeDecoder.Decode(bytes, offset, size);
785 if (sizeDecoder.IsValueDecoded)
787 currentState = State.EnvelopeStart;
788 envelopeSize = sizeDecoder.Value;
789 envelopeBytesNeeded = envelopeSize;
792 case State.EnvelopeStart:
794 currentState = State.ReadingEnvelopeBytes;
796 case State.ReadingEnvelopeBytes:
797 bytesConsumed = size;
798 if (bytesConsumed > envelopeBytesNeeded)
799 bytesConsumed = envelopeBytesNeeded;
800 envelopeBytesNeeded -= bytesConsumed;
801 if (envelopeBytesNeeded == 0)
802 currentState = State.EnvelopeEnd;
804 case State.EnvelopeEnd:
806 currentState = State.ReadingEndRecord;
809 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
810 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
812 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
813 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
816 StreamPosition += bytesConsumed;
817 return bytesConsumed;
819 catch (InvalidDataException e)
821 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
829 ReadingContentTypeRecord,
830 ReadingContentTypeString,
831 ReadingContentTypeByte,
833 ReadingUpgradeRecord,
834 ReadingUpgradeString,
836 ReadingPreambleEndRecord,
838 ReadingEnvelopeRecord,
841 ReadingEnvelopeBytes,
848 class SingletonMessageDecoder : FramingDecoder
850 IntDecoder sizeDecoder;
851 int chunkBytesNeeded;
855 public SingletonMessageDecoder(long streamPosition)
856 : base(streamPosition)
858 this.sizeDecoder = new IntDecoder();
859 this.currentState = State.ChunkStart;
864 this.currentState = State.ChunkStart;
867 public State CurrentState
869 get { return currentState; }
872 protected override string CurrentStateAsString
874 get { return currentState.ToString(); }
881 if (currentState < State.ChunkStart)
883 #pragma warning suppress 56503 // [....], not a publicly accessible API
884 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
887 return this.chunkSize;
891 public int Decode(byte[] bytes, int offset, int size)
893 DecoderHelper.ValidateSize(size);
898 switch (currentState)
900 case State.ReadingEnvelopeChunkSize:
901 bytesConsumed = sizeDecoder.Decode(bytes, offset, size);
902 if (sizeDecoder.IsValueDecoded)
904 this.chunkSize = sizeDecoder.Value;
907 if (this.chunkSize == 0)
909 currentState = State.EnvelopeEnd;
913 currentState = State.ChunkStart;
914 chunkBytesNeeded = chunkSize;
918 case State.ChunkStart:
920 currentState = State.ReadingEnvelopeBytes;
922 case State.ReadingEnvelopeBytes:
923 bytesConsumed = size;
924 if (bytesConsumed > chunkBytesNeeded)
926 bytesConsumed = chunkBytesNeeded;
928 chunkBytesNeeded -= bytesConsumed;
929 if (chunkBytesNeeded == 0)
931 currentState = State.ChunkEnd;
936 currentState = State.ReadingEnvelopeChunkSize;
938 case State.EnvelopeEnd:
939 ValidateRecordType(FramingRecordType.End, (FramingRecordType)bytes[offset]);
941 currentState = State.End;
944 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
945 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
948 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
949 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
952 StreamPosition += bytesConsumed;
953 return bytesConsumed;
955 catch (InvalidDataException e)
957 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
963 ReadingEnvelopeChunkSize,
965 ReadingEnvelopeBytes,
974 // (UpgradeRequest, upgrade-bytes)*,
976 class ServerSingletonDecoder : FramingDecoder
978 ViaStringDecoder viaDecoder;
979 ContentTypeStringDecoder contentTypeDecoder;
984 public ServerSingletonDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength)
985 : base(streamPosition)
987 this.viaDecoder = new ViaStringDecoder(maxViaLength);
988 this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength);
989 this.currentState = State.ReadingViaRecord;
994 this.currentState = State.ReadingViaRecord;
997 public State CurrentState
999 get { return currentState; }
1002 protected override string CurrentStateAsString
1004 get { return currentState.ToString(); }
1011 if (currentState < State.ReadingContentTypeRecord)
1012 #pragma warning suppress 56503 // [....], not a publicly accessible API
1013 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1014 return viaDecoder.ValueAsUri;
1018 public string ContentType
1022 if (currentState < State.PreUpgradeStart)
1023 #pragma warning suppress 56503 // [....], not a publicly accessible API
1024 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1029 public string Upgrade
1033 if (currentState != State.UpgradeRequest)
1034 #pragma warning suppress 56503 // [....], not a publicly accessible API
1035 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1040 public int Decode(byte[] bytes, int offset, int size)
1042 DecoderHelper.ValidateSize(size);
1047 FramingRecordType recordType;
1048 switch (currentState)
1050 case State.ReadingViaRecord:
1051 recordType = (FramingRecordType)bytes[offset];
1052 ValidateRecordType(FramingRecordType.Via, recordType);
1055 currentState = State.ReadingViaString;
1057 case State.ReadingViaString:
1058 bytesConsumed = viaDecoder.Decode(bytes, offset, size);
1059 if (viaDecoder.IsValueDecoded)
1061 currentState = State.ReadingContentTypeRecord;
1064 case State.ReadingContentTypeRecord:
1065 recordType = (FramingRecordType)bytes[offset];
1066 if (recordType == FramingRecordType.KnownEncoding)
1069 currentState = State.ReadingContentTypeByte;
1073 ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
1075 contentTypeDecoder.Reset();
1076 currentState = State.ReadingContentTypeString;
1079 case State.ReadingContentTypeByte:
1080 contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]);
1082 currentState = State.PreUpgradeStart;
1084 case State.ReadingContentTypeString:
1085 bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
1086 if (contentTypeDecoder.IsValueDecoded)
1088 currentState = State.PreUpgradeStart;
1089 contentType = contentTypeDecoder.Value;
1092 case State.PreUpgradeStart:
1094 currentState = State.ReadingUpgradeRecord;
1096 case State.ReadingUpgradeRecord:
1097 recordType = (FramingRecordType)bytes[offset];
1098 if (recordType == FramingRecordType.UpgradeRequest)
1101 contentTypeDecoder.Reset();
1102 currentState = State.ReadingUpgradeString;
1107 currentState = State.ReadingPreambleEndRecord;
1110 case State.ReadingUpgradeString:
1111 bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
1112 if (contentTypeDecoder.IsValueDecoded)
1114 currentState = State.UpgradeRequest;
1115 upgrade = contentTypeDecoder.Value;
1118 case State.UpgradeRequest:
1120 currentState = State.ReadingUpgradeRecord;
1122 case State.ReadingPreambleEndRecord:
1123 recordType = (FramingRecordType)bytes[offset];
1124 ValidateRecordType(FramingRecordType.PreambleEnd, recordType);
1126 currentState = State.Start;
1130 currentState = State.ReadingEnvelopeRecord;
1132 case State.ReadingEnvelopeRecord:
1133 ValidateRecordType(FramingRecordType.UnsizedEnvelope, (FramingRecordType)bytes[offset]);
1135 currentState = State.EnvelopeStart;
1137 case State.EnvelopeStart:
1138 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1139 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
1141 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1142 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
1145 StreamPosition += bytesConsumed;
1146 return bytesConsumed;
1148 catch (InvalidDataException e)
1150 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
1158 ReadingContentTypeRecord,
1159 ReadingContentTypeString,
1160 ReadingContentTypeByte,
1162 ReadingUpgradeRecord,
1163 ReadingUpgradeString,
1165 ReadingPreambleEndRecord,
1167 ReadingEnvelopeRecord,
1169 ReadingEnvelopeChunkSize,
1171 ReadingEnvelopeChunk,
1180 class ServerSingletonSizedDecoder : FramingDecoder
1182 ViaStringDecoder viaDecoder;
1183 ContentTypeStringDecoder contentTypeDecoder;
1187 public ServerSingletonSizedDecoder(long streamPosition, int maxViaLength, int maxContentTypeLength)
1188 : base(streamPosition)
1190 this.viaDecoder = new ViaStringDecoder(maxViaLength);
1191 this.contentTypeDecoder = new ContentTypeStringDecoder(maxContentTypeLength);
1192 this.currentState = State.ReadingViaRecord;
1195 public int Decode(byte[] bytes, int offset, int size)
1197 DecoderHelper.ValidateSize(size);
1202 FramingRecordType recordType;
1203 switch (currentState)
1205 case State.ReadingViaRecord:
1206 recordType = (FramingRecordType)bytes[offset];
1207 ValidateRecordType(FramingRecordType.Via, recordType);
1210 currentState = State.ReadingViaString;
1212 case State.ReadingViaString:
1213 bytesConsumed = viaDecoder.Decode(bytes, offset, size);
1214 if (viaDecoder.IsValueDecoded)
1215 currentState = State.ReadingContentTypeRecord;
1217 case State.ReadingContentTypeRecord:
1218 recordType = (FramingRecordType)bytes[offset];
1219 if (recordType == FramingRecordType.KnownEncoding)
1222 currentState = State.ReadingContentTypeByte;
1226 ValidateRecordType(FramingRecordType.ExtensibleEncoding, recordType);
1228 contentTypeDecoder.Reset();
1229 currentState = State.ReadingContentTypeString;
1232 case State.ReadingContentTypeByte:
1233 contentType = ContentTypeStringDecoder.GetString((FramingEncodingType)bytes[offset]);
1235 currentState = State.Start;
1237 case State.ReadingContentTypeString:
1238 bytesConsumed = contentTypeDecoder.Decode(bytes, offset, size);
1239 if (contentTypeDecoder.IsValueDecoded)
1241 currentState = State.Start;
1242 contentType = contentTypeDecoder.Value;
1246 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1247 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
1249 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1250 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
1253 StreamPosition += bytesConsumed;
1254 return bytesConsumed;
1256 catch (InvalidDataException e)
1258 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
1262 public void Reset(long streamPosition)
1264 this.StreamPosition = streamPosition;
1265 this.currentState = State.ReadingViaRecord;
1268 public State CurrentState
1270 get { return currentState; }
1273 protected override string CurrentStateAsString
1275 get { return currentState.ToString(); }
1282 if (currentState < State.ReadingContentTypeRecord)
1283 #pragma warning suppress 56503 // [....], not a publicly accessible API
1284 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1285 return viaDecoder.ValueAsUri;
1289 public string ContentType
1293 if (currentState < State.Start)
1294 #pragma warning suppress 56503 // [....], not a publicly accessible API
1295 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1304 ReadingContentTypeRecord,
1305 ReadingContentTypeString,
1306 ReadingContentTypeByte,
1311 // common set of states used on the client-side.
1312 enum ClientFramingDecoderState
1314 ReadingUpgradeRecord,
1322 ReadingEnvelopeRecord,
1323 ReadingEnvelopeSize,
1325 ReadingEnvelopeBytes,
1331 abstract class ClientFramingDecoder : FramingDecoder
1333 ClientFramingDecoderState currentState;
1335 protected ClientFramingDecoder(long streamPosition)
1336 : base(streamPosition)
1338 this.currentState = ClientFramingDecoderState.ReadingUpgradeRecord;
1341 public ClientFramingDecoderState CurrentState
1345 return this.currentState;
1350 this.currentState = value;
1354 protected override string CurrentStateAsString
1356 get { return currentState.ToString(); }
1359 public abstract string Fault
1364 public abstract int Decode(byte[] bytes, int offset, int size);
1368 // (UpgradeResponse, upgrade-bytes)*, (Ack | Fault),
1369 // ((EnvelopeStart, ReadingEnvelopeBytes*, EnvelopeEnd) | Fault)*,
1371 class ClientDuplexDecoder : ClientFramingDecoder
1373 IntDecoder sizeDecoder;
1374 FaultStringDecoder faultDecoder;
1375 int envelopeBytesNeeded;
1378 public ClientDuplexDecoder(long streamPosition)
1379 : base(streamPosition)
1381 sizeDecoder = new IntDecoder();
1384 public int EnvelopeSize
1388 if (CurrentState < ClientFramingDecoderState.EnvelopeStart)
1389 #pragma warning suppress 56503 // [....], not a publicly accessible API
1390 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1391 return envelopeSize;
1395 public override string Fault
1399 if (CurrentState < ClientFramingDecoderState.Fault)
1400 #pragma warning suppress 56503 // [....], not a publicly accessible API
1401 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1402 return faultDecoder.Value;
1406 public override int Decode(byte[] bytes, int offset, int size)
1408 DecoderHelper.ValidateSize(size);
1413 FramingRecordType recordType;
1414 switch (CurrentState)
1416 case ClientFramingDecoderState.ReadingUpgradeRecord:
1417 recordType = (FramingRecordType)bytes[offset];
1418 if (recordType == FramingRecordType.UpgradeResponse)
1421 base.CurrentState = ClientFramingDecoderState.UpgradeResponse;
1426 base.CurrentState = ClientFramingDecoderState.ReadingAckRecord;
1429 case ClientFramingDecoderState.UpgradeResponse:
1431 base.CurrentState = ClientFramingDecoderState.ReadingUpgradeRecord;
1433 case ClientFramingDecoderState.ReadingAckRecord:
1434 recordType = (FramingRecordType)bytes[offset];
1435 if (recordType == FramingRecordType.Fault)
1438 faultDecoder = new FaultStringDecoder();
1439 base.CurrentState = ClientFramingDecoderState.ReadingFaultString;
1442 ValidatePreambleAck(recordType);
1444 base.CurrentState = ClientFramingDecoderState.Start;
1446 case ClientFramingDecoderState.Start:
1448 base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeRecord;
1450 case ClientFramingDecoderState.ReadingEnvelopeRecord:
1451 recordType = (FramingRecordType)bytes[offset];
1452 if (recordType == FramingRecordType.End)
1455 base.CurrentState = ClientFramingDecoderState.End;
1458 else if (recordType == FramingRecordType.Fault)
1461 faultDecoder = new FaultStringDecoder();
1462 base.CurrentState = ClientFramingDecoderState.ReadingFaultString;
1465 ValidateRecordType(FramingRecordType.SizedEnvelope, recordType);
1467 base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeSize;
1468 sizeDecoder.Reset();
1470 case ClientFramingDecoderState.ReadingEnvelopeSize:
1471 bytesConsumed = sizeDecoder.Decode(bytes, offset, size);
1472 if (sizeDecoder.IsValueDecoded)
1474 base.CurrentState = ClientFramingDecoderState.EnvelopeStart;
1475 envelopeSize = sizeDecoder.Value;
1476 envelopeBytesNeeded = envelopeSize;
1479 case ClientFramingDecoderState.EnvelopeStart:
1481 base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeBytes;
1483 case ClientFramingDecoderState.ReadingEnvelopeBytes:
1484 bytesConsumed = size;
1485 if (bytesConsumed > envelopeBytesNeeded)
1486 bytesConsumed = envelopeBytesNeeded;
1487 envelopeBytesNeeded -= bytesConsumed;
1488 if (envelopeBytesNeeded == 0)
1489 base.CurrentState = ClientFramingDecoderState.EnvelopeEnd;
1491 case ClientFramingDecoderState.EnvelopeEnd:
1493 base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeRecord;
1495 case ClientFramingDecoderState.ReadingFaultString:
1496 bytesConsumed = faultDecoder.Decode(bytes, offset, size);
1497 if (faultDecoder.IsValueDecoded)
1499 base.CurrentState = ClientFramingDecoderState.Fault;
1502 case ClientFramingDecoderState.Fault:
1504 base.CurrentState = ClientFramingDecoderState.ReadingEndRecord;
1506 case ClientFramingDecoderState.ReadingEndRecord:
1507 ValidateRecordType(FramingRecordType.End, (FramingRecordType)bytes[offset]);
1509 base.CurrentState = ClientFramingDecoderState.End;
1511 case ClientFramingDecoderState.End:
1512 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1513 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
1515 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1516 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
1519 StreamPosition += bytesConsumed;
1520 return bytesConsumed;
1522 catch (InvalidDataException e)
1524 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));
1530 // (UpgradeResponse, upgrade-bytes)*, (Ack | Fault),
1532 class ClientSingletonDecoder : ClientFramingDecoder
1534 FaultStringDecoder faultDecoder;
1536 public ClientSingletonDecoder(long streamPosition)
1537 : base(streamPosition)
1541 public override string Fault
1545 if (CurrentState < ClientFramingDecoderState.Fault)
1546 #pragma warning suppress 56503 // [....], not a publicly accessible API
1547 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.FramingValueNotAvailable)));
1548 return faultDecoder.Value;
1552 public override int Decode(byte[] bytes, int offset, int size)
1554 DecoderHelper.ValidateSize(size);
1559 FramingRecordType recordType;
1560 switch (CurrentState)
1562 case ClientFramingDecoderState.ReadingUpgradeRecord:
1563 recordType = (FramingRecordType)bytes[offset];
1564 if (recordType == FramingRecordType.UpgradeResponse)
1567 base.CurrentState = ClientFramingDecoderState.UpgradeResponse;
1572 base.CurrentState = ClientFramingDecoderState.ReadingAckRecord;
1575 case ClientFramingDecoderState.UpgradeResponse:
1577 base.CurrentState = ClientFramingDecoderState.ReadingUpgradeRecord;
1579 case ClientFramingDecoderState.ReadingAckRecord:
1580 recordType = (FramingRecordType)bytes[offset];
1581 if (recordType == FramingRecordType.Fault)
1584 faultDecoder = new FaultStringDecoder();
1585 base.CurrentState = ClientFramingDecoderState.ReadingFaultString;
1588 ValidatePreambleAck(recordType);
1590 base.CurrentState = ClientFramingDecoderState.Start;
1593 case ClientFramingDecoderState.Start:
1595 base.CurrentState = ClientFramingDecoderState.ReadingEnvelopeRecord;
1598 case ClientFramingDecoderState.ReadingEnvelopeRecord:
1599 recordType = (FramingRecordType)bytes[offset];
1600 if (recordType == FramingRecordType.End)
1603 base.CurrentState = ClientFramingDecoderState.End;
1606 else if (recordType == FramingRecordType.Fault)
1609 base.CurrentState = ClientFramingDecoderState.ReadingFault;
1612 ValidateRecordType(FramingRecordType.UnsizedEnvelope, recordType);
1614 base.CurrentState = ClientFramingDecoderState.EnvelopeStart;
1617 case ClientFramingDecoderState.EnvelopeStart:
1618 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1619 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
1621 case ClientFramingDecoderState.ReadingFault:
1622 recordType = (FramingRecordType)bytes[offset];
1623 ValidateRecordType(FramingRecordType.Fault, recordType);
1625 faultDecoder = new FaultStringDecoder();
1626 base.CurrentState = ClientFramingDecoderState.ReadingFaultString;
1628 case ClientFramingDecoderState.ReadingFaultString:
1629 bytesConsumed = faultDecoder.Decode(bytes, offset, size);
1630 if (faultDecoder.IsValueDecoded)
1632 base.CurrentState = ClientFramingDecoderState.Fault;
1635 case ClientFramingDecoderState.Fault:
1636 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1637 CreateException(new InvalidDataException(SR.GetString(SR.FramingAtEnd))));
1639 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
1640 CreateException(new InvalidDataException(SR.GetString(SR.InvalidDecoderStateMachine))));
1643 StreamPosition += bytesConsumed;
1644 return bytesConsumed;
1646 catch (InvalidDataException e)
1648 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateException(e));