From 8d659d4261a81dd99caef9a51662ac35d01ec20c Mon Sep 17 00:00:00 2001 From: Rasmus Date: Sat, 8 Feb 2025 13:02:18 +0100 Subject: [PATCH] Implement autosave --- Backend/Handler/ContentFilter.cs | 93 +++++++++++++++++--- Backend/Handler/IpFilterHandler.cs | 1 + Backend/Handler/IpScanner.cs | 54 +++++++++++- Backend/Handler/ThreadHandler.cs | 38 +++++--- Backend/Scripts/443Header0.txt | 76 ++++++++++++++++ Backend/Scripts/443Header1.txt | 70 +++++++++++++++ Backend/Scripts/443Header2.txt | 70 +++++++++++++++ Backend/Scripts/443Header3.txt | 70 +++++++++++++++ Backend/Scripts/80Header0.txt | 28 ++++++ Backend/Scripts/80Header1.txt | 4 + Backend/Scripts/80Header2.txt | 4 + Backend/Scripts/80Header3.txt | 4 + Models/BackupDB/ScannerResume.db | Bin 8192 -> 8192 bytes Models/CompressedDatabases.db | Bin 12288 -> 0 bytes Models/Filtered.db | Bin 118784 -> 0 bytes Models/Handler/DbHandler.cs | 34 +++++-- Models/Model/Backend/ScannerResumeObject.cs | 3 + Models/ScannerResume.db | Bin 8192 -> 0 bytes Models/mydb.db | Bin 73728 -> 0 bytes RSE.sln.DotSettings.user | 3 +- 20 files changed, 511 insertions(+), 41 deletions(-) create mode 100644 Backend/Scripts/443Header0.txt create mode 100644 Backend/Scripts/443Header1.txt create mode 100644 Backend/Scripts/443Header2.txt create mode 100644 Backend/Scripts/443Header3.txt create mode 100644 Backend/Scripts/80Header0.txt create mode 100644 Backend/Scripts/80Header1.txt create mode 100644 Backend/Scripts/80Header2.txt create mode 100644 Backend/Scripts/80Header3.txt delete mode 100644 Models/CompressedDatabases.db delete mode 100644 Models/Filtered.db delete mode 100644 Models/ScannerResume.db delete mode 100644 Models/mydb.db diff --git a/Backend/Handler/ContentFilter.cs b/Backend/Handler/ContentFilter.cs index 29c685b..0b444a0 100644 --- a/Backend/Handler/ContentFilter.cs +++ b/Backend/Handler/ContentFilter.cs @@ -6,10 +6,24 @@ using Models.Model.Backend; namespace Backend.Handler; +public class Content +{ + public int Port1 { get; set; } + public int Port2 { get; set; } + public Ip Ip { get; set; } +} + +public class ContentThread +{ + public int ThreadId { get; set; } + public EventWaitHandle EventWaitHandle { get; set; } +} + public class ContentFilter { private readonly ConcurrentQueue _queue; private readonly ConcurrentQueue _unfilteredQueue; + private readonly ConcurrentQueue _contentQueue = new(); private readonly DbHandler _dbHandler; private readonly string _getDomainPort80; private readonly string _getDomainPort443; @@ -58,6 +72,11 @@ public class ContentFilter { if (_stop) break; + if (_contentQueue.Count >= 500) + { + Thread.Sleep(1000); + } + Unfiltered unfiltered = _dbHandler.ReadUnfilteredWithId(indexes[i]); if (unfiltered.Filtered) continue; @@ -78,13 +97,13 @@ public class ContentFilter { continue; } + + Content content = new(); + content.Ip = ip; + content.Port1 = unfiltered.Port1; + content.Port2 = unfiltered.Port2; - Filtered filtered = GetSiteData(ip); - - filtered.Port1 = unfiltered.Port1; - filtered.Port2 = unfiltered.Port2; - - _queue.Enqueue(filtered); + _contentQueue.Enqueue(content); } Thread.Sleep(_timeOut); @@ -92,11 +111,59 @@ public class ContentFilter ((EventWaitHandle) obj).Set(); } - - private Filtered GetSiteData(Ip ip) + + public WaitHandle[] StartFilterThread(int threads) { - StartProcess(ip, 80); - StartProcess(ip, 443); + WaitHandle[] waitHandle = new WaitHandle[threads]; + + for (int i = 0; i < threads; i++) + { + EventWaitHandle handle = new(false, EventResetMode.ManualReset); + ContentThread contentThread = new(); + contentThread.ThreadId = i; + contentThread.EventWaitHandle = handle; + waitHandle[i] = handle; + + Thread thread = new(FilterThread!); + thread.Start(contentThread); + } + + return waitHandle; + } + + private void FilterThread(object obj) + { + ContentThread thread = (ContentThread) obj; + + while (!_stop) + { + if (_contentQueue.IsEmpty) + { + Thread.Sleep(1000); + } + + _contentQueue.TryDequeue(out Content? content); + + if (content is null) + { + continue; + } + + Filtered filtered = GetSiteData(content.Ip, thread.ThreadId); + + filtered.Port1 = content.Port1; + filtered.Port2 = content.Port2; + + _queue.Enqueue(filtered); + } + + thread.EventWaitHandle.Set(); + } + + private Filtered GetSiteData(Ip ip, int threadId) + { + StartProcess(ip, 80, threadId); + StartProcess(ip, 443, threadId); string url1 = ""; string url2 = ""; @@ -125,7 +192,7 @@ public class ContentFilter for (int i = 0; i < ports.Length; i++) { - using StreamReader streamReader = new($"{_basePath}/Backend/Scripts/{ports[i]}Header.txt"); + using StreamReader streamReader = new($"{_basePath}/Backend/Scripts/{ports[i]}Header{threadId}.txt"); while (streamReader.Peek() != -1) { @@ -192,7 +259,7 @@ public class ContentFilter return siteData; } - private void StartProcess(Ip ip, int port) + private void StartProcess(Ip ip, int port, int threadId) { string fileName = port == 80 ? _getDomainPort80 : _getDomainPort443; @@ -200,7 +267,7 @@ public class ContentFilter proc.StartInfo = new() { FileName = "/bin/bash", - Arguments = $"{fileName} {ip.Ip1}.{ip.Ip2}.{ip.Ip3}.{ip.Ip4} {_basePath}/Backend/Scripts/{port}Header.txt", + Arguments = $"{fileName} {ip.Ip1}.{ip.Ip2}.{ip.Ip3}.{ip.Ip4} {_basePath}/Backend/Scripts/{port}Header{threadId}.txt", UseShellExecute = false, RedirectStandardOutput = false, RedirectStandardError = false, diff --git a/Backend/Handler/IpFilterHandler.cs b/Backend/Handler/IpFilterHandler.cs index 00f4a02..cce748d 100644 --- a/Backend/Handler/IpFilterHandler.cs +++ b/Backend/Handler/IpFilterHandler.cs @@ -73,6 +73,7 @@ public class IpFilterHandler if (i == 10) { _stopAutoscaledThreads = false; + Console.WriteLine("Autoscaler started"); while (!_stopAutoscaledThreads) { diff --git a/Backend/Handler/IpScanner.cs b/Backend/Handler/IpScanner.cs index 65f2aaf..8dbb371 100644 --- a/Backend/Handler/IpScanner.cs +++ b/Backend/Handler/IpScanner.cs @@ -108,16 +108,26 @@ public class IpScanner if (resumeNow is not null) { + if (resumeNow.Completed) + { + return; + } + scanSettings.Start = resumeNow.FirstByte; scanSettings.End = resumeNow.EndRange; secondByte = resumeNow.SecondByte; thirdByte = resumeNow.ThirdByte; fourthByte = resumeNow.FourthByte; } + else + { + CreateResumeObject(scanSettings.ThreadNumber, scanSettings.Start, scanSettings.End, scanSettings.Start, secondByte, thirdByte, fourthByte, false, false, Operations.Insert); + } // Empty buffer so we use the lowest abstracted ping.Send() method. byte[] buf = []; using Ping ping = new(); + int x = 0; for (int i = scanSettings.Start; i < scanSettings.End; i++) { @@ -148,6 +158,14 @@ public class IpScanner for (int l = fourthByte; l < 256; l++) { + if (x == 75_000) + { + CreateResumeObject(scanSettings.ThreadNumber, scanSettings.Start, scanSettings.End, i, j, k, l, false, false, Operations.Update); + x = 0; + } + + x++; + if (_stop) { resumeObject.FourthByte = l; @@ -172,12 +190,12 @@ public class IpScanner if (address is not null) { responseCode = ping.Send(address, _timeout, buf, null).Status; - //Thread.Sleep(256); + //Thread.Sleep(4); } } - catch (Exception e) + catch { - Console.WriteLine(e); + // } if (responseCode != IPStatus.Success) @@ -211,11 +229,39 @@ public class IpScanner Console.WriteLine($"Thread ({scanSettings.ThreadNumber}) is at index ({i}) out of ({scanSettings.End}). Remaining ({scanSettings.End - i})"); } - + + if (_stop) + { + resumeObject.Paused = true; + } + else + { + resumeObject.Completed = true; + } + + resumeObject.Operation = Operations.Update; + _resumeQueue.Enqueue(resumeObject); scanSettings.Handle!.Set(); } + + private void CreateResumeObject(int threadNumber, int startRange, int endRange, int firstByte, int secondByte, int thirdByte, int fourthByte, bool paused, bool completed, Operations operation) + { + ScannerResumeObject resumeObject = new(); + resumeObject.ThreadNumber = threadNumber; + resumeObject.StartRange = startRange; + resumeObject.EndRange = endRange; + resumeObject.FirstByte = firstByte; + resumeObject.SecondByte = secondByte; + resumeObject.ThirdByte = thirdByte; + resumeObject.FourthByte = fourthByte; + resumeObject.Paused = paused; + resumeObject.Completed = completed; + resumeObject.Operation = operation; + + _resumeQueue.Enqueue(resumeObject); + } private static Discarded CreateDiscardedQueueItem(Ip ip, int responseCode) { diff --git a/Backend/Handler/ThreadHandler.cs b/Backend/Handler/ThreadHandler.cs index 4fb3e54..d1f6d8e 100644 --- a/Backend/Handler/ThreadHandler.cs +++ b/Backend/Handler/ThreadHandler.cs @@ -34,35 +34,38 @@ public class ThreadHandler public void Start() { - //Thread scanner = new(StartScanner); - //Thread ipFilter = new(StartIpFilter); + Thread scanner = new(StartScanner); + Thread ipFilter = new(StartIpFilter); Thread indexer = new(StartContentFilter); Thread database = new(StartDbHandler); Thread discarded = new(StartDiscardedDbHandler); Thread filtered = new(StartFilteredDbHandler); Thread resume = new(StartResumeDbHandler); - //Thread communication = new(StartCommunicationHandler); - //Thread ipFilterAutoScaler = new(StartIpFilterAutoScaler); + Thread communication = new(StartCommunicationHandler); + Thread ipFilterAutoScaler = new(StartIpFilterAutoScaler); + Thread contentFilterThread = new(StartContentFilterThread); - //ipFilter.Start(); - //scanner.Start(); - //ipFilterAutoScaler.Start(); + ipFilter.Start(); + scanner.Start(); + ipFilterAutoScaler.Start(); indexer.Start(); database.Start(); discarded.Start(); filtered.Start(); resume.Start(); - //communication.Start(); + communication.Start(); + contentFilterThread.Start(); - //scanner.Join(); - //ipFilter.Join(); + scanner.Join(); + ipFilter.Join(); indexer.Join(); database.Join(); discarded.Join(); filtered.Join(); resume.Join(); - //communication.Join(); - //ipFilterAutoScaler.Join(); + communication.Join(); + ipFilterAutoScaler.Join(); + contentFilterThread.Join(); } private void StartScanner() @@ -94,6 +97,13 @@ public class ThreadHandler _contentFilterStopped = true; } + private void StartContentFilterThread() + { + WaitHandle[] wait = _contentFilter.StartFilterThread(4); + + WaitHandle.WaitAll(wait); + } + private void StartIpFilterAutoScaler() { _ipFilterHandler.AutoScaler(); @@ -139,7 +149,7 @@ public class ThreadHandler Console.WriteLine("Discarded DbHandler finished"); } - /*private void StartCommunicationHandler() + private void StartCommunicationHandler() { WaitHandle[] wait = _communication.Start(); @@ -150,7 +160,7 @@ public class ThreadHandler _communicationStopped = true; Stop(); - }*/ + } private void Stop() { diff --git a/Backend/Scripts/443Header0.txt b/Backend/Scripts/443Header0.txt new file mode 100644 index 0000000..740521a --- /dev/null +++ b/Backend/Scripts/443Header0.txt @@ -0,0 +1,76 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.0.72.3:443... +* Connected to 192.0.72.3 (192.0.72.3) port 443 +* ALPN: curl offers h2,http/1.1 +} [5 bytes data] +* TLSv1.3 (OUT), TLS handshake, Client hello (1): +} [512 bytes data] +* TLSv1.3 (IN), TLS handshake, Server hello (2): +{ [122 bytes data] +* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): +{ [15 bytes data] +* TLSv1.3 (IN), TLS handshake, Certificate (11): +{ [2063 bytes data] +* TLSv1.3 (IN), TLS handshake, CERT verify (15): +{ [79 bytes data] +* TLSv1.3 (IN), TLS handshake, Finished (20): +{ [52 bytes data] +* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): +} [1 bytes data] +* TLSv1.3 (OUT), TLS handshake, Finished (20): +} [52 bytes data] +* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / id-ecPublicKey +* ALPN: server accepted h2 +* Server certificate: +* subject: CN=files.wordpress.com +* start date: Dec 16 09:49:37 2024 GMT +* expire date: Mar 16 09:49:36 2025 GMT +* issuer: C=US; O=Let's Encrypt; CN=E6 +* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. +* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 +* Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption +} [5 bytes data] +* using HTTP/2 +* [HTTP/2] [1] OPENED stream for https://192.0.72.3/ +* [HTTP/2] [1] [:method: HEAD] +* [HTTP/2] [1] [:scheme: https] +* [HTTP/2] [1] [:authority: 192.0.72.3] +* [HTTP/2] [1] [:path: /] +* [HTTP/2] [1] [user-agent: curl/8.9.1] +* [HTTP/2] [1] [accept: */*] +} [5 bytes data] +> HEAD / HTTP/2 +> Host: 192.0.72.3 +> User-Agent: curl/8.9.1 +> Accept: */* +> +* Request completely sent off +{ [5 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +< HTTP/2 302 +< server: nginx +< date: Fri, 07 Feb 2025 22:58:34 GMT +< content-type: text/html; charset=utf-8 +< location: https://developer.wordpress.com +< vary: Cookie +< x-nc: MISS hhn 3 +< x-content-type-options: nosniff +< alt-svc: h3=":443"; ma=86400 +< +{ [0 bytes data] + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +* Connection #0 to host 192.0.72.3 left intact +HTTP/2 302 +server: nginx +date: Fri, 07 Feb 2025 22:58:34 GMT +content-type: text/html; charset=utf-8 +location: https://developer.wordpress.com +vary: Cookie +x-nc: MISS hhn 3 +x-content-type-options: nosniff +alt-svc: h3=":443"; ma=86400 + diff --git a/Backend/Scripts/443Header1.txt b/Backend/Scripts/443Header1.txt new file mode 100644 index 0000000..450aab7 --- /dev/null +++ b/Backend/Scripts/443Header1.txt @@ -0,0 +1,70 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.0.66.251:443... +* Connected to 192.0.66.251 (192.0.66.251) port 443 +* ALPN: curl offers h2,http/1.1 +} [5 bytes data] +* TLSv1.3 (OUT), TLS handshake, Client hello (1): +} [512 bytes data] +* TLSv1.3 (IN), TLS handshake, Server hello (2): +{ [122 bytes data] +* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): +{ [15 bytes data] +* TLSv1.3 (IN), TLS handshake, Certificate (11): +{ [2033 bytes data] +* TLSv1.3 (IN), TLS handshake, CERT verify (15): +{ [79 bytes data] +* TLSv1.3 (IN), TLS handshake, Finished (20): +{ [52 bytes data] +* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): +} [1 bytes data] +* TLSv1.3 (OUT), TLS handshake, Finished (20): +} [52 bytes data] +* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / id-ecPublicKey +* ALPN: server accepted h2 +* Server certificate: +* subject: CN=go-vip.co +* start date: Jan 18 19:43:58 2025 GMT +* expire date: Apr 18 19:43:57 2025 GMT +* issuer: C=US; O=Let's Encrypt; CN=E5 +* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. +* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 +* Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption +} [5 bytes data] +* using HTTP/2 +* [HTTP/2] [1] OPENED stream for https://192.0.66.251/ +* [HTTP/2] [1] [:method: HEAD] +* [HTTP/2] [1] [:scheme: https] +* [HTTP/2] [1] [:authority: 192.0.66.251] +* [HTTP/2] [1] [:path: /] +* [HTTP/2] [1] [user-agent: curl/8.9.1] +* [HTTP/2] [1] [accept: */*] +} [5 bytes data] +> HEAD / HTTP/2 +> Host: 192.0.66.251 +> User-Agent: curl/8.9.1 +> Accept: */* +> +* Request completely sent off +{ [5 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +< HTTP/2 404 +< server: nginx +< date: Fri, 07 Feb 2025 22:58:27 GMT +< content-type: text/html +< content-length: 146 +< x-rq: hhn2 +< +{ [0 bytes data] + 0 146 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +* Connection #0 to host 192.0.66.251 left intact +HTTP/2 404 +server: nginx +date: Fri, 07 Feb 2025 22:58:27 GMT +content-type: text/html +content-length: 146 +x-rq: hhn2 + diff --git a/Backend/Scripts/443Header2.txt b/Backend/Scripts/443Header2.txt new file mode 100644 index 0000000..2e5251c --- /dev/null +++ b/Backend/Scripts/443Header2.txt @@ -0,0 +1,70 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.0.66.254:443... +* Connected to 192.0.66.254 (192.0.66.254) port 443 +* ALPN: curl offers h2,http/1.1 +} [5 bytes data] +* TLSv1.3 (OUT), TLS handshake, Client hello (1): +} [512 bytes data] +* TLSv1.3 (IN), TLS handshake, Server hello (2): +{ [122 bytes data] +* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): +{ [15 bytes data] +* TLSv1.3 (IN), TLS handshake, Certificate (11): +{ [2033 bytes data] +* TLSv1.3 (IN), TLS handshake, CERT verify (15): +{ [78 bytes data] +* TLSv1.3 (IN), TLS handshake, Finished (20): +{ [52 bytes data] +* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): +} [1 bytes data] +* TLSv1.3 (OUT), TLS handshake, Finished (20): +} [52 bytes data] +* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / id-ecPublicKey +* ALPN: server accepted h2 +* Server certificate: +* subject: CN=go-vip.co +* start date: Jan 18 19:43:58 2025 GMT +* expire date: Apr 18 19:43:57 2025 GMT +* issuer: C=US; O=Let's Encrypt; CN=E5 +* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. +* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 +* Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption +} [5 bytes data] +* using HTTP/2 +* [HTTP/2] [1] OPENED stream for https://192.0.66.254/ +* [HTTP/2] [1] [:method: HEAD] +* [HTTP/2] [1] [:scheme: https] +* [HTTP/2] [1] [:authority: 192.0.66.254] +* [HTTP/2] [1] [:path: /] +* [HTTP/2] [1] [user-agent: curl/8.9.1] +* [HTTP/2] [1] [accept: */*] +} [5 bytes data] +> HEAD / HTTP/2 +> Host: 192.0.66.254 +> User-Agent: curl/8.9.1 +> Accept: */* +> +* Request completely sent off +{ [5 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +< HTTP/2 404 +< server: nginx +< date: Fri, 07 Feb 2025 22:58:28 GMT +< content-type: text/html +< content-length: 146 +< x-rq: hhn2 +< +{ [0 bytes data] + 0 146 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +* Connection #0 to host 192.0.66.254 left intact +HTTP/2 404 +server: nginx +date: Fri, 07 Feb 2025 22:58:28 GMT +content-type: text/html +content-length: 146 +x-rq: hhn2 + diff --git a/Backend/Scripts/443Header3.txt b/Backend/Scripts/443Header3.txt new file mode 100644 index 0000000..215e22b --- /dev/null +++ b/Backend/Scripts/443Header3.txt @@ -0,0 +1,70 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.0.66.253:443... +* Connected to 192.0.66.253 (192.0.66.253) port 443 +* ALPN: curl offers h2,http/1.1 +} [5 bytes data] +* TLSv1.3 (OUT), TLS handshake, Client hello (1): +} [512 bytes data] +* TLSv1.3 (IN), TLS handshake, Server hello (2): +{ [122 bytes data] +* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): +{ [15 bytes data] +* TLSv1.3 (IN), TLS handshake, Certificate (11): +{ [2033 bytes data] +* TLSv1.3 (IN), TLS handshake, CERT verify (15): +{ [78 bytes data] +* TLSv1.3 (IN), TLS handshake, Finished (20): +{ [52 bytes data] +* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): +} [1 bytes data] +* TLSv1.3 (OUT), TLS handshake, Finished (20): +} [52 bytes data] +* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / id-ecPublicKey +* ALPN: server accepted h2 +* Server certificate: +* subject: CN=go-vip.co +* start date: Jan 18 19:43:58 2025 GMT +* expire date: Apr 18 19:43:57 2025 GMT +* issuer: C=US; O=Let's Encrypt; CN=E5 +* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. +* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 +* Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption +} [5 bytes data] +* using HTTP/2 +* [HTTP/2] [1] OPENED stream for https://192.0.66.253/ +* [HTTP/2] [1] [:method: HEAD] +* [HTTP/2] [1] [:scheme: https] +* [HTTP/2] [1] [:authority: 192.0.66.253] +* [HTTP/2] [1] [:path: /] +* [HTTP/2] [1] [user-agent: curl/8.9.1] +* [HTTP/2] [1] [accept: */*] +} [5 bytes data] +> HEAD / HTTP/2 +> Host: 192.0.66.253 +> User-Agent: curl/8.9.1 +> Accept: */* +> +* Request completely sent off +{ [5 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +{ [249 bytes data] +< HTTP/2 404 +< server: nginx +< date: Fri, 07 Feb 2025 22:58:28 GMT +< content-type: text/html +< content-length: 146 +< x-rq: hhn2 +< +{ [0 bytes data] + 0 146 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +* Connection #0 to host 192.0.66.253 left intact +HTTP/2 404 +server: nginx +date: Fri, 07 Feb 2025 22:58:28 GMT +content-type: text/html +content-length: 146 +x-rq: hhn2 + diff --git a/Backend/Scripts/80Header0.txt b/Backend/Scripts/80Header0.txt new file mode 100644 index 0000000..44e3cbc --- /dev/null +++ b/Backend/Scripts/80Header0.txt @@ -0,0 +1,28 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 192.0.72.3:80... +* Connected to 192.0.72.3 (192.0.72.3) port 80 +> HEAD / HTTP/1.1 +> Host: 192.0.72.3 +> User-Agent: curl/8.9.1 +> Accept: */* +> +* Request completely sent off +< HTTP/1.1 301 Moved Permanently +< Server: nginx +< Date: Fri, 07 Feb 2025 22:58:33 GMT +< Content-Type: text/html +< Content-Length: 162 +< Connection: keep-alive +< Location: https://192.0.72.3/ +< + 0 162 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +* Connection #0 to host 192.0.72.3 left intact +HTTP/1.1 301 Moved Permanently +Server: nginx +Date: Fri, 07 Feb 2025 22:58:33 GMT +Content-Type: text/html +Content-Length: 162 +Connection: keep-alive +Location: https://192.0.72.3/ + diff --git a/Backend/Scripts/80Header1.txt b/Backend/Scripts/80Header1.txt new file mode 100644 index 0000000..7fa8cfd --- /dev/null +++ b/Backend/Scripts/80Header1.txt @@ -0,0 +1,4 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 141.0.64.106:80... + 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0 \ No newline at end of file diff --git a/Backend/Scripts/80Header2.txt b/Backend/Scripts/80Header2.txt new file mode 100644 index 0000000..35429d1 --- /dev/null +++ b/Backend/Scripts/80Header2.txt @@ -0,0 +1,4 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 141.0.68.86:80... + 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0 \ No newline at end of file diff --git a/Backend/Scripts/80Header3.txt b/Backend/Scripts/80Header3.txt new file mode 100644 index 0000000..33a551f --- /dev/null +++ b/Backend/Scripts/80Header3.txt @@ -0,0 +1,4 @@ + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 141.0.68.78:80... + 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:02 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:03 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:05 --:--:-- 0 \ No newline at end of file diff --git a/Models/BackupDB/ScannerResume.db b/Models/BackupDB/ScannerResume.db index a44725c94c534967899d2392373bfd3dd9f212b2..a57f8e71158332b096ec8e683d33c793afcbc2e8 100644 GIT binary patch delta 139 zcmZp0XmFSyEx3h&fq@B#VL)M`jxqlh2EBMGUZ4;o-)08B%^M3{`M8?A7}>=oB^g`t zCo}T@oqUg<*FGSzv^X_IiPO_B#MRw3NWsrPM8PlA$47^YQ^`3$w;(6A1e-LMCdg<8 Pfz5^j3;8xSL^1*ZW(y%9 delta 416 zcmY+;ze)o^5C-sX_hRl(E<3wkAxS`N6_FEPVAU6hg|&8ql|I28QBb=CeE@ANtW4|# z;d}v+ly*LW5QJ+~oV)W12XD+jJ{C8 zpefviPDh*^Tt2Dqm0-DOfCgwr@AN{CbW2y1&>`*8HpR3^zWP*CHRbU;m5}yCRdfCQ z9Vv^YrUa>%3_s5!@!_`PCAObc^L9YSyz3Hz|5USI##| l diff --git a/Models/CompressedDatabases.db b/Models/CompressedDatabases.db deleted file mode 100644 index 4a547900dda6905478f96200534182152e226a85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI#&r8EF6bJC68_EX$xD7moo?14%^ytO91*vw~jM<^5(Ygr2y1J&rv;L?4C#GT# zj^fSB_&!LJzPyI^)6;u=h+itro{KV1D;AJ*LMgdsj1bbbqhm)C^}5bAL7T-NbC+B$ zFHUTMbNWfn0((I~00Izz00bZa0SG_<0uX=z1pY%{?i>w-XGf<@O?>_$`-A%oG!gI3C&jBon(l(`EavEZ$7(&Rj;*P$ul2CtiIv3m0k@ z3HvfrE|lN*>)zZp{Rjv^00Izz00bZa0SG_<0uX=z1P)jL{r>^~Tznb?AOHafKmY;| PfB*y_009U<;78yK=7C|d diff --git a/Models/Filtered.db b/Models/Filtered.db deleted file mode 100644 index ccb8ab2383d3860d6f1e6053719d5b8f77ad2acb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118784 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 500_000 && !_compressing) + if (i >= 5_000_000 && !_compressing) { _compressing = true; @@ -457,19 +459,31 @@ public class DbHandler { using SqliteConnection connection = new(_resumeConnectionString); connection.Open(); - - using SqliteCommand command = new(InsertIntoResume, connection); + SqliteCommand command; + + if (resumeObject.Operation == Operations.Insert) + { + command = new(InsertIntoResume, connection); + command.Parameters.AddWithValue("@startRange", resumeObject.StartRange); + command.Parameters.AddWithValue("@endRange", resumeObject.EndRange); + } + else + { + command = new(UpdateResumeStatement, connection); + } command.Parameters.AddWithValue("@threadNumber", resumeObject.ThreadNumber); - command.Parameters.AddWithValue("@startRange", resumeObject.StartRange); - command.Parameters.AddWithValue("@endRange", resumeObject.EndRange); command.Parameters.AddWithValue("@firstByte", resumeObject.FirstByte); command.Parameters.AddWithValue("@secondByte", resumeObject.SecondByte); command.Parameters.AddWithValue("@thirdByte", resumeObject.ThirdByte); command.Parameters.AddWithValue("@fourthByte", resumeObject.FourthByte); + command.Parameters.AddWithValue("@paused", resumeObject.Paused); + command.Parameters.AddWithValue("@completed", resumeObject.Completed); _ = command.ExecuteNonQuery(); connection.Close(); + + command.Dispose(); } private void InsertCompressedDatabase(int threadNumber, long rows) @@ -739,7 +753,7 @@ public class DbHandler using SqliteConnection connection = new(_resumeConnectionString); connection.Open(); - using SqliteCommand command = new(ReadAndDeleteResumeStatement, connection); + using SqliteCommand command = new(ReadResumeStatement, connection); command.Parameters.AddWithValue("@threadNumber", threadNumber); using SqliteDataReader reader = command.ExecuteReader(); @@ -760,6 +774,8 @@ public class DbHandler resumeObject.SecondByte = reader.GetInt32(4); resumeObject.ThirdByte = reader.GetInt32(5); resumeObject.FourthByte = reader.GetInt32(6); + resumeObject.Paused = reader.GetBoolean(7); + resumeObject.Completed = reader.GetBoolean(8); } return resumeObject; diff --git a/Models/Model/Backend/ScannerResumeObject.cs b/Models/Model/Backend/ScannerResumeObject.cs index 0799b6e..e29c57d 100644 --- a/Models/Model/Backend/ScannerResumeObject.cs +++ b/Models/Model/Backend/ScannerResumeObject.cs @@ -9,4 +9,7 @@ public class ScannerResumeObject public int ThirdByte { get; set; } public int FourthByte { get; set; } public int ThreadNumber { get; set; } + public Operations Operation { get; set; } + public bool Paused { get; set; } + public bool Completed { get; set; } } \ No newline at end of file diff --git a/Models/ScannerResume.db b/Models/ScannerResume.db deleted file mode 100644 index a44725c94c534967899d2392373bfd3dd9f212b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeI1K}#D!6oB8%Mzfp5osBsZ6=cY%g(6D-z$UVa5K@zD&UI~86ETTyHiw=XQlUMz z;1AG?=hkCS=^rR1$KLu2gdpT1(zhEIDl~fY^oE_;+3(G~8NNLYQz;c1zAN|IUeodA zD=>gDFr@^5OROAgRF<$4i$3tp{^?KaUc$upm&Vu#7IPgV&--(AQ>&nmB372 z;XH(D1e1sc@a;b2&_meg3XF}os!i4~p_fN;m6?s^DmX|NzhRNj$3lh;GQ5i)C~%ur eCQQTJK{~90hsls*GE;?7imAAhV25TLZvFzJ^MOqO diff --git a/Models/mydb.db b/Models/mydb.db deleted file mode 100644 index f0567d0e17771070b55102f99f0196f52a46dfe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73728 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%0ATM!5Wgqsma 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 ItBIcd0=B|nZvX%Q diff --git a/RSE.sln.DotSettings.user b/RSE.sln.DotSettings.user index e7d85bb..a0f49b6 100644 --- a/RSE.sln.DotSettings.user +++ b/RSE.sln.DotSettings.user @@ -20,4 +20,5 @@ ForceIncluded ForceIncluded ForceIncluded - ForceIncluded \ No newline at end of file + ForceIncluded + ForceIncluded \ No newline at end of file