< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.Framing.StreamedFramingRequestContext
Assembly: CoreWCF.NetFramingBase
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/StreamedFramingRequestContext.cs
Line coverage
80%
Covered lines: 32
Uncovered lines: 8
Coverable lines: 40
Total lines: 258
Line coverage: 80%
Branch coverage
75%
Covered branches: 12
Total branches: 16
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
OnAbort()100%110%
OnCloseAsync()66.66%121280.76%
OnReplyAsync()100%44100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/StreamedFramingRequestContext.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.IO;
 6using System.Threading;
 7using System.Threading.Tasks;
 8using CoreWCF.Runtime;
 9
 10namespace CoreWCF.Channels.Framing
 11{
 12    internal class StreamedFramingRequestContext : RequestContextBase
 13    {
 14        private readonly FramingConnection _connection;
 15        private readonly Message _requestMessage;
 16        private readonly Stream _inputStream;
 17        private bool _isClosed;
 18        private readonly TaskCompletionSource<object> _tcs;
 19
 20        public StreamedFramingRequestContext(FramingConnection connection, Message requestMessage, Stream inputStream)
 5021            : base(requestMessage, connection.ServiceDispatcher.Binding.CloseTimeout, connection.ServiceDispatcher.Bindi
 22        {
 5023            _connection = connection;
 5024            _requestMessage = requestMessage;
 5025            _inputStream = inputStream;
 5026            _tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
 5027        }
 28
 29        protected override void OnAbort()
 30        {
 031            _tcs.TrySetResult(null);
 032            _connection.Abort();
 033        }
 34
 35        protected override async Task OnCloseAsync(CancellationToken token)
 36        {
 5037            lock (ThisLock)
 38            {
 5039                if (_isClosed)
 40                {
 041                    return;
 42                }
 43
 5044                _isClosed = true;
 5045            }
 46
 5047            bool success = false;
 48            try
 49            {
 50                // first drain our stream if necessary
 5051                if (_inputStream != null)
 52                {
 5053                    byte[] dummy = Fx.AllocateByteArray(_connection.ConnectionBufferSize);
 5054                    while (!_connection.EOF)
 55                    {
 056                        int bytesRead = await _inputStream.ReadAsync(dummy, 0, dummy.Length, token);
 057                        if (bytesRead == 0)
 58                        {
 059                            _connection.EOF = true;
 60                        }
 61                    }
 5062                }
 63
 64                // send back EOF and then recycle the connection
 65                try
 66                {
 5067                    await _connection.Output.WriteAsync(SingletonEncoder.EndBytes, token);
 5068                    await _connection.Output.FlushAsync(token);
 69                }
 70                finally
 71                {
 5072                    if (_connection.RawStream != null)
 73                    {
 174                        _connection.Logger.UnwrappingRawStream();
 175                        _connection.RawStream = null;
 176                        await _connection.Output.CompleteAsync();
 177                        await _connection.Input.CompleteAsync();
 78                    }
 79                }
 80
 81                // TODO: ChannelBinding
 82                //ChannelBindingUtility.Dispose(ref this.channelBindingToken);
 83
 5084                success = true;
 5085            }
 86            finally
 87            {
 5088                _tcs.TrySetResult(null);
 89
 5090                if (!success)
 91                {
 092                    Abort();
 93                }
 94            }
 5095        }
 96
 97        protected override async Task OnReplyAsync(Message message, CancellationToken token)
 98        {
 5099            if (_connection.MessageEncoderFactory.Encoder is ICompressedMessageEncoder compressedMessageEncoder && compr
 100            {
 12101                compressedMessageEncoder.AddCompressedMessageProperties(message, _connection.FramingDecoder.ContentType)
 102            }
 103
 50104            await StreamingConnectionHelper.WriteMessageAsync(message, _connection, false, _connection.ServiceDispatcher
 50105        }
 106
 50107        public Task ReplySent => _tcs.Task;
 108    }
 109
 110    internal static class StreamingConnectionHelper
 111    {
 112        public static async Task WriteMessageAsync(Message message, FramingConnection connection, bool isRequest,
 113            IDefaultCommunicationTimeouts settings, CancellationToken token)
 114        {
 115            byte[] endBytes = null;
 116            if (message != null)
 117            {
 118                MessageEncoder messageEncoder = connection.MessageEncoderFactory.Encoder;
 119                byte[] envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;
 120
 121                bool writeStreamed;
 122                if (isRequest)
 123                {
 124                    endBytes = SingletonEncoder.EnvelopeEndFramingEndBytes;
 125                    writeStreamed = TransferModeHelper.IsRequestStreamed(connection.TransferMode);
 126                }
 127                else
 128                {
 129                    endBytes = SingletonEncoder.EnvelopeEndBytes;
 130                    writeStreamed = TransferModeHelper.IsResponseStreamed(connection.TransferMode);
 131                }
 132
 133                if (writeStreamed)
 134                {
 135                    await connection.Output.WriteAsync(envelopeStartBytes, token);
 136                    Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
 137                    // TODO: Determine if timeout stream is needed as StreamingOutputConnectionStream implements some ti
 138                    //Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
 139                    await messageEncoder.WriteMessageAsync(message, connectionStream);
 140                    await connection.Output.FlushAsync();
 141                }
 142                else
 143                {
 144                    ArraySegment<byte> messageData = messageEncoder.WriteMessage(message,
 145                        int.MaxValue, connection.BufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
 146                    messageData = SingletonEncoder.EncodeMessageFrame(messageData);
 147                    Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.L
 148                        envelopeStartBytes.Length);
 149                    await connection.Output.WriteAsync(new ArraySegment<byte>(messageData.Array, messageData.Offset - en
 150                        messageData.Count + envelopeStartBytes.Length), token);
 151                    await connection.Output.FlushAsync();
 152                    connection.BufferManager.ReturnBuffer(messageData.Array);
 153                }
 154            }
 155            else if (isRequest) // context handles response end bytes
 156            {
 157                endBytes = SingletonEncoder.EndBytes;
 158            }
 159
 160            if (endBytes != null)
 161            {
 162                await connection.Output.WriteAsync(endBytes, token);
 163                await connection.Output.FlushAsync();
 164            }
 165        }
 166    }
 167
 168    // overrides Stream to add a Framing int at the beginning of each record
 169    internal class StreamingOutputConnectionStream : Stream
 170    {
 171        private readonly byte[] _encodedSize;
 172        private readonly FramingConnection _connection;
 173        private readonly IDefaultCommunicationTimeouts _timeouts;
 174
 175        public override bool CanRead => false;
 176
 177        public override bool CanSeek => false;
 178
 179        public override bool CanWrite => true;
 180
 181        public override long Length => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedExcepti
 182
 183        public override long Position
 184        {
 185            get => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupport
 186            set => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupport
 187        }
 188
 189        public StreamingOutputConnectionStream(FramingConnection connection, IDefaultCommunicationTimeouts timeouts)
 190        {
 191            _encodedSize = new byte[IntEncoder.MaxEncodedSize];
 192            _connection = connection;
 193            _timeouts = timeouts;
 194        }
 195
 196        private async Task WriteChunkSizeAsync(int size, CancellationToken token)
 197        {
 198            if (size > 0)
 199            {
 200                int bytesEncoded = IntEncoder.Encode(size, _encodedSize, 0);
 201                await _connection.Output.WriteAsync(new ArraySegment<byte>(_encodedSize, 0, bytesEncoded), token);
 202            }
 203        }
 204
 205        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object sta
 206        {
 207            return WriteAsync(buffer, offset, count, CancellationToken.None).ToApm(callback, state);
 208        }
 209
 210        public override void EndWrite(IAsyncResult asyncResult)
 211        {
 212            asyncResult.ToApmEnd();
 213        }
 214
 215        public override void WriteByte(byte value)
 216        {
 217            var timeoutHelper = new TimeoutHelper(_timeouts.SendTimeout);
 218            CancellationToken ct = timeoutHelper.GetCancellationToken();
 219            WriteChunkSizeAsync(1, ct).GetAwaiter().GetResult();
 220            _connection.Output.WriteAsync(new byte[] { value }, ct).GetAwaiter().GetResult();
 221            _connection.Output.FlushAsync();
 222        }
 223
 224        public override void Write(byte[] buffer, int offset, int count)
 225        {
 226            WriteAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult();
 227        }
 228
 229        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 230        {
 231            var timeoutHelper = new TimeoutHelper(_timeouts.SendTimeout);
 232            CancellationToken ct = timeoutHelper.GetCancellationToken();
 233            await WriteChunkSizeAsync(count, ct);
 234            await _connection.Output.WriteAsync(new ArraySegment<byte>(buffer, offset, count), ct);
 235            await _connection.Output.FlushAsync();
 236        }
 237
 238        public override void Flush()
 239        {
 240            _connection.Output.FlushAsync().GetAwaiter().GetResult();
 241        }
 242
 243        public override int Read(byte[] buffer, int offset, int count)
 244        {
 245            throw new NotImplementedException();
 246        }
 247
 248        public override long Seek(long offset, SeekOrigin origin)
 249        {
 250            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupported));
 251        }
 252
 253        public override void SetLength(long value)
 254        {
 255            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupported));
 256        }
 257    }
 258}