Files
SuperVPN/desktop_global/VideoReader/InOutSocket.cs
2025-10-09 09:57:24 +09:00

301 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<byte[]> outbuffer = new ConcurrentQueue<byte[]>();
private BinaryWriter bw;
private ConcurrentQueue<byte[]> output = new ConcurrentQueue<byte[]>();
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<byte[]>();
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;
}
}