//
// ProcessTcpManager.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.Diagnostics;
using Microsoft.Extensions.Options;
namespace NosSmooth.Pcap;
///
/// A manager containing tcp connections, allowing notifications
/// to to know about any new connections.
///
public class ProcessTcpManager
{
private readonly PcapNostaleOptions _options;
private readonly SemaphoreSlim _semaphore;
private readonly List _processes;
private DateTimeOffset _lastRefresh;
private IReadOnlyDictionary> _connections;
///
/// Initializes a new instance of the class.
///
/// The options.
public ProcessTcpManager(IOptions options)
{
_options = options.Value;
_lastRefresh = DateTimeOffset.MinValue;
_semaphore = new SemaphoreSlim(1, 1);
_processes = new List();
_connections = new Dictionary>();
}
///
/// Register the given process to refreshing list to allow calling
/// with that process.
///
/// The id of the process to register.
/// A representing the asynchronous operation.
public async Task RegisterProcess(int processId)
{
await _semaphore.WaitAsync();
try
{
_processes.Add(processId);
}
finally
{
_semaphore.Release();
}
}
///
/// Unregister the given process from refreshing list, won't
/// work for that process anymore.
///
/// The process to unregister.
/// A representing the asynchronous operation.
public async Task UnregisterProcess(int processId)
{
await _semaphore.WaitAsync();
try
{
_processes.Remove(processId);
}
finally
{
_semaphore.Release();
}
}
///
/// Get connections established by the given process.
///
///
/// Works only for processes registered using .
///
/// The id of process to retrieve connections for.
/// The list of process connections.
public async Task> GetConnectionsAsync(int processId)
{
await Refresh();
if (!_connections.ContainsKey(processId))
{
return Array.Empty();
}
return _connections[processId];
}
private async Task Refresh()
{
if (_lastRefresh.AddMilliseconds(_options.ProcessRefreshInterval) >= DateTimeOffset.Now)
{
return;
}
_lastRefresh = DateTimeOffset.Now;
if (_processes.Count == 0)
{
if (_connections.Count > 0)
{
_connections = new Dictionary>();
}
}
_semaphore.WaitAsync();
var processes = new List(_processes);
_semaphore.Release();
_connections = TcpConnectionHelper.GetConnections(processes);
}
}