< Summary

Information
Class: IceRpc.ClientProtocolConnectionFactory
Assembly: IceRpc
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/ClientProtocolConnectionFactory.cs
Tag: 1856_27024993493
Line coverage
82%
Covered lines: 76
Uncovered lines: 16
Coverable lines: 92
Total lines: 156
Line coverage: 82.6%
Branch coverage
83%
Covered branches: 25
Total branches: 30
Branch coverage: 83.3%
Method coverage
100%
Covered methods: 3
Fully covered methods: 1
Total methods: 3
Method coverage: 100%
Full method coverage: 33.3%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)87.5%161690.9%
CreateConnection(...)78.57%171474.46%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/ClientProtocolConnectionFactory.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using IceRpc.Internal;
 4using IceRpc.Transports;
 5using IceRpc.Transports.Internal;
 6using Microsoft.Extensions.Logging;
 7using Microsoft.Extensions.Logging.Abstractions;
 8using System.Net.Security;
 9
 10namespace IceRpc;
 11
 12/// <summary>Default implementation of <see cref="IClientProtocolConnectionFactory" />.</summary>
 13public sealed class ClientProtocolConnectionFactory : IClientProtocolConnectionFactory
 14{
 215    private static readonly string[] _iceParams = ["t", "z"];
 16
 17    private readonly ConnectionOptions _connectionOptions;
 18    private readonly IDuplexClientTransport _duplexClientTransport;
 19    private readonly DuplexConnectionOptions _duplexConnectionOptions;
 20    private readonly SslClientAuthenticationOptions? _iceClientAuthenticationOptions;
 21    private readonly SslClientAuthenticationOptions? _iceRpcClientAuthenticationOptions;
 22    private readonly ILogger _logger;
 23    private readonly IMultiplexedClientTransport _multiplexedClientTransport;
 24    private readonly MultiplexedConnectionOptions _multiplexedConnectionOptions;
 25
 26    /// <summary>Constructs a client protocol connection factory.</summary>
 27    /// <param name="connectionOptions">The connection options.</param>
 28    /// <param name="connectTimeout">The connect timeout.</param>
 29    /// <param name="clientAuthenticationOptions">The client authentication options.</param>
 30    /// <param name="duplexClientTransport">The duplex client transport. <see langword="null" /> is equivalent to <see
 31    /// cref="IDuplexClientTransport.Default" />.</param>
 32    /// <param name="multiplexedClientTransport">The multiplexed client transport. <see langword="null" /> is equivalent
 33    /// to <see cref="IMultiplexedClientTransport.Default" />.</param>
 34    /// <param name="logger">The logger. <see langword="null" /> is equivalent to <see cref="NullLogger.Instance" />.
 35    /// </param>
 10336    public ClientProtocolConnectionFactory(
 10337        ConnectionOptions connectionOptions,
 10338        TimeSpan connectTimeout,
 10339        SslClientAuthenticationOptions? clientAuthenticationOptions = null,
 10340        IDuplexClientTransport? duplexClientTransport = null,
 10341        IMultiplexedClientTransport? multiplexedClientTransport = null,
 10342        ILogger? logger = null)
 10343    {
 10344        if (clientAuthenticationOptions?.ApplicationProtocols is not null)
 045        {
 046            throw new ArgumentException(
 047                "The ApplicationProtocols property of the SSL client authentication options must be null. The ALPN is se
 048                nameof(clientAuthenticationOptions));
 49        }
 50
 10351        _connectionOptions = connectionOptions;
 52
 10353        _duplexClientTransport = duplexClientTransport ?? IDuplexClientTransport.Default;
 10354        _duplexConnectionOptions = new DuplexConnectionOptions
 10355        {
 10356            Pool = connectionOptions.Pool,
 10357            MinSegmentSize = connectionOptions.MinSegmentSize,
 10358        };
 59
 10360        _multiplexedClientTransport = multiplexedClientTransport ?? IMultiplexedClientTransport.Default;
 61
 62        // If the dispatcher is null, we don't allow the peer to open streams for incoming requests. The only stream
 63        // which is accepted locally is the control stream created by the peer.
 10364        _multiplexedConnectionOptions = new MultiplexedConnectionOptions
 10365        {
 10366            HandshakeTimeout = connectTimeout,
 10367
 10368            MaxBidirectionalStreams = connectionOptions.Dispatcher is null ? 0 :
 10369                connectionOptions.MaxIceRpcBidirectionalStreams,
 10370
 10371            // Add an additional stream for the icerpc protocol control stream.
 10372            MaxUnidirectionalStreams = connectionOptions.Dispatcher is null ? 1 :
 10373                connectionOptions.MaxIceRpcUnidirectionalStreams + 1,
 10374
 10375            Pool = connectionOptions.Pool,
 10376            MinSegmentSize = connectionOptions.MinSegmentSize,
 10377        };
 78
 79        // Clone and set ALPN for each protocol.
 10380        if (clientAuthenticationOptions is not null)
 581        {
 582            _iceClientAuthenticationOptions = clientAuthenticationOptions.ShallowClone();
 583            _iceClientAuthenticationOptions.ApplicationProtocols = [Protocol.Ice.AlpnProtocol];
 84
 585            _iceRpcClientAuthenticationOptions = clientAuthenticationOptions.ShallowClone();
 586            _iceRpcClientAuthenticationOptions.ApplicationProtocols = [Protocol.IceRpc.AlpnProtocol];
 587        }
 88
 10389        _logger = logger ?? NullLogger.Instance;
 10390    }
 91
 92    /// <summary>Creates a protocol connection to the specified server address.</summary>
 93    /// <param name="serverAddress">The address of the server.</param>
 94    /// <returns>The new protocol connection.</returns>
 95    /// <remarks>The protocol connection returned by this factory method is not connected. The caller must call
 96    /// <see cref="IProtocolConnection.ConnectAsync" /> exactly once on this connection before calling
 97    /// <see cref="IInvoker.InvokeAsync" />.</remarks>
 98    public IProtocolConnection CreateConnection(ServerAddress serverAddress)
 10599    {
 105100        var transportAddress = new TransportAddress
 105101        {
 105102            Host = serverAddress.Host,
 105103            Port = serverAddress.Port,
 105104            TransportName = serverAddress.Transport,
 105105            Params = serverAddress.Params
 105106        };
 107
 108        IProtocolConnection connection;
 105109        if (serverAddress.Protocol == Protocol.Ice)
 27110        {
 27111            SslClientAuthenticationOptions? clientAuthenticationOptions = _iceClientAuthenticationOptions;
 27112            if (clientAuthenticationOptions is null && _duplexClientTransport.IsSslRequired(serverAddress.Transport))
 0113            {
 0114                clientAuthenticationOptions = new SslClientAuthenticationOptions
 0115                {
 0116                    ApplicationProtocols = [Protocol.Ice.AlpnProtocol]
 0117                };
 0118            }
 119
 120            // Strip Ice-specific params ("t", "z") before passing to transport. These params have no
 121            // effect with IceRPC transports.
 27122            transportAddress = transportAddress with
 27123            {
 27124                Params = transportAddress.Params.RemoveRange(_iceParams)
 27125            };
 126
 27127            connection = new IceProtocolConnection(
 27128                _duplexClientTransport.CreateConnection(transportAddress, _duplexConnectionOptions, clientAuthentication
 27129                transportConnectionInformation: null,
 27130                _connectionOptions);
 27131        }
 132        else
 78133        {
 78134            SslClientAuthenticationOptions? clientAuthenticationOptions = _iceRpcClientAuthenticationOptions;
 78135            if (clientAuthenticationOptions is null && _multiplexedClientTransport.IsSslRequired(serverAddress.Transport
 0136            {
 0137                clientAuthenticationOptions = new SslClientAuthenticationOptions
 0138                {
 0139                    ApplicationProtocols = [Protocol.IceRpc.AlpnProtocol]
 0140                };
 0141            }
 142
 78143            connection = new IceRpcProtocolConnection(
 78144                _multiplexedClientTransport.CreateConnection(transportAddress, _multiplexedConnectionOptions, clientAuth
 78145                transportConnectionInformation: null,
 78146                _connectionOptions,
 78147                taskExceptionObserver: _logger == NullLogger.Instance ? null :
 78148                    new LogTaskExceptionObserver(_logger));
 78149        }
 150
 105151        connection = new MetricsProtocolConnectionDecorator(connection, Metrics.ClientMetrics, connectStarted: false);
 152
 105153        return _logger == NullLogger.Instance ? connection :
 105154            new LogProtocolConnectionDecorator(connection, serverAddress, remoteNetworkAddress: null, _logger);
 105155    }
 156}