using System.Diagnostics.CodeAnalysis; using System.Text.Json; using Backend.Helper; using MessagePack; using Models.Handler; using Models.Model.Backend; using Models.Model.External; using NetMQ; using NetMQ.Sockets; namespace Backend.Handler; public class Communication { private readonly NetMQPoller _poller; private readonly DbHandler _dbHandler; private readonly ThreadHandler _threadHandler; public Communication(DbHandler dbHandler, ThreadHandler threadHandler) { _dbHandler = dbHandler; _threadHandler = threadHandler; _poller = new(); } public WaitHandle[] Start() { WaitHandle[] waitHandles = new WaitHandle[1]; EventWaitHandle handle = new(false, EventResetMode.ManualReset); waitHandles[0] = handle; Thread thread = new(Server!); thread.Start(handle); return waitHandles; } private void Server(object obj) { using ResponseSocket server = new(); server.Bind("tcp://*:5556"); server.ReceiveReady += OnServerOnReceiveReady; _poller.Add(server); Console.WriteLine("Server is running and waiting for client requests..."); _poller.Run(); Console.WriteLine("Communication stopped."); ((EventWaitHandle) obj).Set(); } [RequiresDynamicCode("Calls System.Text.Json.JsonSerializer.Serialize(TValue, JsonSerializerOptions)")] [RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Serialize(TValue, JsonSerializerOptions)")] private void OnServerOnReceiveReady(object? _, NetMQSocketEventArgs e) { byte[] message = e.Socket.ReceiveFrameBytes(); CommunicationObject communicationObject = MessagePackSerializer.Deserialize(message); switch (communicationObject.Command) { case CommunicationCommand.GetScanningProgress: { DatabaseSizes databaseSizes = FilesystemHelper.GetDatabaseSizes(); long discardedIndexes = _dbHandler.GetDiscardedIndexes(); ScanningStatus status = new(); // 4294967296 is all Ipv4 addresses. if (discardedIndexes != 0) { status.PercentageOfIpv4Scanned = (float)discardedIndexes / 4294967296 * 100; } else { status.PercentageOfIpv4Scanned = 0.0000000001f; } status.AmountOfIpv4Left = 4294967296 - discardedIndexes; status.TotalFiltered = DbHandler.GetFilteredIndexes(); status.TotalDiscarded = discardedIndexes; status.MyDbSize = databaseSizes.MyDbSize; status.FilteredDbSize = databaseSizes.FilteredDbSize; status.DiscardedDbSize = databaseSizes.DiscardedDbSize; byte[] serializedResult = MessagePackSerializer.Serialize(status, MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray)); e.Socket.SendFrame(serializedResult); break; } case CommunicationCommand.StopScanning: SendStringResponse(e, "Server is stopping."); _threadHandler.Stop(); break; case CommunicationCommand.GarbageCollect: ThreadHandler.ManualGc(); SendStringResponse(e, "Server has garbage collected."); _threadHandler.Stop(); break; case CommunicationCommand.DbReindex: _dbHandler.ReIndex(); SendStringResponse(e, "All Dbs have been reindexed."); break; case CommunicationCommand.DbVacuum: _dbHandler.Vacuum(); SendStringResponse(e, "All Dbs have been vacuumed."); break; case CommunicationCommand.GetSearches: { if (!string.IsNullOrWhiteSpace(communicationObject.SearchTerm)) { SendSearchResponse(e, communicationObject.SearchTerm); } break; } } } private static void SendStringResponse(NetMQSocketEventArgs e, string response) { MessagePackSerializerOptions withCompression = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray); byte[] serializedResult = MessagePackSerializer.Serialize(response, withCompression); e.Socket.SendFrame(serializedResult); } private static void SendSearchResponse(NetMQSocketEventArgs e, string searchTerm) { //SearchResults result = SearchHelper.Search(communicationObject.SearchTerm!, _dbHandler); SearchResults result = new() { Results = [] }; SearchResult lol = new() { Url = "Remember to use an actual search tearm. Like 'dotnet 9.0'", Title = "Remember to use an actual search tearm. Like 'dotnet 9.0'", }; result.Results.Add(lol); string serializedResult = JsonSerializer.Serialize(result); e.Socket.SendFrame(serializedResult); } public void Stop() { _poller.Stop(); } }