< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.Framing.StreamingOutputConnectionStream
Assembly: CoreWCF.NetFramingBase
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/StreamedFramingRequestContext.cs
Line coverage
54%
Covered lines: 20
Uncovered lines: 17
Coverable lines: 37
Total lines: 258
Line coverage: 54%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
WriteChunkSizeAsync()100%22100%
BeginWrite(...)100%110%
EndWrite(...)100%110%
WriteByte(...)100%110%
Write(...)100%11100%
WriteAsync()100%11100%
Flush()100%11100%
Read(...)100%110%
Seek(...)100%110%
SetLength(...)100%110%

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)
 21            : base(requestMessage, connection.ServiceDispatcher.Binding.CloseTimeout, connection.ServiceDispatcher.Bindi
 22        {
 23            _connection = connection;
 24            _requestMessage = requestMessage;
 25            _inputStream = inputStream;
 26            _tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
 27        }
 28
 29        protected override void OnAbort()
 30        {
 31            _tcs.TrySetResult(null);
 32            _connection.Abort();
 33        }
 34
 35        protected override async Task OnCloseAsync(CancellationToken token)
 36        {
 37            lock (ThisLock)
 38            {
 39                if (_isClosed)
 40                {
 41                    return;
 42                }
 43
 44                _isClosed = true;
 45            }
 46
 47            bool success = false;
 48            try
 49            {
 50                // first drain our stream if necessary
 51                if (_inputStream != null)
 52                {
 53                    byte[] dummy = Fx.AllocateByteArray(_connection.ConnectionBufferSize);
 54                    while (!_connection.EOF)
 55                    {
 56                        int bytesRead = await _inputStream.ReadAsync(dummy, 0, dummy.Length, token);
 57                        if (bytesRead == 0)
 58                        {
 59                            _connection.EOF = true;
 60                        }
 61                    }
 62                }
 63
 64                // send back EOF and then recycle the connection
 65                try
 66                {
 67                    await _connection.Output.WriteAsync(SingletonEncoder.EndBytes, token);
 68                    await _connection.Output.FlushAsync(token);
 69                }
 70                finally
 71                {
 72                    if (_connection.RawStream != null)
 73                    {
 74                        _connection.Logger.UnwrappingRawStream();
 75                        _connection.RawStream = null;
 76                        await _connection.Output.CompleteAsync();
 77                        await _connection.Input.CompleteAsync();
 78                    }
 79                }
 80
 81                // TODO: ChannelBinding
 82                //ChannelBindingUtility.Dispose(ref this.channelBindingToken);
 83
 84                success = true;
 85            }
 86            finally
 87            {
 88                _tcs.TrySetResult(null);
 89
 90                if (!success)
 91                {
 92                    Abort();
 93                }
 94            }
 95        }
 96
 97        protected override async Task OnReplyAsync(Message message, CancellationToken token)
 98        {
 99            if (_connection.MessageEncoderFactory.Encoder is ICompressedMessageEncoder compressedMessageEncoder && compr
 100            {
 101                compressedMessageEncoder.AddCompressedMessageProperties(message, _connection.FramingDecoder.ContentType)
 102            }
 103
 104            await StreamingConnectionHelper.WriteMessageAsync(message, _connection, false, _connection.ServiceDispatcher
 105        }
 106
 107        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
 0175        public override bool CanRead => false;
 176
 0177        public override bool CanSeek => false;
 178
 8179        public override bool CanWrite => true;
 180
 0181        public override long Length => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedExcepti
 182
 183        public override long Position
 184        {
 0185            get => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupport
 0186            set => throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupport
 187        }
 188
 43189        public StreamingOutputConnectionStream(FramingConnection connection, IDefaultCommunicationTimeouts timeouts)
 190        {
 43191            _encodedSize = new byte[IntEncoder.MaxEncodedSize];
 43192            _connection = connection;
 43193            _timeouts = timeouts;
 43194        }
 195
 196        private async Task WriteChunkSizeAsync(int size, CancellationToken token)
 197        {
 362198            if (size > 0)
 199            {
 362200                int bytesEncoded = IntEncoder.Encode(size, _encodedSize, 0);
 362201                await _connection.Output.WriteAsync(new ArraySegment<byte>(_encodedSize, 0, bytesEncoded), token);
 202            }
 362203        }
 204
 205        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object sta
 206        {
 0207            return WriteAsync(buffer, offset, count, CancellationToken.None).ToApm(callback, state);
 208        }
 209
 210        public override void EndWrite(IAsyncResult asyncResult)
 211        {
 0212            asyncResult.ToApmEnd();
 0213        }
 214
 215        public override void WriteByte(byte value)
 216        {
 0217            var timeoutHelper = new TimeoutHelper(_timeouts.SendTimeout);
 0218            CancellationToken ct = timeoutHelper.GetCancellationToken();
 0219            WriteChunkSizeAsync(1, ct).GetAwaiter().GetResult();
 0220            _connection.Output.WriteAsync(new byte[] { value }, ct).GetAwaiter().GetResult();
 0221            _connection.Output.FlushAsync();
 0222        }
 223
 224        public override void Write(byte[] buffer, int offset, int count)
 225        {
 362226            WriteAsync(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult();
 362227        }
 228
 229        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
 230        {
 362231            var timeoutHelper = new TimeoutHelper(_timeouts.SendTimeout);
 362232            CancellationToken ct = timeoutHelper.GetCancellationToken();
 362233            await WriteChunkSizeAsync(count, ct);
 362234            await _connection.Output.WriteAsync(new ArraySegment<byte>(buffer, offset, count), ct);
 362235            await _connection.Output.FlushAsync();
 362236        }
 237
 238        public override void Flush()
 239        {
 86240            _connection.Output.FlushAsync().GetAwaiter().GetResult();
 86241        }
 242
 243        public override int Read(byte[] buffer, int offset, int count)
 244        {
 0245            throw new NotImplementedException();
 246        }
 247
 248        public override long Seek(long offset, SeekOrigin origin)
 249        {
 0250            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupported));
 251        }
 252
 253        public override void SetLength(long value)
 254        {
 0255            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.SeekNotSupported));
 256        }
 257    }
 258}