using System; using System.IO; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MalwareMultiScan.Backends.Backends.Implementations; using MalwareMultiScan.Shared.Data.Enums; using MalwareMultiScan.Shared.Data.Responses; using MalwareMultiScan.Shared.Interfaces; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace MalwareMultiScan.Worker.Jobs { public class ScanJob { private readonly ILogger _logger; private readonly IScanBackend _backend; private readonly int _scanTimeout; public ScanJob(IConfiguration configuration, ILogger logger) { _logger = logger; _scanTimeout = configuration.GetValue("ScanTimeout"); _backend = configuration.GetValue("BackendType") switch { BackendType.Defender => new WindowsDefenderScanBackend(logger), _ => throw new NotImplementedException() }; } public async Task PostResult(ResultResponse response, Uri callbackUrl, CancellationToken cancellationToken) { var serializedResponse = JsonSerializer.Serialize( response, typeof(ResultResponse), new JsonSerializerOptions { WriteIndented = true }); _logger.LogInformation(serializedResponse); } private async Task Scan(Func> scanMethod, Uri callbackUrl) { var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.CancelAfter(_scanTimeout * 1000); var cancellationToken = cancellationTokenSource.Token; var response = new ResultResponse { Backend = _backend.Name }; try { response.Success = true; response.Threats = await scanMethod(cancellationToken); response.DatabaseLastUpdate = _backend.DatabaseLastUpdate; } catch (Exception exception) { response.Success = false; _logger.LogError(exception, "Scanning failed with exception"); } await PostResult(response, callbackUrl, cancellationToken); } public async Task ScanUrl(Uri url, Uri callbackUrl) { await Scan(async t => await _backend.ScanAsync(url, t), callbackUrl); } public async Task ScanFile(string file, Uri callbackUrl) { try { await Scan(async t => await _backend.ScanAsync(file, t), callbackUrl); } finally { File.Delete(file); } } } }