~ruther/NosTale-PacketLogger

18df69cdbb20143d0bdcbc2ebcc39e135d0fc42f — František Boháček 2 years ago a86fc38
feat: add packet providers
A src/PacketLogger/Models/Packets/FilePacketProvider.cs => src/PacketLogger/Models/Packets/FilePacketProvider.cs +98 -0
@@ 0,0 1,98 @@
//
//  FilePacketProvider.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using DynamicData;
using NosSmooth.PacketSerializer.Abstractions.Attributes;
using PacketLogger.Models.Filters;
using Remora.Results;

namespace PacketLogger.Models.Packets;

/// <summary>
/// Provides packets using a file from the file system.
/// </summary>
public class FilePacketProvider : IPacketProvider
{
    private readonly string _fileName;
    private IReadOnlyList<PacketInfo>? _packets;
    private ObservableCollection<PacketInfo>? _filteredPackets;

    /// <summary>
    /// Initializes a new instance of the <see cref="FilePacketProvider"/> class.
    /// </summary>
    /// <param name="fileName">The name of the file.</param>
    public FilePacketProvider(string fileName)
    {
        _fileName = fileName;
    }

    /// <inheritdoc />
    public bool IsOpen => false;

    /// <inheritdoc />
    public SourceList<PacketInfo> Packets => throw new InvalidOperationException("File client not initialized yet.");

    /// <inheritdoc/>
    public async Task<Result> Open()
    {
        if (!File.Exists(_fileName))
        {
            return new NotFoundError($"Could not find file {_fileName}");
        }

        var packets = new List<PacketInfo>();
        var index = 0;
        foreach (var line in await File.ReadAllLinesAsync(_fileName))
        {
            if (line.Length <= 1)
            {
                continue;
            }

            var splitted = line.Split('\t', 3);
            if (splitted.Length != 3)
            {
                continue;
            }

            packets.Add
            (
                new PacketInfo
                (
                    index++,
                    DateTime.Parse(splitted[0].Trim('[', ']')),
                    splitted[1] == "[Recv]" ? PacketSource.Server : PacketSource.Client,
                    splitted[2]
                )
            );
        }

        _packets = packets.AsReadOnly();
        _filteredPackets = new ObservableCollection<PacketInfo>(_packets);
        return Result.FromSuccess();
    }

    /// <inheritdoc/>
    public Task<Result> Close()
        => Task.FromResult(Result.FromSuccess());

    /// <inheritdoc />
    public void Clear()
    {
        // Clearing packets from file does not make any sense...
    }

    /// <inheritdoc />
    public event PropertyChangedEventHandler? PropertyChanged;
}
\ No newline at end of file

A src/PacketLogger/Models/Packets/IPacketProvider.cs => src/PacketLogger/Models/Packets/IPacketProvider.cs +48 -0
@@ 0,0 1,48 @@
//
//  IPacketProvider.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using DynamicData;
using PacketLogger.Models.Filters;
using Remora.Results;

namespace PacketLogger.Models.Packets;

/// <summary>
/// Provides packets from some kind of a source.
/// </summary>
public interface IPacketProvider : INotifyPropertyChanged
{
    /// <summary>
    /// Gets whether <see cref="Open"/> was called and successfully finished.
    /// </summary>
    public bool IsOpen { get; }

    /// <summary>
    /// Gets the filtered packets from this provider.
    /// </summary>
    public SourceList<PacketInfo> Packets { get; }

    /// <summary>
    /// Open the provider/connection, load etc.
    /// </summary>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Task<Result> Open();

    /// <summary>
    /// Close the connection, dispose.
    /// </summary>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Task<Result> Close();

    /// <summary>
    /// Clear all packets.
    /// </summary>
    public void Clear();
}
\ No newline at end of file

A src/PacketLogger/Models/Packets/IPacketSender.cs => src/PacketLogger/Models/Packets/IPacketSender.cs +34 -0
@@ 0,0 1,34 @@
//
//  IPacketSender.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Remora.Results;

namespace PacketLogger.Models.Packets;

/// <summary>
/// A provider that may as well send or receive packets.
/// </summary>
public interface IPacketSender : IPacketProvider
{
    /// <summary>
    /// Send the given packets.
    /// </summary>
    /// <param name="packetString">The packet to send.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    Task<Result> SendPacket(string packetString, CancellationToken ct = default);

    /// <summary>
    /// Receive the given packet.
    /// </summary>
    /// <param name="packetString">The packet to send.</param>
    /// <param name="ct">The cancellation token used for cancelling the operation.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    Task<Result> ReceivePacket(string packetString, CancellationToken ct = default);
}
\ No newline at end of file

A src/PacketLogger/Models/Packets/PacketInfo.cs => src/PacketLogger/Models/Packets/PacketInfo.cs +12 -0
@@ 0,0 1,12 @@
//
//  PacketInfo.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using NosSmooth.PacketSerializer.Abstractions.Attributes;

namespace PacketLogger.Models.Packets;

public record PacketInfo(long PacketIndex, DateTime Date, PacketSource Source, string PacketString);
\ No newline at end of file

Do not follow this link