< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 24
Coverable lines: 24
Total lines: 133
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 2
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%
CopyTo(...)100%110%
CopyFrom(...)100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Security/src/System/Net/StreamFramer.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.Globalization;
 5using System.IO;
 6using System.Net.Security;
 7using System.Threading;
 8using System.Threading.Tasks;
 9
 10namespace System.Net
 11{
 12    internal sealed class StreamFramer
 13    {
 14        private readonly FrameHeader _writeHeader = new FrameHeader();
 15        private readonly FrameHeader _curReadHeader = new FrameHeader();
 16
 17        private readonly byte[] _readHeaderBuffer = new byte[FrameHeader.Size];
 18        private readonly byte[] _writeHeaderBuffer = new byte[FrameHeader.Size];
 19        private bool _eof;
 20
 21        public FrameHeader ReadHeader => _curReadHeader;
 22        public FrameHeader WriteHeader => _writeHeader;
 23
 24        public async ValueTask<byte[]?> ReadMessageAsync<TAdapter>(Stream stream, CancellationToken cancellationToken)
 25            where TAdapter : IReadWriteAdapter
 26        {
 27            if (_eof)
 28            {
 29                return null;
 30            }
 31
 32            byte[] buffer = _readHeaderBuffer;
 33
 34            int bytesRead = await TAdapter.ReadAtLeastAsync(
 35                stream, buffer, buffer.Length, throwOnEndOfStream: false, cancellationToken).ConfigureAwait(false);
 36            if (bytesRead < buffer.Length)
 37            {
 38                if (bytesRead == 0)
 39                {
 40                    // m_Eof, return null
 41                    _eof = true;
 42                    return null;
 43                }
 44                throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed));
 45            }
 46
 47            _curReadHeader.CopyFrom(buffer, 0);
 48            if (_curReadHeader.PayloadSize > FrameHeader.MaxMessageSize)
 49            {
 50                throw new InvalidOperationException(SR.Format(SR.net_frame_size,
 51                                                               FrameHeader.MaxMessageSize,
 52                                                               _curReadHeader.PayloadSize.ToString(NumberFormatInfo.Inva
 53            }
 54
 55            buffer = new byte[_curReadHeader.PayloadSize];
 56
 57            if (buffer.Length > 0)
 58            {
 59                bytesRead = await TAdapter.ReadAtLeastAsync(
 60                    stream, buffer, buffer.Length, throwOnEndOfStream: false, cancellationToken).ConfigureAwait(false);
 61                if (bytesRead < buffer.Length)
 62                {
 63                    throw new IOException(SR.Format(SR.net_io_readfailure, SR.net_io_connectionclosed));
 64                }
 65            }
 66            return buffer;
 67        }
 68
 69        public async Task WriteMessageAsync<TAdapter>(Stream stream, byte[] message, CancellationToken cancellationToken
 70            where TAdapter : IReadWriteAdapter
 71        {
 72            _writeHeader.PayloadSize = message.Length;
 73            _writeHeader.CopyTo(_writeHeaderBuffer, 0);
 74
 75            await TAdapter.WriteAsync(stream, _writeHeaderBuffer, cancellationToken).ConfigureAwait(false);
 76            if (message.Length != 0)
 77            {
 78                await TAdapter.WriteAsync(stream, message, cancellationToken).ConfigureAwait(false);
 79            }
 80        }
 81    }
 82
 83    // Describes the header used in framing of the stream data.
 84    internal sealed class FrameHeader
 85    {
 86        public const int IgnoreValue = -1;
 87        public const int HandshakeDoneId = 20;
 88        public const int HandshakeErrId = 21;
 89        public const int HandshakeId = 22;
 90        public const int DefaultMajorV = 1;
 91        public const int DefaultMinorV = 0;
 92        public const int Size = 5;
 93        public const int MaxMessageSize = 0xFFFF;
 94
 095        private int _payloadSize = -1;
 96
 097        public int MessageId { get; set; } = HandshakeId;
 098        public int MajorV { get; private set; } = DefaultMajorV;
 099        public int MinorV { get; private set; } = DefaultMinorV;
 100
 101        public int PayloadSize
 102        {
 0103            get => _payloadSize;
 104            set
 0105            {
 0106                if (value > MaxMessageSize)
 0107                {
 0108                    throw new ArgumentException(SR.Format(SR.net_frame_max_size, MaxMessageSize, value), nameof(PayloadS
 109                }
 110
 0111                _payloadSize = value;
 0112            }
 113        }
 114
 115        public void CopyTo(byte[] dest, int start)
 0116        {
 0117            dest[start++] = (byte)MessageId;
 0118            dest[start++] = (byte)MajorV;
 0119            dest[start++] = (byte)MinorV;
 0120            dest[start++] = (byte)((_payloadSize >> 8) & 0xFF);
 0121            dest[start] = (byte)(_payloadSize & 0xFF);
 0122        }
 123
 124        public void CopyFrom(byte[] bytes, int start)
 0125        {
 0126            MessageId = bytes[start++];
 0127            MajorV = bytes[start++];
 0128            MinorV = bytes[start++];
 0129            _payloadSize = (bytes[start++] << 8) | bytes[start];
 0130        }
 131    }
 132}
 133