using System; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using EasyNetQ; using MalwareMultiScan.Api.Services.Interfaces; using MalwareMultiScan.Backends.Messages; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace MalwareMultiScan.Api.Services.Implementations { /// public class ReceiverHostedService : IReceiverHostedService { private readonly IBus _bus; private readonly IConfiguration _configuration; private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; private readonly IScanResultService _scanResultService; /// /// Initialize receiver hosted service. /// /// EasyNetQ bus. /// Configuration. /// Scan result service. /// Logger. /// HTTP client factory. public ReceiverHostedService(IBus bus, IConfiguration configuration, IScanResultService scanResultService, ILogger logger, IHttpClientFactory httpClientFactory) { _bus = bus; _configuration = configuration; _scanResultService = scanResultService; _logger = logger; _httpClientFactory = httpClientFactory; } /// public Task StartAsync(CancellationToken cancellationToken) { _bus.Receive( _configuration.GetValue("ResultsSubscriptionId"), StoreScanResult); _logger.LogInformation( "Started hosted service for receiving scan results"); return Task.CompletedTask; } /// public Task StopAsync(CancellationToken cancellationToken) { _bus?.Dispose(); _logger.LogInformation( "Stopped hosted service for receiving scan results"); return Task.CompletedTask; } private async Task StoreScanResult(ScanResultMessage message) { message.Threats ??= new string[] { }; _logger.LogInformation( $"Received a result from {message.Backend} for {message.Id} " + $"with threats {string.Join(",", message.Threats)}"); await _scanResultService.UpdateScanResultForBackend( message.Id, message.Backend, message.Duration, true, message.Succeeded, message.Threats); var result = await _scanResultService.GetScanResult(message.Id); if (result?.CallbackUrl == null) return; var cancellationTokenSource = new CancellationTokenSource( TimeSpan.FromSeconds(3)); using var httpClient = _httpClientFactory.CreateClient(); try { var response = await httpClient.PostAsync( result.CallbackUrl, new StringContent(JsonConvert.SerializeObject(result), Encoding.UTF8, "application/json"), cancellationTokenSource.Token); response.EnsureSuccessStatusCode(); } catch (Exception exception) { _logger.LogError(exception, $"Failed to POST to callback URL {result.CallbackUrl}"); } } } }