using File_Watcher.Models; using System.Net.Sockets; using System.Text; namespace File_Watcher.Helpers; internal static partial class TransmissionControlProtocolHelper { private record Record(BinaryReader BinaryReader, BinaryWriter BinaryWriter, NetworkStream NetworkStream, List ReadTimes); private static long _LastWrite; private static Record? _Record; private static readonly object _Lock = new(); private static void ReadFiles(TransmissionControlProtocolConfiguration tcpConfiguration, ILogger logger) { List bytes = []; // byte nullByte = Convert.ToByte('\0'); string directory = GetDirectory(tcpConfiguration); string[] files = Directory.GetFiles(directory, $"{tcpConfiguration.IPAddress}-*.raw", SearchOption.TopDirectoryOnly); logger.LogInformation("Read {count} files", files.Length); foreach (string file in files) { foreach (byte @byte in File.ReadAllBytes(file)) { // if (@byte.Equals(nullByte)) // continue; bytes.Add(@byte); } } if (bytes.Count > 0) { string bytesFile = Path.Combine(directory, $"{tcpConfiguration.IPAddress}-{DateTime.Now.Ticks}.pcl"); File.WriteAllBytes(bytesFile, bytes.ToArray()); foreach (string file in files) File.Delete(file); } } private static void CreateClient(AppSettings appSettings, ILogger logger) { logger.LogDebug(appSettings.TransmissionControlProtocolConfiguration.IPAddress); TcpClient tcpClient = new(appSettings.TransmissionControlProtocolConfiguration.IPAddress, appSettings.TransmissionControlProtocolConfiguration.Port); NetworkStream networkStream = tcpClient.GetStream(); _Record = new(BinaryReader: new(networkStream), BinaryWriter: new(networkStream), NetworkStream: networkStream, ReadTimes: []); } private static string GetDirectory(TransmissionControlProtocolConfiguration tcpConfiguration) { string result = Path.GetFullPath(Path.Combine(tcpConfiguration.Destination, tcpConfiguration.IPAddress)); if (!Directory.Exists(result)) _ = Directory.CreateDirectory(result); return result; } private static void NetworkStreamCanRead(TransmissionControlProtocolConfiguration tcpConfiguration, ILogger logger, NetworkStream networkStream) { List results = []; byte[] bytes = new byte[1024]; string directory = GetDirectory(tcpConfiguration); do { int count = networkStream.Read(bytes, 0, bytes.Length); if (count > 0) results.AddRange(bytes.Take(count)); } while (networkStream.DataAvailable); logger.LogInformation("Read {count} bytes", results.Count); if (results.Count > 0) { bytes = results.ToArray(); File.WriteAllBytes(Path.Combine(directory, $"{tcpConfiguration.IPAddress}-{DateTime.Now.Ticks}.raw"), bytes); if (!string.IsNullOrEmpty(tcpConfiguration.DelimiterPattern)) { string content = Encoding.ASCII.GetString(bytes); logger.LogDebug("Content {content}", content); if (content.Contains(tcpConfiguration.DelimiterPattern)) ReadFiles(tcpConfiguration, logger); } } } internal static bool ReadWrite(AppSettings appSettings, ILogger logger) { lock (_Lock) { if (!appSettings.TransmissionControlProtocolConfiguration.Server && _Record is not null && appSettings.TransmissionControlProtocolConfiguration.DelimiterSeconds > 0) { TimeSpan? timeSpan = _Record.ReadTimes.Count == 0 ? null : new(DateTime.Now.Ticks - _Record.ReadTimes[^1]); if (timeSpan is not null && timeSpan.Value.TotalSeconds > appSettings.TransmissionControlProtocolConfiguration.DelimiterSeconds) { ReadFiles(appSettings.TransmissionControlProtocolConfiguration, logger); _Record.ReadTimes.Clear(); } } if (!appSettings.TransmissionControlProtocolConfiguration.Server && _Record is not null) { TimeSpan timeSpan = new(DateTime.Now.Ticks - _LastWrite); if (_LastWrite == 0 || timeSpan.TotalMinutes > 1) { try { _Record.NetworkStream.WriteByte(Convert.ToByte('\0')); _LastWrite = DateTime.Now.Ticks; } catch (Exception) { } } } if (!appSettings.TransmissionControlProtocolConfiguration.Server && (_Record?.NetworkStream is null || !_Record.NetworkStream.Socket.Connected)) CreateClient(appSettings, logger); else if (appSettings.TransmissionControlProtocolConfiguration.Server) throw new NotImplementedException($"Use {nameof(HelperTCP)}"); if (_Record?.NetworkStream is not null && _Record.NetworkStream.CanRead && _Record.NetworkStream.DataAvailable) { _Record.ReadTimes.Add(DateTime.Now.Ticks); NetworkStreamCanRead(appSettings.TransmissionControlProtocolConfiguration, logger, _Record.NetworkStream); } if (appSettings.TransmissionControlProtocolConfiguration.Server && _Record?.NetworkStream is not null && _Record.NetworkStream.CanWrite) throw new NotImplementedException($"Use {nameof(HelperTCP)}"); } return true; } }