< Summary

Line coverage
6%
Covered lines: 6
Uncovered lines: 93
Coverable lines: 99
Total lines: 216
Line coverage: 6%
Branch coverage
4%
Covered branches: 2
Total branches: 44
Branch coverage: 4.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
ReceiveAsync(...)0%220%
SendAsync(...)0%220%
SendAsync(...)100%110%
SendWithArrayPoolAsync(...)100%110%
ThrowOnInvalidState(...)0%880%
IsStateTerminal(...)0%220%
CreateClientBuffer(...)100%110%
CreateServerBuffer(...)100%110%
CreateFromStream(...)0%12120%
CreateFromStream(...)33.33%6685.71%
IsApplicationTargeting45()100%110%
RegisterPrefixes()100%110%
CreateClientWebSocket(...)0%12120%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/WebSocket.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.ComponentModel;
 6using System.IO;
 7using System.Runtime.InteropServices;
 8using System.Threading;
 9using System.Threading.Tasks;
 10
 11namespace System.Net.WebSockets
 12{
 13    public abstract class WebSocket : IDisposable
 14    {
 15        public abstract WebSocketCloseStatus? CloseStatus { get; }
 16        public abstract string? CloseStatusDescription { get; }
 17        public abstract string? SubProtocol { get; }
 18        public abstract WebSocketState State { get; }
 19
 20        public abstract void Abort();
 21        public abstract Task CloseAsync(WebSocketCloseStatus closeStatus,
 22            string? statusDescription,
 23            CancellationToken cancellationToken);
 24        public abstract Task CloseOutputAsync(WebSocketCloseStatus closeStatus,
 25            string? statusDescription,
 26            CancellationToken cancellationToken);
 27        public abstract void Dispose();
 28        public abstract Task<WebSocketReceiveResult> ReceiveAsync(ArraySegment<byte> buffer,
 29            CancellationToken cancellationToken);
 30        public abstract Task SendAsync(ArraySegment<byte> buffer,
 31            WebSocketMessageType messageType,
 32            bool endOfMessage,
 33            CancellationToken cancellationToken);
 34
 35        public virtual async ValueTask<ValueWebSocketReceiveResult> ReceiveAsync(Memory<byte> buffer, CancellationToken 
 036        {
 037            if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> arraySegment))
 038            {
 039                WebSocketReceiveResult r = await ReceiveAsync(arraySegment, cancellationToken).ConfigureAwait(false);
 040                return new ValueWebSocketReceiveResult(r.Count, r.MessageType, r.EndOfMessage);
 41            }
 42
 043            byte[] array = ArrayPool<byte>.Shared.Rent(buffer.Length);
 44            try
 045            {
 046                WebSocketReceiveResult r = await ReceiveAsync(new ArraySegment<byte>(array, 0, buffer.Length), cancellat
 047                new Span<byte>(array, 0, r.Count).CopyTo(buffer.Span);
 048                return new ValueWebSocketReceiveResult(r.Count, r.MessageType, r.EndOfMessage);
 49            }
 50            finally
 051            {
 052                ArrayPool<byte>.Shared.Return(array);
 053            }
 054        }
 55
 56        public virtual ValueTask SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, bool endOfMess
 057            MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> arraySegment) ?
 058                new ValueTask(SendAsync(arraySegment, messageType, endOfMessage, cancellationToken)) :
 059                SendWithArrayPoolAsync(buffer, messageType, endOfMessage, cancellationToken);
 60
 61        public virtual ValueTask SendAsync(ReadOnlyMemory<byte> buffer, WebSocketMessageType messageType, WebSocketMessa
 062        {
 063            return SendAsync(buffer, messageType, (messageFlags & WebSocketMessageFlags.EndOfMessage) != 0, cancellation
 064        }
 65
 66        private async ValueTask SendWithArrayPoolAsync(
 67            ReadOnlyMemory<byte> buffer,
 68            WebSocketMessageType messageType,
 69            bool endOfMessage,
 70            CancellationToken cancellationToken)
 071        {
 072            byte[] array = ArrayPool<byte>.Shared.Rent(buffer.Length);
 73            try
 074            {
 075                buffer.Span.CopyTo(array);
 076                await SendAsync(new ArraySegment<byte>(array, 0, buffer.Length), messageType, endOfMessage, cancellation
 077            }
 78            finally
 079            {
 080                ArrayPool<byte>.Shared.Return(array);
 081            }
 082        }
 83
 84        public static TimeSpan DefaultKeepAliveInterval
 85        {
 86            // In the .NET Framework, this pulls the value from a P/Invoke.  Here we just hardcode it to a reasonable de
 087            get { return WebSocketDefaults.DefaultClientKeepAliveInterval; }
 88        }
 89
 90        protected static void ThrowOnInvalidState(WebSocketState state, params WebSocketState[] validStates)
 091        {
 092            string validStatesText = string.Empty;
 93
 094            if (validStates != null && validStates.Length > 0)
 095            {
 096                foreach (WebSocketState currentState in validStates)
 097                {
 098                    if (state == currentState)
 099                    {
 0100                        return;
 101                    }
 0102                }
 103
 0104                validStatesText = string.Join(", ", validStates);
 0105            }
 106
 0107            throw new WebSocketException(WebSocketError.InvalidState, SR.Format(SR.net_WebSockets_InvalidState, state, v
 0108        }
 109
 110        protected static bool IsStateTerminal(WebSocketState state) =>
 0111            state == WebSocketState.Closed || state == WebSocketState.Aborted;
 112
 113        public static ArraySegment<byte> CreateClientBuffer(int receiveBufferSize, int sendBufferSize)
 0114        {
 0115            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(receiveBufferSize);
 0116            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(sendBufferSize);
 0117            return new ArraySegment<byte>(new byte[Math.Max(receiveBufferSize, sendBufferSize)]);
 0118        }
 119
 120        public static ArraySegment<byte> CreateServerBuffer(int receiveBufferSize)
 0121        {
 0122            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(receiveBufferSize);
 0123            return new ArraySegment<byte>(new byte[receiveBufferSize]);
 0124        }
 125
 126        /// <summary>Creates a <see cref="WebSocket"/> that operates on a <see cref="Stream"/> representing a web socket
 127        /// <param name="stream">The <see cref="Stream"/> for the connection.</param>
 128        /// <param name="isServer"><code>true</code> if this is the server-side of the connection; <code>false</code> if
 129        /// <param name="subProtocol">The agreed upon sub-protocol that was used when creating the connection.</param>
 130        /// <param name="keepAliveInterval">The keep-alive interval to use, or <see cref="Timeout.InfiniteTimeSpan"/> to
 131        /// <returns>The created <see cref="WebSocket"/>.</returns>
 132        public static WebSocket CreateFromStream(Stream stream, bool isServer, string? subProtocol, TimeSpan keepAliveIn
 0133        {
 0134            ArgumentNullException.ThrowIfNull(stream);
 135
 0136            if (!stream.CanRead || !stream.CanWrite)
 0137            {
 0138                throw new ArgumentException(!stream.CanRead ? SR.NotReadableStream : SR.NotWriteableStream, nameof(strea
 139            }
 140
 0141            if (subProtocol != null)
 0142            {
 0143                WebSocketValidate.ValidateSubprotocol(subProtocol);
 0144            }
 145
 0146            if (keepAliveInterval != Timeout.InfiniteTimeSpan && keepAliveInterval < TimeSpan.Zero)
 0147            {
 0148                throw new ArgumentOutOfRangeException(nameof(keepAliveInterval), keepAliveInterval,
 0149                    SR.Format(SR.net_WebSockets_ArgumentOutOfRange_TooSmall,
 0150                    0));
 151            }
 152
 0153            return new ManagedWebSocket(stream, isServer, subProtocol, keepAliveInterval, WebSocketDefaults.DefaultKeepA
 0154        }
 155
 156        /// <summary>Creates a <see cref="WebSocket"/> that operates on a <see cref="Stream"/> representing a web socket
 157        /// <param name="stream">The <see cref="Stream"/> for the connection.</param>
 158        /// <param name="options">The options with which the websocket must be created.</param>
 159        public static WebSocket CreateFromStream(Stream stream, WebSocketCreationOptions options)
 8642160        {
 8642161            ArgumentNullException.ThrowIfNull(stream);
 8642162            ArgumentNullException.ThrowIfNull(options);
 163
 8642164            if (!stream.CanRead || !stream.CanWrite)
 0165                throw new ArgumentException(!stream.CanRead ? SR.NotReadableStream : SR.NotWriteableStream, nameof(strea
 166
 8642167            return new ManagedWebSocket(stream, options);
 8642168        }
 169
 170        [EditorBrowsable(EditorBrowsableState.Never)]
 171        [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your
 0172        public static bool IsApplicationTargeting45() => true;
 173
 174        [EditorBrowsable(EditorBrowsableState.Never)]
 175        [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your
 176        public static void RegisterPrefixes()
 0177        {
 178            // The current WebRequest implementation in the libraries does not support upgrading
 179            // web socket connections.  For now, we throw.
 0180            throw new PlatformNotSupportedException();
 181        }
 182
 183        [EditorBrowsable(EditorBrowsableState.Never)]
 184        public static WebSocket CreateClientWebSocket(Stream innerStream,
 185            string? subProtocol, int receiveBufferSize, int sendBufferSize,
 186            TimeSpan keepAliveInterval, bool useZeroMaskingKey, ArraySegment<byte> internalBuffer)
 0187        {
 0188            ArgumentNullException.ThrowIfNull(innerStream);
 189
 0190            if (!innerStream.CanRead || !innerStream.CanWrite)
 0191            {
 0192                throw new ArgumentException(!innerStream.CanRead ? SR.NotReadableStream : SR.NotWriteableStream, nameof(
 193            }
 194
 0195            if (subProtocol != null)
 0196            {
 0197                WebSocketValidate.ValidateSubprotocol(subProtocol);
 0198            }
 199
 0200            if (keepAliveInterval != Timeout.InfiniteTimeSpan && keepAliveInterval < TimeSpan.Zero)
 0201            {
 0202                throw new ArgumentOutOfRangeException(nameof(keepAliveInterval), keepAliveInterval,
 0203                    SR.Format(SR.net_WebSockets_ArgumentOutOfRange_TooSmall,
 0204                    0));
 205            }
 206
 0207            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(receiveBufferSize);
 0208            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(sendBufferSize);
 209
 210            // Ignore useZeroMaskingKey. ManagedWebSocket doesn't currently support that debugging option.
 211            // Ignore internalBuffer. ManagedWebSocket uses its own small buffer for headers/control messages.
 0212            return new ManagedWebSocket(innerStream, false, subProtocol, keepAliveInterval, WebSocketDefaults.DefaultKee
 0213        }
 214    }
 215}
 216