// // 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); } }