< Summary

Line coverage
22%
Covered lines: 11
Uncovered lines: 39
Coverable lines: 50
Total lines: 125
Line coverage: 22%
Branch coverage
31%
Covered branches: 10
Total branches: 32
Branch coverage: 31.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.cctor()100%110%
ValidateSubprotocol(...)0%440%
ValidateCloseStatus(...)55.55%181844%
ValidateArraySegment(...)0%10100%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.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.Buffers;
 5using System.Diagnostics;
 6using System.Text;
 7
 8namespace System.Net.WebSockets
 9{
 10    internal static partial class WebSocketValidate
 11    {
 12        /// <summary>
 13        /// The minimum value for window bits that the websocket per-message-deflate extension can support.<para />
 14        /// For the current implementation of deflate(), a windowBits value of 8 (a window size of 256 bytes) is not sup
 15        /// We cannot use silently 9 instead of 8, because the websocket produces raw deflate stream
 16        /// and thus it needs to know the window bits in advance.
 17        /// </summary>
 18        internal const int MinDeflateWindowBits = 9;
 19
 20        /// <summary>
 21        /// The maximum value for window bits that the websocket per-message-deflate extension can support.
 22        /// </summary>
 23        internal const int MaxDeflateWindowBits = 15;
 24
 25        internal const int MaxControlFramePayloadLength = 123;
 26#if TARGET_BROWSER
 27        private const int ValidCloseStatusCodesFrom = 3000;
 28        private const int ValidCloseStatusCodesTo = 4999;
 29#else
 30        private const int CloseStatusCodeAbort = 1006;
 31        private const int CloseStatusCodeFailedTLSHandshake = 1015;
 32        private const int InvalidCloseStatusCodesFrom = 0;
 33        private const int InvalidCloseStatusCodesTo = 999;
 34#endif
 35
 36        // [0x21, 0x7E] except separators "()<>@,;:\\\"/[]?={} ".
 037        private static readonly SearchValues<char> s_validSubprotocolChars =
 038            SearchValues.Create("!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~");
 39
 40        internal static void ValidateSubprotocol(string subProtocol)
 041        {
 042            ArgumentException.ThrowIfNullOrWhiteSpace(subProtocol);
 43
 044            int indexOfInvalidChar = subProtocol.AsSpan().IndexOfAnyExcept(s_validSubprotocolChars);
 045            if (indexOfInvalidChar >= 0)
 046            {
 047                char invalidChar = subProtocol[indexOfInvalidChar];
 48
 049                string invalidCharDescription = char.IsBetween(invalidChar, (char)0x21, (char)0x7E)
 050                    ? invalidChar.ToString() // ASCII separator
 051                    : $"[{(int)invalidChar}]";
 52
 053                throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCharInProtocolString, subProtocol, invali
 54            }
 055        }
 56
 57        internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, string? statusDescription)
 574458        {
 574459            if (closeStatus == WebSocketCloseStatus.Empty && !string.IsNullOrEmpty(statusDescription))
 060            {
 061                throw new ArgumentException(SR.Format(SR.net_WebSockets_ReasonNotNull,
 062                    statusDescription,
 063                    WebSocketCloseStatus.Empty),
 064                    nameof(statusDescription));
 65            }
 66
 574467            int closeStatusCode = (int)closeStatus;
 68#if TARGET_BROWSER
 69            // as defined in https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code
 70            if (closeStatus != WebSocketCloseStatus.NormalClosure && (closeStatusCode < ValidCloseStatusCodesFrom || clo
 71#else
 574472            if ((closeStatusCode >= InvalidCloseStatusCodesFrom &&
 574473                closeStatusCode <= InvalidCloseStatusCodesTo) ||
 574474                closeStatusCode == CloseStatusCodeAbort ||
 574475                closeStatusCode == CloseStatusCodeFailedTLSHandshake)
 76#endif
 077            {
 78                // CloseStatus 1006 means Aborted - this will never appear on the wire and is reflected by calling WebSo
 079                throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCloseStatusCode,
 080                    closeStatusCode),
 081                    nameof(closeStatus));
 82            }
 83
 574484            if (!string.IsNullOrEmpty(statusDescription) &&
 574485                Encoding.UTF8.GetMaxByteCount(statusDescription.Length) > MaxControlFramePayloadLength &&
 574486                Encoding.UTF8.GetByteCount(statusDescription) > MaxControlFramePayloadLength)
 087            {
 088                throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCloseStatusDescription,
 089                    statusDescription,
 090                    MaxControlFramePayloadLength),
 091                    nameof(statusDescription));
 92            }
 574493        }
 94
 95        internal static void ValidateArraySegment(ArraySegment<byte> arraySegment, string parameterName)
 096        {
 097            Debug.Assert(!string.IsNullOrEmpty(parameterName), "'parameterName' MUST NOT be NULL or string.Empty");
 98
 099            if (arraySegment.Array == null)
 0100            {
 0101                throw new ArgumentNullException(parameterName + "." + nameof(arraySegment.Array));
 102            }
 0103            if (arraySegment.Offset < 0 || arraySegment.Offset > arraySegment.Array.Length)
 0104            {
 0105                throw new ArgumentOutOfRangeException(parameterName + "." + nameof(arraySegment.Offset));
 106            }
 0107            if (arraySegment.Count < 0 || arraySegment.Count > (arraySegment.Array.Length - arraySegment.Offset))
 0108            {
 0109                throw new ArgumentOutOfRangeException(parameterName + "." + nameof(arraySegment.Count));
 110            }
 0111        }
 112
 113        internal static void ValidateBuffer(byte[] buffer, int offset, int count)
 114        {
 115            ArgumentNullException.ThrowIfNull(buffer);
 116
 117            ArgumentOutOfRangeException.ThrowIfNegative(offset);
 118            ArgumentOutOfRangeException.ThrowIfGreaterThan(offset, buffer.Length);
 119
 120            ArgumentOutOfRangeException.ThrowIfNegative(count);
 121            ArgumentOutOfRangeException.ThrowIfGreaterThan(count, buffer.Length - offset);
 122        }
 123    }
 124}
 125