< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.Framing.FramingModeHandshakeMiddleware
Assembly: CoreWCF.NetFramingBase
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/FramingModeHandshakeMiddleware.cs
Line coverage
72%
Covered lines: 37
Uncovered lines: 14
Coverable lines: 51
Total lines: 114
Line coverage: 72.5%
Branch coverage
80%
Covered branches: 8
Total branches: 10
Branch coverage: 80%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
OnConnectedAsync()100%1150%
OnConnectedCoreAsync()80%101077.77%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/FramingModeHandshakeMiddleware.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.Threading;
 6using System.Threading.Tasks;
 7using CoreWCF.Configuration;
 8using Microsoft.Extensions.Hosting;
 9
 10namespace CoreWCF.Channels.Framing
 11{
 12    internal class FramingModeHandshakeMiddleware
 13    {
 14        private readonly HandshakeDelegate _next;
 15        private readonly IApplicationLifetime _appLifetime;
 16
 8317        public FramingModeHandshakeMiddleware(HandshakeDelegate next, IApplicationLifetime appLifetime)
 18        {
 8319            _next = next;
 8320            _appLifetime = appLifetime;
 8321        }
 22
 23        public async Task OnConnectedAsync(FramingConnection connection)
 24        {
 25            // If the remote client aborts or the connection, AspNetCore throws an exceptions which
 26            // bubbles all the way up to here and causes a critical level event to be logged. This is a normal thing
 27            // to happen so just swallowing the exception to suppress the critical log output.
 28            try
 29            {
 8230                await OnConnectedCoreAsync(connection);
 7631            }
 032            catch (Microsoft.AspNetCore.Connections.ConnectionAbortedException) { }
 033            catch (Microsoft.AspNetCore.Connections.ConnectionResetException) { }
 034            catch (CoreWCF.Security.SecurityNegotiationException) { } // TODO: Work out where this needs to be caught
 035            catch (System.IO.IOException) { } // TODO: Work out where this needs to be caught
 236            catch (CommunicationException) { } // TODO: Work out how this is logged in WCF and replicate
 7737        }
 38
 39        public async Task OnConnectedCoreAsync(FramingConnection connection)
 40        {
 8241            using (_appLifetime.ApplicationStopped.Register(() =>
 8242             {
 043                 connection.RawTransport.Input.Complete();
 044                 connection.RawTransport.Output.Complete();
 8245             }))
 46            {
 8247                IConnectionReuseHandler reuseHandler = null;
 48                do
 49                {
 11850                    System.IO.Pipelines.PipeReader inputPipe = connection.Input;
 11851                    var modeDecoder = new ServerModeDecoder(connection.Logger);
 52                    try
 53                    {
 11854                        if (!await modeDecoder.ReadModeAsync(inputPipe, connection.ChannelInitializationCancellationToke
 55                        {
 256                            break; // Input pipe closed
 57                        }
 11558                    }
 059                    catch (CommunicationException e)
 60                    {
 61                        // see if we need to send back a framing fault
 062                        if (FramingEncodingString.TryGetFaultString(e, out string framingFault))
 63                        {
 064                            await connection.SendFaultAsync(
 065                                framingFault,
 066                                ConnectionOrientedTransportDefaults.MaxViaSize + ConnectionOrientedTransportDefaults.Max
 067                                connection.ChannelInitializationCancellationToken);
 68                        }
 69
 070                        return; // Completing the returned Task causes the connection to be closed if needed and cleans 
 71                    }
 172                    catch (OperationCanceledException oce)
 73                    {
 74                        // Need to Abort (RST) the connection as aspnetcore on .NET Framework doesn't correctly close th
 75                        // In the case of connection establishment timeout, this is a change in behavior as WCF will clo
 176                        connection.Abort(oce);
 177                        throw;
 78                    }
 79
 11580                    connection.FramingMode = modeDecoder.Mode;
 11581                    await _next(connection);
 82
 83                    // Unwrap the connection.
 84                    // TODO: Investigate calling Dispose on the wrapping stream to improve cleanup. nb: .NET Framework d
 11485                    connection.Transport = connection.RawTransport;
 86
 87                    // connection.ServiceDispatcher is null until later middleware layers are executed.
 11488                    if (connection.ServiceDispatcher == null)
 89                    {
 190                        await connection.SendFaultAsync(
 191                            FramingEncodingString.EndpointNotFoundFault,
 192                            ConnectionOrientedTransportDefaults.MaxViaSize + ConnectionOrientedTransportDefaults.MaxCont
 193                            connection.ChannelInitializationCancellationToken);
 094                        return;
 95                    }
 96
 11397                    if (reuseHandler == null)
 98                    {
 7799                        var listenOptions = connection.ConnectionFeatures.Get<NetFramingListenOptions>();
 77100                        reuseHandler = listenOptions.ConnectionReuseHandler;
 101                    }
 220102                } while (await reuseHandler.ReuseConnectionAsync(connection, _appLifetime.ApplicationStopping));
 103
 104                // On .NET Framework, with the way that AspNetCore closes a connection, it sometimes doesn't send the
 105                // final bytes if those bytes haven't been sent yet. Delaying completeing the connection to compensate.
 76106                await Task.Delay(5);
 76107            }
 108
 109            // AspNetCore 2.1 doesn't close the connection. 2.2+ does so these lines can eventually be removed.
 76110            connection.RawTransport.Input.Complete();
 76111            connection.RawTransport.Output.Complete();
 76112        }
 113    }
 114}