< Summary

Information
Class: IceRpc.Transports.Tcp.Internal.TcpListener
Assembly: IceRpc
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Transports/Tcp/Internal/TcpListener.cs
Tag: 1321_24790053727
Line coverage
90%
Covered lines: 54
Uncovered lines: 6
Coverable lines: 60
Total lines: 100
Line coverage: 90%
Branch coverage
87%
Covered branches: 7
Total branches: 8
Branch coverage: 87.5%
Method coverage
100%
Covered methods: 4
Fully covered methods: 2
Total methods: 4
Method coverage: 100%
Full method coverage: 50%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_TransportAddress()100%11100%
AcceptAsync()50%2288.23%
DisposeAsync()100%22100%
.ctor(...)100%4488.57%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Transports/Tcp/Internal/TcpListener.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Buffers;
 4using System.Net;
 5using System.Net.Security;
 6using System.Net.Sockets;
 7
 8namespace IceRpc.Transports.Tcp.Internal;
 9
 10/// <summary>The listener implementation for the TCP transport.</summary>
 11internal sealed class TcpListener : IListener<IDuplexConnection>
 12{
 13313    public TransportAddress TransportAddress { get; }
 14
 15    private readonly SslServerAuthenticationOptions? _serverAuthenticationOptions;
 16    private readonly int _minSegmentSize;
 17    private readonly MemoryPool<byte> _pool;
 18    private readonly Socket _socket;
 19
 20    // Set to 1 when the listener is disposed.
 21    private volatile int _disposed;
 22
 23    public async Task<(IDuplexConnection, EndPoint)> AcceptAsync(CancellationToken cancellationToken)
 12424    {
 25        try
 12426        {
 12427            Socket acceptedSocket = await _socket.AcceptAsync(cancellationToken).ConfigureAwait(false);
 28
 9229            var tcpConnection = new TcpServerConnection(
 9230                acceptedSocket,
 9231                _serverAuthenticationOptions,
 9232                _pool,
 9233                _minSegmentSize);
 9234            return (tcpConnection, acceptedSocket.RemoteEndPoint!);
 35        }
 336        catch (SocketException exception)
 337        {
 338            if (exception.SocketErrorCode == SocketError.OperationAborted)
 339            {
 340                ObjectDisposedException.ThrowIf(_disposed == 1, this);
 041            }
 042            throw exception.ToIceRpcException();
 43        }
 9244    }
 45
 46    public ValueTask DisposeAsync()
 19547    {
 19548        if (Interlocked.Exchange(ref _disposed, 1) == 0)
 11949        {
 11950            _socket.Dispose();
 11951        }
 19552        return default;
 19553    }
 54
 12455    internal TcpListener(
 12456        TransportAddress transportAddress,
 12457        DuplexConnectionOptions options,
 12458        SslServerAuthenticationOptions? serverAuthenticationOptions,
 12459        TcpServerTransportOptions tcpOptions)
 12460    {
 12461        if (!IPAddress.TryParse(transportAddress.Host, out IPAddress? ipAddress))
 262        {
 263            throw new ArgumentException(
 264                $"Listening on the DNS name '{transportAddress.Host}' is not allowed; an IP address is required.",
 265                nameof(transportAddress));
 66        }
 67
 12268        _serverAuthenticationOptions = serverAuthenticationOptions;
 12269        _minSegmentSize = options.MinSegmentSize;
 12270        _pool = options.Pool;
 71
 12272        var address = new IPEndPoint(ipAddress, transportAddress.Port);
 73
 74        // When using IPv6 address family we use the socket constructor without AddressFamily parameter to ensure
 75        // dual-mode socket are used in platforms that support them.
 12276        _socket = ipAddress.AddressFamily == AddressFamily.InterNetwork ?
 12277            new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp) :
 12278            new Socket(SocketType.Stream, ProtocolType.Tcp);
 79        try
 12280        {
 12281            _socket.ExclusiveAddressUse = true;
 12282            _socket.Configure(tcpOptions);
 12283            _socket.Bind(address);
 11984            address = (IPEndPoint)_socket.LocalEndPoint!;
 11985            _socket.Listen(tcpOptions.ListenBacklog);
 11986        }
 387        catch (SocketException exception)
 388        {
 389            _socket.Dispose();
 390            throw exception.ToIceRpcException();
 91        }
 092        catch
 093        {
 094            _socket.Dispose();
 095            throw;
 96        }
 97
 11998        TransportAddress = transportAddress with { Port = (ushort)address.Port };
 11999    }
 100}