LANCommander/LANCommander.SDK/Clients/BeaconClient.cs

183 lines
5.7 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
using LANCommander.SDK.Abstractions;
using LANCommander.SDK.Helpers;
using LANCommander.SDK.Interceptors;
using LANCommander.SDK.Models;
using Microsoft.Extensions.Logging;
namespace LANCommander.SDK.Services;
public class BeaconClient(
ILogger<BeaconClient> logger,
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
INetworkInformationProvider networkInformationProvider)
{
public delegate void OnBeaconResponseHandler(object sender, BeaconResponseArgs e);
public event OnBeaconResponseHandler OnBeaconResponse;
private List<DiscoveryProbe> _probeClients = new();
private List<DiscoveryBeacon> _beaconClients = new();
private List<IBeaconMessageInterceptor> _beaconMessageInterceptors = new();
public void Initialize()
{
_beaconMessageInterceptors = new List<IBeaconMessageInterceptor>();
}
public BeaconClient AddBeaconMessageInterceptor(IBeaconMessageInterceptor interceptor)
{
_beaconMessageInterceptors.Add(interceptor);
return this;
}
/// <summary>
/// Send broadcast packets across all interfaces to tell any server that we exist
/// </summary>
/// <param name="port">The port to beacon on</param>
/// <param name="retryAttempts">The number of attempts to make before giving up</param>
/// <param name="retryInterval">THe interval (in ms) between probe packets</param>
/// <param name="cancellationToken"></param>
2025-04-25 00:56:58 -05:00
public async Task StartProbeAsync(int port = 35891, int retryAttempts = 10, int retryInterval = 2000,
CancellationToken cancellationToken = default)
{
int attempt = 0;
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
foreach (var networkInterface in networkInformationProvider.GetNetworkInterfaces())
{
DiscoveryProbe probeClient = null;
try
{
probeClient = new DiscoveryProbe(networkInterface);
await probeClient.BindSocketAsync(port);
probeClient.OnBeaconResponse += (sender, args) => OnBeaconResponse?.Invoke(sender, args);
_probeClients.Add(probeClient);
}
catch
{
// ignored
probeClient?.Dispose();
_probeClients.Remove(probeClient);
}
}
while (!cancellationToken.IsCancellationRequested)
{
if (attempt >= retryAttempts || cancellationToken.IsCancellationRequested)
break;
2025-04-25 00:56:47 -05:00
foreach (var probe in _probeClients)
{
if (probe.IsDisposed)
continue;
2025-04-25 00:56:47 -05:00
await probe.SendAsync();
}
await Task.Delay(retryInterval, cancellationToken);
}
foreach (var client in _probeClients)
client.Dispose();
_probeClients.Clear();
}
/// <summary>
/// Stop any active probes
/// </summary>
public async Task StopProbeAsync()
{
foreach (var probeClient in _probeClients)
{
probeClient.Dispose();
}
}
/// <summary>
/// Cleans up ressources created for probing
/// </summary>
/// <remarks>Clears list of current probe clients</remarks>
public void CleanupProbe()
{
foreach (var probeClient in _probeClients)
{
if (!probeClient.IsDisposed)
{
probeClient.Dispose();
}
}
_probeClients.Clear();
}
/// <summary>
/// Start listening for probe broadcasts
/// </summary>
/// <param name="port">Port to listen on</param>
/// <param name="address">The server address to send to the probe</param>
/// <param name="name">The name of the server to send to the probe</param>
public async Task StartBeaconAsync(
int port,
string address,
string name)
{
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
foreach (var networkInterface in networkInformationProvider.GetNetworkInterfaces())
{
try
{
var beaconClient = new DiscoveryBeacon(networkInterface);
await beaconClient.StartAsync(port);
beaconClient.OnProbe += async (beacon, probeEndPoint) =>
{
var message = new BeaconMessage
{
Address = address,
Name = name,
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
Version = VersionHelper.GetCurrentVersion().ToString(),
};
foreach (var interceptor in _beaconMessageInterceptors)
{
message = await interceptor.ExecuteAsync(message, beacon.InterfaceIPEndPoint);
}
await beacon.SendAsync(JsonSerializer.Serialize(message), probeEndPoint);
};
2025-10-08 19:51:44 -05:00
logger?.LogInformation("Started beacon on network interface {NetworkInterface}", networkInterface.Name);
_beaconClients.Add(beaconClient);
}
catch (NetworkInformationException)
{
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
logger?.LogError("Unable to start beacon on network interface {NetworkInterface}",
networkInterface.Name);
}
catch (Exception ex)
{
Implement SDK using dependency injection - API requests are now made through the ApiRequestBuilder with DI supplied via the ApiRequestFactory singleton - Reliance on RestSharp and WebClient has been removed in favor of HttpClient - Auth token is now being tracked by the ITokenProvider - Network information (MAC address, broadcast addresses, IP address) is now supplied with the INetworkInformationProvider singleton - Connection state is now being maintained by the ConnectionService, with a reliance on RPC (SignalR websocket) reporting actual connection state without relying on pings - All download streams are now provided as a TrackableStream - Singleton Client class has been removed. All usage of the SDK should happen via Dependency Injection This is just a base, non-functional refactor of the SDK to use DI. The following changes to the rest of the codebase need to be made: - Usage of the SDK client in the launcher needs to be replaced in favor of injecting SDK services - PowerShell cmdlets need to be able to have services injected. Most likely a separate scope will have to be opened up per PS runtime? - Usage of the SDK client in the server needs to be replaced in favor of injecting SDK services. This should be minimal and should actually provide benefit when it comes to executing client-like features (scripts mostly) without needing a fully configured client that maintains connection state. - Configuration of the client needs to be implemented using ILANCommanderConfiguration
2025-09-22 00:29:51 -05:00
logger?.LogError(ex, "Unknown error while starting beacon on network interface {NetworkInterface}", networkInterface.Name);
}
}
}
/// <summary>
/// Kill any running beacons
/// </summary>
public async Task StopBeaconAsync()
{
foreach (var beaconClient in _beaconClients)
{
beaconClient.Dispose();
}
}
}