< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Channels.Framing.NetMessageFramingConnectionHandler
Assembly: CoreWCF.NetFramingBase
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/NetMessageFramingConnectionHandler.cs
Line coverage
98%
Covered lines: 112
Uncovered lines: 2
Coverable lines: 114
Total lines: 229
Line coverage: 98.2%
Branch coverage
91%
Covered branches: 44
Total branches: 48
Branch coverage: 91.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%22100%
OnServiceBuilderOpened(...)100%11100%
BuildHandshake(...)100%11100%
BuildAddressTable(...)93.75%1616100%
BuildHandshakeDelegateForDispatcher(...)88.88%181897.67%
TryApplyIdentityToChannelDispatcher(...)100%66100%
PerformServiceHandshake()100%22100%
GetServiceHandshakeDelegate(...)75%4483.33%
OnConnectedAsync(...)100%11100%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.NetFramingBase/src/CoreWCF/Channels/Framing/NetMessageFramingConnectionHandler.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.Collections.Generic;
 6using System.Linq;
 7using System.Threading.Tasks;
 8using CoreWCF.Configuration;
 9using CoreWCF.Dispatcher;
 10using CoreWCF.Security;
 11using Microsoft.AspNetCore.Connections;
 12using Microsoft.AspNetCore.Server.Kestrel.Core;
 13using Microsoft.Extensions.DependencyInjection;
 14using Microsoft.Extensions.Logging;
 15
 16namespace CoreWCF.Channels.Framing
 17{
 18    public class NetMessageFramingConnectionHandler : ConnectionHandler
 19    {
 20        private readonly IDispatcherBuilder _dispatcherBuilder;
 21        private readonly HandshakeDelegate _handshake;
 22        private readonly ILogger _framingLogger;
 23        private readonly IServiceProvider _services;
 24
 25        [Obsolete("Added by mistake, does nothing", true)]
 8326        public List<ListenOptions> ListenOptions { get; } = new List<ListenOptions>();
 27
 8328        public NetMessageFramingConnectionHandler(IServiceBuilder serviceBuilder, IDispatcherBuilder dispatcherBuilder, 
 29        {
 8330            _dispatcherBuilder = dispatcherBuilder;
 8331            _handshake = BuildHandshake(handshakeBuilder);
 8332            _framingLogger = framingLogger;
 8333            _services = handshakeBuilder.HandshakeServices;
 8334            if (serviceBuilder.State == CommunicationState.Created)
 35            {
 8336                serviceBuilder.Opened += OnServiceBuilderOpened;
 37            }
 8338        }
 39
 40        private void OnServiceBuilderOpened(object sender, EventArgs e)
 41        {
 42            // Trigger building all of the services to improve first request time and to catch any service config issues
 8343            _services.GetRequiredService<UriPrefixTable<HandshakeDelegate>>();
 8344        }
 45
 46        private HandshakeDelegate BuildHandshake(IFramingConnectionHandshakeBuilder handshakeBuilder)
 47        {
 8348            handshakeBuilder.UseMiddleware<FramingModeHandshakeMiddleware>();
 19849            handshakeBuilder.Map(connection => connection.FramingMode == FramingMode.Duplex,
 8350                configuration =>
 8351                {
 8352                    configuration.UseMiddleware<DuplexFramingMiddleware>();
 23153                    configuration.Use(next => connection => PerformServiceHandshake(configuration, connection, next));
 8354                    configuration.UseMiddleware<ServerFramingDuplexSessionMiddleware>();
 8355                    configuration.UseMiddleware<ServerSessionConnectionReaderMiddleware>();
 16656                });
 13357            handshakeBuilder.Map(connection => connection.FramingMode == FramingMode.Singleton,
 8358                configuration =>
 8359                {
 8360                    configuration.UseMiddleware<SingletonFramingMiddleware>();
 21661                    configuration.Use(next => connection => PerformServiceHandshake(configuration, connection, next));
 8362                    configuration.UseMiddleware<ServerFramingSingletonMiddleware>();
 8363                    configuration.UseMiddleware<ServerSingletonConnectionReaderMiddleware>();
 16664                });
 8365            return handshakeBuilder.Build();
 66        }
 67
 68        internal static UriPrefixTable<HandshakeDelegate> BuildAddressTable(IServiceProvider services)
 69        {
 8370            ILogger<NetMessageFramingConnectionHandler> logger = services.GetRequiredService<ILogger<NetMessageFramingCo
 8371            IServiceBuilder serviceBuilder = services.GetRequiredService<IServiceBuilder>();
 8372            IDispatcherBuilder dispatcherBuilder = services.GetRequiredService<IDispatcherBuilder>();
 8373            var addressTable = new UriPrefixTable<HandshakeDelegate>();
 33674            foreach (Type serviceType in serviceBuilder.Services)
 75            {
 8576                List<IServiceDispatcher> dispatchers = dispatcherBuilder.BuildDispatchers(serviceType);
 38677                foreach (IServiceDispatcher dispatcher in dispatchers)
 78                {
 10879                    if (dispatcher.BaseAddress == null)
 80                    {
 81                        // TODO: Should we throw? Ignore?
 82                        continue;
 83                    }
 84
 85                    // TODO: Limit to specifically TcpTransportBindingElement if net.tcp etc
 10886                    BindingElementCollection be = dispatcher.Binding.CreateBindingElements();
 10887                    ConnectionOrientedTransportBindingElement cotbe = be.Find<ConnectionOrientedTransportBindingElement>
 10888                    if (cotbe == null)
 89                    {
 90                        // TODO: Should we throw? Ignore?
 91                        continue;
 92                    }
 93
 10894                    IServiceDispatcher _serviceDispatcher = null;
 10895                    var _customBinding = dispatcher.Binding as CustomBinding ?? new CustomBinding(dispatcher.Binding);
 10896                    if (_customBinding.Elements.Find<ConnectionOrientedTransportBindingElement>() != null)
 97                    {
 10898                        var parameters = new BindingParameterCollection();
 10899                        if (_customBinding.CanBuildServiceDispatcher<IDuplexSessionChannel>(parameters))
 100                        {
 108101                            _serviceDispatcher = _customBinding.BuildServiceDispatcher<IDuplexSessionChannel>(parameters
 102                        }
 103                    }
 108104                    _serviceDispatcher ??= dispatcher;
 108105                    HandshakeDelegate handshake = BuildHandshakeDelegateForDispatcher(_serviceDispatcher);
 106
 108107                    logger.LogDebug("Registering URI {baseAddress} with NetMessageFramingConnectionHandler", dispatcher.
 108108                    addressTable.RegisterUri(dispatcher.BaseAddress, cotbe.HostNameComparisonMode, handshake);
 109                }
 110            }
 111
 83112            return addressTable;
 113        }
 114
 115        private static HandshakeDelegate BuildHandshakeDelegateForDispatcher(IServiceDispatcher dispatcher)
 116        {
 108117            BindingElementCollection be = dispatcher.Binding.CreateBindingElements();
 108118            MessageEncodingBindingElement mebe = be.Find<MessageEncodingBindingElement>();
 108119            MessageEncoderFactory mefact = mebe.CreateMessageEncoderFactory();
 108120            ConnectionOrientedTransportBindingElement tbe = be.Find<ConnectionOrientedTransportBindingElement>();
 108121            long maxReceivedMessageSize = tbe.MaxReceivedMessageSize;
 108122            int maxBufferSize = tbe.MaxBufferSize;
 108123            var bufferManager = BufferManager.CreateBufferManager(tbe.MaxBufferPoolSize, maxBufferSize);
 108124            int connectionBufferSize = tbe.ConnectionBufferSize;
 108125            TransferMode transferMode = tbe.TransferMode;
 346126            var upgradeBindingElements = (from element in be where element is StreamUpgradeBindingElement select element
 108127            StreamUpgradeProvider streamUpgradeProvider = null;
 108128            ISecurityCapabilities securityCapabilities = null;
 108129            if (upgradeBindingElements.Count > 1)
 130            {
 0131                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.MultipleStrea
 132            }
 133            // TODO: Limit NamedPipes to prevent it using SslStreamSecurityUpgradeProvider
 108134            else if ((upgradeBindingElements.Count == 1) && tbe.SupportsUpgrade(upgradeBindingElements[0]))
 135            {
 19136                SecurityCredentialsManager credentialsManager = dispatcher.Host.Description.Behaviors.Find<SecurityCrede
 19137                var bindingContext = new BindingContext(new CustomBinding(dispatcher.Binding), new BindingParameterColle
 138
 19139                if (credentialsManager != null)
 5140                    bindingContext.BindingParameters.Add(credentialsManager);
 141
 19142                streamUpgradeProvider = upgradeBindingElements[0].BuildServerStreamUpgradeProvider(bindingContext);
 19143                if (streamUpgradeProvider != null)
 144                {
 18145                    streamUpgradeProvider.OpenAsync().GetAwaiter().GetResult();
 18146                    securityCapabilities = upgradeBindingElements[0].GetProperty<ISecurityCapabilities>(bindingContext);
 18147                    var identity = (streamUpgradeProvider as StreamSecurityUpgradeProvider)?.Identity;
 18148                    if (identity != null)
 149                    {
 17150                        TryApplyIdentityToChannelDispatcher(dispatcher, identity);
 151                    }
 152                }
 153            }
 108154            return (connection) =>
 108155            {
 114156                connection.MessageEncoderFactory = mefact;
 114157                connection.StreamUpgradeAcceptor = streamUpgradeProvider?.CreateUpgradeAcceptor();
 114158                if(connection.StreamUpgradeAcceptor != null)
 108159                {
 8160                    connection.StreamUpgradeAcceptor.Features.Set<FramingConnection>(connection);
 108161                }
 114162                connection.SecurityCapabilities = securityCapabilities;
 114163                connection.ServiceDispatcher = dispatcher;
 114164                connection.BufferManager = bufferManager;
 114165                connection.MaxReceivedMessageSize = maxReceivedMessageSize;
 114166                connection.MaxBufferSize = maxBufferSize;
 114167                connection.ConnectionBufferSize = connectionBufferSize;
 114168                connection.TransferMode = transferMode;
 114169                return Task.CompletedTask;
 108170            };
 171        }
 172
 173        private static void TryApplyIdentityToChannelDispatcher(IServiceDispatcher dispatcher, EndpointIdentity identity
 174        {
 175            // The transport-derived identity applies only to the endpoints hosted on the
 176            // ChannelDispatcher for this service dispatcher's listen address. Applying it to
 177            // every ChannelDispatcher on the host would set a distinct identity instance on
 178            // endpoints that already had one, tripping EndpointDispatcher's set-once guard when
 179            // multiple net.tcp endpoints are hosted under transport security (see issue #1742).
 88180            foreach (ChannelDispatcher channelDispatcher in dispatcher.Host.ChannelDispatchers)
 181            {
 27182                if (channelDispatcher.ListenUri == dispatcher.BaseAddress)
 183                {
 68184                    foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
 185                    {
 17186                        endpointDispatcher.Identity = identity;
 187                    }
 188                }
 189            }
 17190        }
 191
 192        private static async Task PerformServiceHandshake(IFramingConnectionHandshakeBuilder configuration, FramingConne
 193        {
 115194            UriPrefixTable<HandshakeDelegate> addressTable = configuration.HandshakeServices.GetRequiredService<UriPrefi
 115195            HandshakeDelegate serviceHandshake = GetServiceHandshakeDelegate(addressTable, connection.Via);
 115196            if (serviceHandshake != null)
 197            {
 114198                await serviceHandshake(connection);
 114199                await next(connection);
 200            }
 201            else
 202            {
 1203                await connection.SendFaultAsync(FramingEncodingString.EndpointNotFoundFault, TransportDefaults.MaxDrainS
 204            }
 114205        }
 206
 207        private static HandshakeDelegate GetServiceHandshakeDelegate(UriPrefixTable<HandshakeDelegate> addressTable, Uri
 208        {
 115209            if (addressTable.TryLookupUri(via, HostNameComparisonMode.StrongWildcard, out HandshakeDelegate handshake))
 210            {
 114211                return handshake;
 212            }
 213
 1214            if (addressTable.TryLookupUri(via, HostNameComparisonMode.Exact, out handshake))
 215            {
 0216                return handshake;
 217            }
 218
 1219            addressTable.TryLookupUri(via, HostNameComparisonMode.WeakWildcard, out handshake);
 1220            return handshake;
 221        }
 222
 223        public override Task OnConnectedAsync(ConnectionContext context)
 224        {
 82225            var connection = new FramingConnection(context);
 82226            return _handshake(connection);
 227        }
 228    }
 229}