< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Protocol.Services.PingPongService
Assembly: NLightning.Infrastructure
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Protocol/Services/PingPongService.cs
Tag: 36_15743069263
Line coverage
0%
Covered lines: 0
Uncovered lines: 31
Coverable lines: 31
Total lines: 97
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
StartPingAsync()0%110100%
HandlePong(...)0%7280%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure/Protocol/Services/PingPongService.cs

#LineLine coverage
 1using Microsoft.Extensions.Options;
 2
 3namespace NLightning.Infrastructure.Protocol.Services;
 4
 5using Domain.Exceptions;
 6using Domain.Node.Options;
 7using Domain.Protocol.Interfaces;
 8using Domain.Protocol.Messages;
 9
 10/// <summary>
 11/// Service for managing the ping pong protocol.
 12/// </summary>
 13/// <remarks>
 14/// This class is used to manage the ping pong protocol.
 15/// </remarks>
 16internal class PingPongService : IPingPongService
 17{
 18    private readonly IMessageFactory _messageFactory;
 19    private readonly NodeOptions _nodeOptions;
 020    private readonly Random _random = new();
 21
 022    private TaskCompletionSource<bool> _pongReceivedTaskSource = new();
 23    private PingMessage _pingMessage;
 24
 25    /// <inheritdoc />
 26    public event EventHandler<IMessage>? OnPingMessageReady;
 27
 28    /// <inheritdoc />
 29    public event EventHandler? OnPongReceived;
 30
 31    /// <inheritdoc />
 32    public event EventHandler<Exception>? DisconnectEvent;
 33
 034    public PingPongService(IMessageFactory messageFactory, IOptions<NodeOptions> nodeOptions)
 35    {
 036        _messageFactory = messageFactory;
 037        _nodeOptions = nodeOptions.Value;
 038        _pingMessage = messageFactory.CreatePingMessage();
 039    }
 40
 41    /// <inheritdoc />
 42    /// <remarks>
 43    /// Ping messages are sent to the peer at random intervals ranging from 30 seconds to 5 minutes.
 44    /// If a pong message is not received within the network timeout, DisconnectEvent is raised.
 45    /// </remarks>
 46    public async Task StartPingAsync(CancellationToken cancellationToken)
 47    {
 48        // Send the first ping message
 049        while (!cancellationToken.IsCancellationRequested)
 50        {
 051            OnPingMessageReady?.Invoke(this, _pingMessage);
 52
 053            using var pongTimeoutTokenSource = CancellationTokenSource
 054               .CreateLinkedTokenSource(cancellationToken,
 055                                        new CancellationTokenSource(_nodeOptions.NetworkTimeout).Token);
 56
 057            var task = await Task.WhenAny(_pongReceivedTaskSource.Task, Task.Delay(-1, pongTimeoutTokenSource.Token));
 058            if (task.IsFaulted)
 59            {
 060                DisconnectEvent?
 061                   .Invoke(this, new ConnectionException("Pong message not received within network timeout."));
 062                return;
 63            }
 64
 065            if (task.IsCanceled)
 66            {
 067                continue;
 68            }
 69
 70            // ReSharper disable once PossiblyMistakenUseOfCancellationToken
 071            await Task.Delay(_random.Next(30_000, 300_000), cancellationToken);
 72
 073            _pongReceivedTaskSource = new TaskCompletionSource<bool>();
 074            _pingMessage = _messageFactory.CreatePingMessage();
 075        }
 076    }
 77
 78    /// <inheritdoc />
 79    /// <remarks>
 80    /// Handles a pong message.
 81    /// If the pong message has a different length than the ping message, DisconnectEvent is raised.
 82    /// </remarks>
 83    public void HandlePong(IMessage message)
 84    {
 85        // if the pong message has a different length than the ping message, disconnect
 086        if (message is not PongMessage pongMessage ||
 087            pongMessage.Payload.BytesLength != _pingMessage.Payload.NumPongBytes)
 88        {
 089            DisconnectEvent?.Invoke(this, new Exception("Pong message has different length than ping message."));
 090            return;
 91        }
 92
 093        _pongReceivedTaskSource.TrySetResult(true);
 94
 095        OnPongReceived?.Invoke(this, EventArgs.Empty);
 096    }
 97}