using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading; using VideoReader.Properties; namespace VideoReader; internal class InOutSocket { public int bitrateout = 0; public int bitratein = 0; private static byte[] keyByte = MD5("73!2#qweaSdzxc4r"); private static byte[] ivByte = MD5("0_=op[l:',./vf73"); private Form1 Form; private bool open; private ServerConfig config; private ConcurrentQueue outbuffer = new ConcurrentQueue(); private BinaryWriter bw; private ConcurrentQueue output = new ConcurrentQueue(); private bool noblock = true; public bool opened { get { return open; } set { open = value; } } private static byte[] MD5(string str) { return new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(str)); } private static byte[] crypt(ICryptoTransform cryptoTransform, byte[] data) { using MemoryStream memoryStream = new MemoryStream(); using CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write); cryptoStream.Write(data, 0, data.Length); cryptoStream.FlushFinalBlock(); return memoryStream.ToArray(); } private static byte[] encrypt(byte[] buf) { byte[] result = new byte[0]; using (Aes aes = Aes.Create()) { aes.Key = keyByte; aes.IV = ivByte; using ICryptoTransform cryptoTransform = aes.CreateEncryptor(aes.Key, aes.IV); result = crypt(cryptoTransform, buf); } return result; } private static byte[] decrypt(byte[] buf) { byte[] result = new byte[0]; using (Aes aes = Aes.Create()) { aes.Key = keyByte; aes.IV = ivByte; using ICryptoTransform cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV); result = crypt(cryptoTransform, buf); } return result; } public InOutSocket(Form1 form, ServerConfig serverConfig = null) { Form = form; config = serverConfig ?? ServerConfigManager.GetDefault(); open = true; // Логирование используемой конфигурации Console.WriteLine($"Using server profile: {config.ProfileName}"); Console.WriteLine($"Signaling server: {config.SignalingServer}"); Console.WriteLine($"Data port: {config.DataPort}"); Console.WriteLine($"Default channel: {config.DefaultChannel}"); Thread thread = new Thread((ThreadStart)delegate { Events(); }); thread.IsBackground = true; thread.Start(); } ~InOutSocket() { open = false; } private int sockWrite(BinaryWriter ns, byte[] buf, int pref) { int num = 0; buf = encrypt(buf); if (buf.Length != 0) { byte[] array = BitConverter.GetBytes(buf.Length + 1); for (int num2 = array.Length; num2 > 0; num2--) { if (array[num2 - 1] > 0) { if (num2 < 4) { Array.Resize(ref array, num2); } break; } } ns.Write((byte)array.Length); num++; ns.Write(array); num += array.Length; ns.Write(buf); num += buf.Length; ns.Write((byte)pref); num++; ns.Flush(); } return num; } public string IpGet() { string result = config.FallbackIP ?? "127.0.0.1"; try { // Формируем URL с учетом SSL string protocol = config.UseSSL ? "https" : "http"; string url = $"{protocol}://{config.SignalingServer}/get-ip-kr.php?port={config.DefaultChannel}"; Console.WriteLine($"Requesting IP from: {url}"); WebRequest request = WebRequest.Create(url); request.Timeout = config.ConnectionTimeout; // Добавляем кастомные заголовки если есть if (config.CustomHeaders != null) { foreach (var header in config.CustomHeaders) { request.Headers.Add(header.Key, header.Value); } } Stream responseStream = request.GetResponse().GetResponseStream(); int[] array = new int[4]; for (int i = 0; i < 4; i++) { array[i] = responseStream.ReadByte(); } result = $"{array[0]}.{array[1]}.{array[2]}.{array[3]}"; Console.WriteLine($"Received IP: {result}"); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } return result; } private void Events() { Stopwatch stopwatch = new Stopwatch(); DateTime now = DateTime.Now; TcpClient tcpClient = new TcpClient(); stopwatch.Start(); Stopwatch stopwatch2 = new Stopwatch(); stopwatch2.Start(); byte b = 0; BinaryReader binaryReader = null; DateTime now2 = DateTime.Now; int num = 0; int num2 = 0; while (open) { try { if ((DateTime.Now - now).TotalSeconds > 10.0 || !tcpClient.Connected) { string mediaServerIP = IpGet(); Console.WriteLine($"Connecting to media server: {mediaServerIP}:{config.DataPort}"); tcpClient = new TcpClient(mediaServerIP, config.DataPort); tcpClient.GetStream().WriteByte(0); // Receiver type tcpClient.GetStream().WriteByte(config.DefaultChannel); tcpClient.GetStream().Flush(); binaryReader = new BinaryReader(tcpClient.GetStream()); bw = new BinaryWriter(tcpClient.GetStream()); output = new ConcurrentQueue(); stopwatch.Restart(); now = DateTime.Now; stopwatch2.Restart(); Thread.Sleep(1); Console.WriteLine($"Connected to channel {config.DefaultChannel}"); } // Используем конфигурируемый интервал heartbeat if (config.EnableHeartbeat && stopwatch.ElapsedMilliseconds > config.HeartbeatInterval) { num2 += sockWrite(bw, BitConverter.GetBytes(DateTime.Now.Ticks), 0); stopwatch.Restart(); } if (tcpClient.Available > 0) { int num3 = binaryReader.Read(); num++; if (num3 < 4) { byte[] array = binaryReader.ReadBytes(num3); num += num3; Array.Resize(ref array, 4); int num4 = BitConverter.ToInt32(array, 0); if (num4 > 0) { byte[] array2 = binaryReader.ReadBytes(num4); num += num4; int num5 = array2[^1]; array2 = decrypt(array2.Take(array2.Length - 1).ToArray()); if (num5 == 0 && array2.Length == 8) { Form.Read((double)(DateTime.Now.Ticks - BitConverter.ToInt64(array2, 0)) / 10000.0); } else { Form.Read(array2); } } } now = DateTime.Now; } else { Thread.Sleep(1); } b = (byte)((b++ < 2) ? 2 : b); byte[] result; while (outbuffer.TryDequeue(out result)) { num2 += sockWrite(bw, result, b); } if ((DateTime.Now - now2).TotalSeconds > 1.0) { double totalSeconds = (DateTime.Now - now2).TotalSeconds; bitratein = (int)Math.Round((double)num / totalSeconds); bitrateout = (int)Math.Round((double)num2 / totalSeconds); now2 = DateTime.Now; num = 0; num2 = 0; } } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } } tcpClient.Close(); stopwatch.Stop(); } public void write(byte[] buf, byte chenal) { outbuffer.Enqueue(buf); } public string[] GetStr(int i) { return new string[0]; } public int GetThCount() { return 1; } }