diff --git a/Content.cs b/Content.cs index 1d39e47..69b1c26 100644 --- a/Content.cs +++ b/Content.cs @@ -6,9 +6,9 @@ using Newtonsoft.Json.Linq; -using Yove.HttpClient.Exceptions; +using Yove.Http.Exceptions; -namespace Yove.HttpClient; +namespace Yove.Http; [ConfigureAwait(false)] public class Content : IDisposable diff --git a/Content/ByteContent.cs b/Content/ByteContent.cs index 37aae95..a239f66 100644 --- a/Content/ByteContent.cs +++ b/Content/ByteContent.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Yove.HttpClient; +namespace Yove.Http; public class ByteContent : HttpContent { diff --git a/Content/FileContent.cs b/Content/FileContent.cs index b93c1cc..cd7680b 100644 --- a/Content/FileContent.cs +++ b/Content/FileContent.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Yove.HttpClient; +namespace Yove.Http; public class FileContent : StreamContent { diff --git a/Content/HttpContent.cs b/Content/HttpContent.cs index 53e12e2..88d174f 100644 --- a/Content/HttpContent.cs +++ b/Content/HttpContent.cs @@ -1,6 +1,6 @@ using System.IO; -namespace Yove.HttpClient; +namespace Yove.Http; public abstract class HttpContent { diff --git a/Content/MultipartContent.cs b/Content/MultipartContent.cs index 6b04a65..075cdc7 100644 --- a/Content/MultipartContent.cs +++ b/Content/MultipartContent.cs @@ -4,7 +4,7 @@ using System.IO; using System.Text; -namespace Yove.HttpClient; +namespace Yove.Http; public class MultipartContent : HttpContent, IEnumerable, IDisposable { diff --git a/Content/StreamContent.cs b/Content/StreamContent.cs index 4411bf6..851e551 100644 --- a/Content/StreamContent.cs +++ b/Content/StreamContent.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Yove.HttpClient; +namespace Yove.Http; public class StreamContent : HttpContent { diff --git a/Content/StringContent.cs b/Content/StringContent.cs index 60dad53..a8f007c 100644 --- a/Content/StringContent.cs +++ b/Content/StringContent.cs @@ -1,7 +1,7 @@ using System; using System.Text; -namespace Yove.HttpClient; +namespace Yove.Http; public class StringContent : ByteContent { diff --git a/Enum/ConnectionResult.cs b/Enums/ConnectionResult.cs similarity index 86% rename from Enum/ConnectionResult.cs rename to Enums/ConnectionResult.cs index f8fe134..c175eb6 100644 --- a/Enum/ConnectionResult.cs +++ b/Enums/ConnectionResult.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient.Proxy; +namespace Yove.Http.Proxy; public enum ConnectionResult { diff --git a/Enum/HttpBrowser.cs b/Enums/HttpBrowser.cs similarity index 76% rename from Enum/HttpBrowser.cs rename to Enums/HttpBrowser.cs index 570fcdc..4287a45 100644 --- a/Enum/HttpBrowser.cs +++ b/Enums/HttpBrowser.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient; +namespace Yove.Http; public enum HttpBrowser { diff --git a/Enum/HttpMethod.cs b/Enums/HttpMethod.cs similarity index 87% rename from Enum/HttpMethod.cs rename to Enums/HttpMethod.cs index b583d56..401165b 100644 --- a/Enum/HttpMethod.cs +++ b/Enums/HttpMethod.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient; +namespace Yove.Http; public enum HttpMethod { diff --git a/Enum/HttpStatusCode.cs b/Enums/HttpStatusCode.cs similarity index 98% rename from Enum/HttpStatusCode.cs rename to Enums/HttpStatusCode.cs index 0913f41..7e0e100 100644 --- a/Enum/HttpStatusCode.cs +++ b/Enums/HttpStatusCode.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient; +namespace Yove.Http; public enum HttpStatusCode { diff --git a/Enum/HttpSystem.cs b/Enums/HttpSystem.cs similarity index 73% rename from Enum/HttpSystem.cs rename to Enums/HttpSystem.cs index 5879ecd..37deb42 100644 --- a/Enum/HttpSystem.cs +++ b/Enums/HttpSystem.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient; +namespace Yove.Http; public enum HttpSystem { diff --git a/Enum/ProxyType.cs b/Enums/ProxyType.cs similarity index 68% rename from Enum/ProxyType.cs rename to Enums/ProxyType.cs index a17e423..de828e8 100644 --- a/Enum/ProxyType.cs +++ b/Enums/ProxyType.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient; +namespace Yove.Http; public enum ProxyType { diff --git a/Events/DownloadEvent.cs b/Events/DownloadEvent.cs index 15aba6a..c3f54a2 100644 --- a/Events/DownloadEvent.cs +++ b/Events/DownloadEvent.cs @@ -1,6 +1,6 @@ using System; -namespace Yove.HttpClient.Events; +namespace Yove.Http.Events; public class DownloadEvent : EventArgs { diff --git a/Events/UploadEvent.cs b/Events/UploadEvent.cs index 144dbe9..9c75419 100644 --- a/Events/UploadEvent.cs +++ b/Events/UploadEvent.cs @@ -1,6 +1,6 @@ using System; -namespace Yove.HttpClient.Events; +namespace Yove.Http.Events; public class UploadEvent : EventArgs { diff --git a/Exceptions/HttpRequestException.cs b/Exceptions/HttpRequestException.cs index 13f809f..e05cacb 100644 --- a/Exceptions/HttpRequestException.cs +++ b/Exceptions/HttpRequestException.cs @@ -1,6 +1,6 @@ using System; -namespace Yove.HttpClient.Exceptions; +namespace Yove.Http.Exceptions; public class HttpRequestException : Exception { diff --git a/Exceptions/HttpResponseException.cs b/Exceptions/HttpResponseException.cs index fd56bef..a8b86a8 100644 --- a/Exceptions/HttpResponseException.cs +++ b/Exceptions/HttpResponseException.cs @@ -1,6 +1,6 @@ using System; -namespace Yove.HttpClient.Exceptions; +namespace Yove.Http.Exceptions; public class HttpResponseException : Exception { diff --git a/Exceptions/ProxyException.cs b/Exceptions/ProxyException.cs index f0b5150..2af9523 100644 --- a/Exceptions/ProxyException.cs +++ b/Exceptions/ProxyException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; -namespace Yove.HttpClient.Exceptions; +namespace Yove.Http.Exceptions; public class HttpProxyException : Exception { diff --git a/HttpClient.cs b/HttpClient.cs index 4635b30..73a434b 100644 --- a/HttpClient.cs +++ b/HttpClient.cs @@ -15,12 +15,12 @@ using Newtonsoft.Json.Linq; -using Yove.HttpClient.Events; -using Yove.HttpClient.Exceptions; -using Yove.HttpClient.Models; -using Yove.HttpClient.Proxy; +using Yove.Http.Events; +using Yove.Http.Exceptions; +using Yove.Http.Models; +using Yove.Http.Proxy; -namespace Yove.HttpClient; +namespace Yove.Http; [ConfigureAwait(false)] public class HttpClient : IDisposable @@ -29,7 +29,7 @@ public class HttpClient : IDisposable public NameValueCollection Headers = new(); public NameValueCollection TempHeaders = new(); - public NameValueCollection Cookie { get; set; } + public NameValueCollection Cookies { get; set; } public string BaseUrl { get; set; } public string Username { get; set; } @@ -47,7 +47,7 @@ public class HttpClient : IDisposable public bool EnableAutoRedirect { get; set; } = true; public bool RedirectOnlyIfOtherDomain { get; set; } public bool EnableProtocolError { get; set; } = true; - public bool EnableCookie { get; set; } = true; + public bool EnableCookies { get; set; } = true; public bool EnableReconnect { get; set; } = true; public bool HasConnection { get; set; } public bool IsDisposed { get; set; } @@ -142,8 +142,8 @@ private bool _canReconnect public HttpClient() { - if (EnableCookie && Cookie == null) - Cookie = new NameValueCollection(); + if (EnableCookies && Cookies == null) + Cookies = new NameValueCollection(); } public HttpClient(CancellationToken token) : this() @@ -158,8 +158,8 @@ public HttpClient(string baseUrl) { BaseUrl = baseUrl; - if (EnableCookie && Cookie == null) - Cookie = new NameValueCollection(); + if (EnableCookies && Cookies == null) + Cookies = new NameValueCollection(); } public HttpClient(string baseUrl, CancellationToken token) : this(baseUrl) @@ -271,8 +271,8 @@ public async Task Raw(HttpMethod method, string url, HttpContent b if (!url.StartsWith("https://") && !url.StartsWith("http://") && !string.IsNullOrEmpty(BaseUrl)) url = $"{BaseUrl.TrimEnd('/')}/{url}"; - if (!EnableCookie && Cookie != null) - Cookie = null; + if (!EnableCookies && Cookies != null) + Cookies = null; Method = method; Content = body; @@ -561,12 +561,12 @@ private string GenerateHeaders(HttpMethod method, long contentLength = 0, string rawHeaders["Connection"] = "close"; } - if (Cookie?.Count > 0) + if (Cookies?.Count > 0) { string cookieBuilder = string.Empty; - foreach (string cookie in Cookie) - cookieBuilder += $"{cookie}={Cookie[cookie]}; "; + foreach (string cookie in Cookies) + cookieBuilder += $"{cookie}={Cookies[cookie]}; "; rawHeaders["Cookie"] = cookieBuilder.TrimEnd(); } @@ -603,8 +603,8 @@ public void AddRawCookie(string source) if (string.IsNullOrEmpty(source)) throw new NullReferenceException("Value is null or empty."); - if (!EnableCookie) - throw new HttpRequestException("Cookie is disabled."); + if (!EnableCookies) + throw new HttpRequestException("Cookies is disabled."); if (source.Contains("Cookie:", StringComparison.OrdinalIgnoreCase)) source = source.Replace("Cookie:", "", StringComparison.OrdinalIgnoreCase).Trim(); @@ -615,7 +615,7 @@ public void AddRawCookie(string source) string value = cookie.Split('=')[1]?.Trim(); if (key != null && value != null) - Cookie[key] = value; + Cookies[key] = value; } } diff --git a/HttpResponse.cs b/HttpResponse.cs index 722ff13..ab19ec7 100644 --- a/HttpResponse.cs +++ b/HttpResponse.cs @@ -8,10 +8,10 @@ using Fody; -using Yove.HttpClient.Exceptions; -using Yove.HttpClient.Models; +using Yove.Http.Exceptions; +using Yove.Http.Models; -namespace Yove.HttpClient; +namespace Yove.Http; [ConfigureAwait(false)] public class HttpResponse @@ -20,7 +20,7 @@ public class HttpResponse private Receiver _content { get; } public NameValueCollection Headers = new(); - public NameValueCollection Cookie = new(); + public NameValueCollection Cookies = new(); public List RedirectHistory = new(); public string ContentType { get; } @@ -196,10 +196,10 @@ internal HttpResponse(HttpClient httpClient) if (!string.IsNullOrEmpty(cookieName)) { - Cookie[cookieName] = cookieValue; + Cookies[cookieName] = cookieValue; - if (_request.EnableCookie && _request.Cookie != null) - _request.Cookie[cookieName] = cookieValue; + if (_request.EnableCookies && _request.Cookies != null) + _request.Cookies[cookieName] = cookieValue; } } else @@ -252,8 +252,7 @@ internal async Task GetBodyContent() if (outputStream == null && ContentLength.HasValue) outputStream = await ReceiveStandartBody(false); - if (outputStream == null) - outputStream = await ReceiveUnsizeBody(_request.CommonStream); + outputStream ??= await ReceiveUnsizeBody(_request.CommonStream); if (outputStream != null && Content.Stream.Length > 0) Content.Stream.Position = 0; diff --git a/HttpUtils.cs b/HttpUtils.cs index 348e72c..17ef643 100644 --- a/HttpUtils.cs +++ b/HttpUtils.cs @@ -1,7 +1,7 @@ using System; using System.Linq; -namespace Yove.HttpClient; +namespace Yove.Http; public static class HttpUtils { diff --git a/Models/RedirectHistory.cs b/Models/RedirectHistory.cs index bf2e266..14c4ba4 100644 --- a/Models/RedirectHistory.cs +++ b/Models/RedirectHistory.cs @@ -1,4 +1,4 @@ -namespace Yove.HttpClient.Models; +namespace Yove.Http.Models; public record RedirectItem { diff --git a/Proxy/HttpProxy.cs b/Proxy/HttpProxy.cs new file mode 100644 index 0000000..9f946b0 --- /dev/null +++ b/Proxy/HttpProxy.cs @@ -0,0 +1,48 @@ +using System; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +using Yove.Http.Exceptions; + +namespace Yove.Http.Proxy; + +public class HttpProxy : ProxyClient +{ + public HttpProxy() { } + public HttpProxy(string host, int port, ProxyType type) : this($"{host}:{port}", type) { } + public HttpProxy(string proxy, ProxyType type) : base(proxy, type) { } + + private protected override async Task SendCommand(NetworkStream networkStream, string destinationHost, int destinationPort) + { + if (destinationPort == 80) + return ConnectionResult.OK; + + byte[] requestBytes = Encoding.ASCII.GetBytes($"CONNECT {destinationHost}:{destinationPort} HTTP/1.1\r\n\r\n"); + + networkStream.Write(requestBytes, 0, requestBytes.Length); + + await WaitStream(networkStream); + + StringBuilder responseBuilder = new(); + + byte[] buffer = new byte[100]; + + while (networkStream.DataAvailable) + { + int readBytes = networkStream.Read(buffer, 0, 100); + + responseBuilder.Append(Encoding.ASCII.GetString(buffer, 0, readBytes)); + } + + if (responseBuilder.Length == 0) + throw new HttpProxyException("Received empty response."); + + HttpStatusCode statusCode = (HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), HttpUtils.Parser(" ", responseBuilder.ToString(), " ")?.Trim()); + + if (statusCode != HttpStatusCode.OK) + return ConnectionResult.InvalidProxyResponse; + + return ConnectionResult.OK; + } +} diff --git a/Proxy/ProxyClient.cs b/Proxy/ProxyClient.cs index ee3efbc..084ed52 100644 --- a/Proxy/ProxyClient.cs +++ b/Proxy/ProxyClient.cs @@ -1,18 +1,17 @@ using System; using System.Net; using System.Net.Sockets; -using System.Text; using System.Threading; using System.Threading.Tasks; using Fody; -using Yove.HttpClient.Exceptions; +using Yove.Http.Exceptions; -namespace Yove.HttpClient.Proxy; +namespace Yove.Http.Proxy; [ConfigureAwait(false)] -public class ProxyClient +public abstract class ProxyClient { public string Host { get; set; } public int Port { get; set; } @@ -21,15 +20,15 @@ public class ProxyClient public int TimeOut { get; set; } = 60000; public int ReadWriteTimeOut { get; set; } = 60000; - private const byte ADDRESS_TYPE_IPV4 = 0x01; - private const byte ADDRESS_TYPE_IPV6 = 0x04; - private const byte ADDRESS_TYPE_DOMAIN_NAME = 0x03; + private protected const byte ADDRESS_TYPE_IPV4 = 0x01; + private protected const byte ADDRESS_TYPE_IPV6 = 0x04; + private protected const byte ADDRESS_TYPE_DOMAIN_NAME = 0x03; - public ProxyClient() { } + protected ProxyClient() { } - public ProxyClient(string host, int port, ProxyType type) : this($"{host}:{port}", type) { } + protected ProxyClient(string host, int port, ProxyType type) : this($"{host}:{port}", type) { } - public ProxyClient(string proxy, ProxyType type) + protected ProxyClient(string proxy, ProxyType type) { if (string.IsNullOrEmpty(proxy) || !proxy.Contains(':')) throw new NullReferenceException("Proxy is null or empty or invalid type."); @@ -93,132 +92,9 @@ internal async Task CreateConnection(string destinationHost, int dest return tcpClient; } - private async Task SendCommand(NetworkStream networkStream, string destinationHost, int destinationPort) - { - return Type switch - { - ProxyType.Http => await SendHttp(networkStream, destinationHost, destinationPort), - ProxyType.Socks4 => await SendSocks4(networkStream, destinationHost, destinationPort), - ProxyType.Socks5 => await SendSocks5(networkStream, destinationHost, destinationPort), - _ => throw new HttpProxyException("Unsupported proxy type."), - }; - } - - private async Task SendHttp(NetworkStream networkStream, string destinationHost, int destinationPort) - { - if (destinationPort == 80) - return ConnectionResult.OK; - - byte[] requestBytes = Encoding.ASCII.GetBytes($"CONNECT {destinationHost}:{destinationPort} HTTP/1.1\r\n\r\n"); - - networkStream.Write(requestBytes, 0, requestBytes.Length); - - await WaitStream(networkStream); - - StringBuilder responseBuilder = new(); - - byte[] buffer = new byte[100]; - - while (networkStream.DataAvailable) - { - int readBytes = networkStream.Read(buffer, 0, 100); - - responseBuilder.Append(Encoding.ASCII.GetString(buffer, 0, readBytes)); - } - - if (responseBuilder.Length == 0) - throw new HttpProxyException("Received empty response."); - - HttpStatusCode statusCode = (HttpStatusCode)Enum.Parse(typeof(HttpStatusCode), HttpUtils.Parser(" ", responseBuilder.ToString(), " ")?.Trim()); - - if (statusCode != HttpStatusCode.OK) - return ConnectionResult.InvalidProxyResponse; - - return ConnectionResult.OK; - } - - private async Task SendSocks4(NetworkStream networkStream, string destinationHost, int destinationPort) - { - byte addressType = GetAddressType(destinationHost); - - if (addressType == ADDRESS_TYPE_DOMAIN_NAME) - destinationHost = GetHost(destinationHost).ToString(); - - byte[] address = GetIPAddressBytes(destinationHost); - byte[] port = GetPortBytes(destinationPort); - byte[] userId = Array.Empty(); - - byte[] request = new byte[9]; - byte[] response = new byte[8]; - - request[0] = 4; - request[1] = 0x01; - address.CopyTo(request, 4); - port.CopyTo(request, 2); - userId.CopyTo(request, 8); - request[8] = 0x00; - - networkStream.Write(request, 0, request.Length); - - await WaitStream(networkStream); - - networkStream.Read(response, 0, response.Length); - - if (response[1] != 0x5a) - return ConnectionResult.InvalidProxyResponse; - - return ConnectionResult.OK; - } + private protected abstract Task SendCommand(NetworkStream networkStream, string destinationHost, int destinationPort); - private async Task SendSocks5(NetworkStream networkStream, string destinationHost, int destinationPort) - { - byte[] response = new byte[255]; - byte[] auth = new byte[3]; - - auth[0] = 5; - auth[1] = 1; - auth[2] = 0; - - networkStream.Write(auth, 0, auth.Length); - - await WaitStream(networkStream); - - networkStream.Read(response, 0, response.Length); - - if (response[1] != 0x00) - return ConnectionResult.InvalidProxyResponse; - - byte addressType = GetAddressType(destinationHost); - - if (addressType == ADDRESS_TYPE_DOMAIN_NAME) - destinationHost = GetHost(destinationHost).ToString(); - - byte[] address = GetAddressBytes(addressType, destinationHost); - byte[] port = GetPortBytes(destinationPort); - - byte[] request = new byte[4 + address.Length + 2]; - - request[0] = 5; - request[1] = 0x01; - request[2] = 0x00; - request[3] = addressType; - - address.CopyTo(request, 4); - port.CopyTo(request, 4 + address.Length); - - networkStream.Write(request, 0, request.Length); - - await WaitStream(networkStream); - - networkStream.Read(response, 0, response.Length); - - if (response[1] != 0x00) - return ConnectionResult.InvalidProxyResponse; - - return ConnectionResult.OK; - } - - private async Task WaitStream(NetworkStream networkStream) + private protected async Task WaitStream(NetworkStream networkStream) { int sleep = 0; int delay = (networkStream.ReadTimeout < 10) ? 10 : networkStream.ReadTimeout; @@ -237,7 +113,7 @@ private async Task WaitStream(NetworkStream networkStream) } } - private static IPAddress GetHost(string host) + private protected static IPAddress GetHost(string host) { if (IPAddress.TryParse(host, out IPAddress ip)) return ip; @@ -245,26 +121,7 @@ private static IPAddress GetHost(string host) return Dns.GetHostAddresses(host)[0]; } - private static byte[] GetAddressBytes(byte addressType, string host) - { - switch (addressType) - { - case ADDRESS_TYPE_IPV4: - case ADDRESS_TYPE_IPV6: - return IPAddress.Parse(host).GetAddressBytes(); - case ADDRESS_TYPE_DOMAIN_NAME: - byte[] bytes = new byte[host.Length + 1]; - - bytes[0] = (byte)host.Length; - Encoding.ASCII.GetBytes(host).CopyTo(bytes, 1); - - return bytes; - default: - return null; - } - } - - private static byte GetAddressType(string host) + private protected static byte GetAddressType(string host) { if (IPAddress.TryParse(host, out IPAddress ip)) { @@ -277,20 +134,7 @@ private static byte GetAddressType(string host) return ADDRESS_TYPE_DOMAIN_NAME; } - private static byte[] GetIPAddressBytes(string destinationHost) - { - if (!IPAddress.TryParse(destinationHost, out IPAddress address)) - { - IPAddress[] ipAddresses = Dns.GetHostAddresses(destinationHost); - - if (ipAddresses.Length > 0) - address = ipAddresses[0]; - } - - return address?.GetAddressBytes(); - } - - private static byte[] GetPortBytes(int port) + private protected static byte[] GetPortBytes(int port) { byte[] bytes = new byte[2]; diff --git a/Proxy/Socks4Proxy.cs b/Proxy/Socks4Proxy.cs new file mode 100644 index 0000000..01c24b7 --- /dev/null +++ b/Proxy/Socks4Proxy.cs @@ -0,0 +1,62 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; + +using Yove.Http; +using Yove.Http.Proxy; + +namespace Yove.Http.Proxy; + +public class Socks4Proxy : ProxyClient +{ + public Socks4Proxy() { } + public Socks4Proxy(string host, int port, ProxyType type) : this($"{host}:{port}", type) { } + public Socks4Proxy(string proxy, ProxyType type) : base(proxy, type) { } + + private protected override async Task SendCommand(NetworkStream networkStream, string destinationHost, int destinationPort) + { + byte addressType = GetAddressType(destinationHost); + + if (addressType == ADDRESS_TYPE_DOMAIN_NAME) + destinationHost = GetHost(destinationHost).ToString(); + + byte[] address = GetIPAddressBytes(destinationHost); + byte[] port = GetPortBytes(destinationPort); + byte[] userId = Array.Empty(); + + byte[] request = new byte[9]; + byte[] response = new byte[8]; + + request[0] = 4; + request[1] = 0x01; + address.CopyTo(request, 4); + port.CopyTo(request, 2); + userId.CopyTo(request, 8); + request[8] = 0x00; + + networkStream.Write(request, 0, request.Length); + + await WaitStream(networkStream); + + networkStream.Read(response, 0, response.Length); + + if (response[1] != 0x5a) + return ConnectionResult.InvalidProxyResponse; + + return ConnectionResult.OK; + } + + private static byte[] GetIPAddressBytes(string destinationHost) + { + if (!IPAddress.TryParse(destinationHost, out IPAddress address)) + { + IPAddress[] ipAddresses = Dns.GetHostAddresses(destinationHost); + + if (ipAddresses.Length > 0) + address = ipAddresses[0]; + } + + return address?.GetAddressBytes(); + } +} diff --git a/Proxy/Socks5Proxy.cs b/Proxy/Socks5Proxy.cs new file mode 100644 index 0000000..53dfca2 --- /dev/null +++ b/Proxy/Socks5Proxy.cs @@ -0,0 +1,83 @@ +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +using Yove.Http; +using Yove.Http.Proxy; + +namespace Yove.Http.Proxy; + +public class Socks5Proxy : ProxyClient +{ + public Socks5Proxy() { } + public Socks5Proxy(string host, int port, ProxyType type) : this($"{host}:{port}", type) { } + public Socks5Proxy(string proxy, ProxyType type) : base(proxy, type) { } + + private protected override async Task SendCommand(NetworkStream networkStream, string destinationHost, int destinationPort) + { + byte[] response = new byte[255]; + byte[] auth = new byte[3]; + + auth[0] = 5; + auth[1] = 1; + auth[2] = 0; + + networkStream.Write(auth, 0, auth.Length); + + await WaitStream(networkStream); + + networkStream.Read(response, 0, response.Length); + + if (response[1] != 0x00) + return ConnectionResult.InvalidProxyResponse; + + byte addressType = GetAddressType(destinationHost); + + if (addressType == ADDRESS_TYPE_DOMAIN_NAME) + destinationHost = GetHost(destinationHost).ToString(); + + byte[] address = GetAddressBytes(addressType, destinationHost); + byte[] port = GetPortBytes(destinationPort); + + byte[] request = new byte[4 + address.Length + 2]; + + request[0] = 5; + request[1] = 0x01; + request[2] = 0x00; + request[3] = addressType; + + address.CopyTo(request, 4); + port.CopyTo(request, 4 + address.Length); + + networkStream.Write(request, 0, request.Length); + + await WaitStream(networkStream); + + networkStream.Read(response, 0, response.Length); + + if (response[1] != 0x00) + return ConnectionResult.InvalidProxyResponse; + + return ConnectionResult.OK; + } + + private static byte[] GetAddressBytes(byte addressType, string host) + { + switch (addressType) + { + case ADDRESS_TYPE_IPV4: + case ADDRESS_TYPE_IPV6: + return IPAddress.Parse(host).GetAddressBytes(); + case ADDRESS_TYPE_DOMAIN_NAME: + byte[] bytes = new byte[host.Length + 1]; + + bytes[0] = (byte)host.Length; + Encoding.ASCII.GetBytes(host).CopyTo(bytes, 1); + + return bytes; + default: + return null; + } + } +} diff --git a/README.md b/README.md index 0854d93..19545a9 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Yove.Http | Http Client / Http Framework -[![NuGet version](https://badge.fury.io/nu/Yove.HttpClient.svg)](https://badge.fury.io/nu/Yove.HttpClient) -[![Downloads](https://img.shields.io/nuget/dt/Yove.HttpClient.svg)](https://www.nuget.org/packages/Yove.HttpClient) +[![NuGet version](https://badge.fury.io/nu/Yove.Http.svg)](https://badge.fury.io/nu/Yove.Http) +[![Downloads](https://img.shields.io/nuget/dt/Yove.Http.svg)](https://www.nuget.org/packages/Yove.Http) [![Target](https://img.shields.io/badge/.NET%20Standard-2.0-green.svg)](https://docs.microsoft.com/ru-ru/dotnet/standard/net-standard) -Nuget: https://www.nuget.org/packages/Yove.HttpClient +Nuget: https://www.nuget.org/packages/Yove.Http ``` -Install-Package Yove.HttpClient +Install-Package Yove.Http ``` ``` -dotnet add package Yove.HttpClient +dotnet add package Yove.Http ``` --- @@ -23,7 +23,7 @@ using(HttpClient client = new HttpClient { Authorization = $"Bearer {Token}", // Add Authorization header EnableAutoRedirect = false, // Disable automatic redirection if the server responded with a Location header - EnableCookie = false, // Disable cookie + EnableCookies = false, // Disable cookies EnableProtocolError = false, // Disable exceptions associated with server response EnableReconnect = false, // Disable reconnection in case of connection errors or data reading ReconnectDelay = 1000, // Delay in attempting a new connection @@ -139,4 +139,10 @@ Supports both default requests and WebDAV | COPY | Copy from one URI to another | | MOVE | Move from one URI to another | | LOCK | Put a lock on the object | -| UNLOCK | Unlock a resource | \ No newline at end of file +| UNLOCK | Unlock a resource | + +--- + +### TODO + +- [ ] Proxy Authorization \ No newline at end of file diff --git a/Receiver.cs b/Receiver.cs index 0c3d2cb..1eaefac 100644 --- a/Receiver.cs +++ b/Receiver.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text; -namespace Yove.HttpClient; +namespace Yove.Http; internal class Receiver { diff --git a/StreamWrapper.cs b/StreamWrapper.cs index b14bb1b..bc09a09 100644 --- a/StreamWrapper.cs +++ b/StreamWrapper.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Yove.HttpClient; +namespace Yove.Http; internal class StreamWrapper : Stream { diff --git a/Yove.Http.csproj b/Yove.Http.csproj index 521b170..0f900ac 100644 --- a/Yove.Http.csproj +++ b/Yove.Http.csproj @@ -5,8 +5,8 @@ true true snupkg - Yove.HttpClient - 1.6.1 + Yove.Http + 1.6.2 Sunny en-US, ru-RU Http Client for .Net | Http, Socks4, Socks5 client @@ -18,10 +18,10 @@ - - + + - + \ No newline at end of file