.NET 7+ da SOCKS5 javoblari: qisman TCP o‘qishlarini boshqarish
SOCKS5 buyruq javobining qat’iy prefiksini va ATYPga bog‘liq suffiksini serverning TCP yozish chegaralariga tayanmasdan o‘qing.
SOCKS5 serveri to‘rt baytni alohida yozadi va mijoz faqat bu yozuvlar birlashtirilgandan keyin ishlaydi. Birlashtirish vaqtni o‘zgartirishi mumkin, lekin TCP hali ham har bir yozuvga bitta o‘qishni va’da qilmaydi.
Mijozga javob tahlilchisi kerak. Usul tanlovi va zarur autentifikatsiyadan so‘ng SOCKS5 buyruq javobi to‘rt bayt bilan boshlanadi: versiya, natija, zaxiralangan bayt va manzil turi. Qolgan uzunlik shu manzil turiga bog‘liq.
Faqat muvaffaqiyatli CONNECT javobini iste’mol qilishi kerak bo‘lgan .NET 7+ tahlilchisi quyidagini ishlatishi mumkin:
static async Task ReadConnectReply(Stream stream, CancellationToken ct)
{
byte[] prefix = new byte[4];
await stream.ReadExactlyAsync(prefix, ct);
if (prefix[0] != 5 || prefix[2] != 0)
throw new IOException("Invalid SOCKS5 reply");
if (prefix[1] != 0)
throw new IOException($"SOCKS5 request failed: {prefix[1]}");
int remaining;
switch (prefix[3])
{
case 1: remaining = 4 + 2; break;
case 4: remaining = 16 + 2; break;
case 3:
byte[] length = new byte[1];
await stream.ReadExactlyAsync(length, ct);
remaining = length[0] + 2;
break;
default:
throw new IOException("Unknown SOCKS5 address type");
}
await stream.ReadExactlyAsync(new byte[remaining], ct);
}
Oxirgi ikki bayt — bog‘langan port. IPv4 to‘rt bayt talab qiladi; IPv6 o‘n olti bayt talab qiladi; domen manzili nomidan oldin uzunlik baytini olib yuradi.
Ko‘zda tutilgan muzokara muddati bilan bekor qilish tokenini bering. ReadExactlyAsync qisqaroq alohida o‘qishlarni boshqaradi va oqim so‘ralgan uzunlikdan oldin tugasa istisno tashlaydi. Muvaffaqiyatsizlikda muvaffaqiyatsiz ulanishni uning egasining tozalash yo‘li orqali tashlang.
Muvaffaqiyatda javob chegarasida to‘xtang. Undan keyingi baytlar manzil protokoliga tegishli. Kattaroq taxminiy o‘qish ortiqcha baytlarni saqlashi kerak, ilova oqimining boshlanishini tashlamasligi kerak.