2020-10-20 16:20:38 +03:00

90 lines
2.9 KiB
C#

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<ScanJob> _logger;
private readonly IScanBackend _backend;
private readonly int _scanTimeout;
public ScanJob(IConfiguration configuration, ILogger<ScanJob> logger)
{
_logger = logger;
_scanTimeout = configuration.GetValue<int>("ScanTimeout");
_backend = configuration.GetValue<BackendType>("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<CancellationToken, Task<string[]>> 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);
}
}
}
}