< Summary

Information
Class: IceRpc.Transports.Quic.Internal.QuicMultiplexedListener
Assembly: IceRpc.Transports.Quic
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Transports.Quic/Internal/QuicMultiplexedListener.cs
Tag: 275_13775359185
Line coverage
79%
Covered lines: 50
Uncovered lines: 13
Coverable lines: 63
Total lines: 98
Line coverage: 79.3%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage
100%
Covered methods: 4
Total methods: 4
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_ServerAddress()100%11100%
AcceptAsync()100%1.16145.45%
DisposeAsync()100%11100%
.ctor(...)75%4.05485.71%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc.Transports.Quic/Internal/QuicMultiplexedListener.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Diagnostics;
 4using System.Net;
 5using System.Net.Quic;
 6using System.Net.Security;
 7using System.Net.Sockets;
 8
 9namespace IceRpc.Transports.Quic.Internal;
 10
 11internal class QuicMultiplexedListener : IListener<IMultiplexedConnection>
 12{
 23713    public ServerAddress ServerAddress { get; }
 14
 15    private readonly QuicListener _listener;
 16    private readonly MultiplexedConnectionOptions _options;
 17    private readonly QuicServerConnectionOptions _quicServerOptions;
 18
 19    public async Task<(IMultiplexedConnection, EndPoint)> AcceptAsync(CancellationToken cancellationToken)
 23420    {
 21        try
 23422        {
 23423            QuicConnection connection = await _listener.AcceptConnectionAsync(cancellationToken).ConfigureAwait(false);
 22324            return (new QuicMultiplexedServerConnection(connection, _options), connection.RemoteEndPoint);
 25        }
 026        catch (QuicException exception)
 027        {
 028            throw exception.ToIceRpcException();
 29        }
 030        catch (SocketException exception)
 031        {
 032            throw exception.ToIceRpcException();
 33        }
 22334    }
 35
 47836    public ValueTask DisposeAsync() => _listener.DisposeAsync();
 37
 24438    internal QuicMultiplexedListener(
 24439        ServerAddress serverAddress,
 24440        MultiplexedConnectionOptions options,
 24441        QuicServerTransportOptions quicTransportOptions,
 24442        SslServerAuthenticationOptions authenticationOptions)
 24443    {
 24444        if (!IPAddress.TryParse(serverAddress.Host, out IPAddress? ipAddress))
 045        {
 046            throw new ArgumentException(
 047                $"Listening on the DNS name '{serverAddress.Host}' is not allowed; an IP address is required.",
 048                nameof(serverAddress));
 49        }
 50
 24451        _options = options;
 52
 24453        authenticationOptions = authenticationOptions.Clone();
 24454        authenticationOptions.ApplicationProtocols ??= new List<SslApplicationProtocol> // Mandatory with Quic
 24455        {
 24456            new SslApplicationProtocol(serverAddress.Protocol.Name)
 24457        };
 58
 24459        _quicServerOptions = new QuicServerConnectionOptions
 24460        {
 24461            DefaultCloseErrorCode = (int)MultiplexedConnectionCloseError.Aborted,
 24462            DefaultStreamErrorCode = 0,
 24463            IdleTimeout = quicTransportOptions.IdleTimeout,
 24464#if NET9_0_OR_GREATER
 24465            KeepAliveInterval = Timeout.InfiniteTimeSpan, // the server doesn't send PING frames
 24466#endif
 24467            ServerAuthenticationOptions = authenticationOptions,
 24468            MaxInboundBidirectionalStreams = options.MaxBidirectionalStreams,
 24469            MaxInboundUnidirectionalStreams = options.MaxUnidirectionalStreams
 24470        };
 71
 72        try
 24473        {
 74            // ListenAsync implementation is synchronous so it's safe to get the result synchronously.
 24475            ValueTask<QuicListener> task = QuicListener.ListenAsync(
 24476                new QuicListenerOptions
 24477                {
 24478                    ListenEndPoint = new IPEndPoint(ipAddress, serverAddress.Port),
 24479                    ListenBacklog = quicTransportOptions.ListenBacklog,
 24480                    ApplicationProtocols = authenticationOptions.ApplicationProtocols,
 22981                    ConnectionOptionsCallback = (connection, sslInfo, cancellationToken) => new(_quicServerOptions)
 24482                },
 24483                CancellationToken.None);
 24284            Debug.Assert(task.IsCompleted);
 24285            _listener = task.Result;
 86
 24287            ServerAddress = serverAddress with { Port = (ushort)_listener.LocalEndPoint.Port };
 24288        }
 289        catch (QuicException exception)
 290        {
 291            throw exception.ToIceRpcException();
 92        }
 093        catch (SocketException exception)
 094        {
 095            throw exception.ToIceRpcException();
 96        }
 24297    }
 98}