From 8422fa8043f6d3571d8174d76787036dfd82a93a Mon Sep 17 00:00:00 2001 From: "Gui.H" Date: Fri, 11 Nov 2022 22:54:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=85=BC=E5=AE=B9ne?= =?UTF-8?q?tcore3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 40 +++- .../Extensions/ServicesExtensions.cs | 33 ++- .../FastTunnel.Core.Client.csproj | 7 +- FastTunnel.Core.Client/FastTunnelClient.cs | 6 + .../Handlers/IClientHandler.cs | 24 ++- FastTunnel.Core.Client/IClientConfig.cs | 15 +- .../Sockets/DnsSocketFactory.cs | 19 +- .../Extensions/ObjectExtensions.cs | 18 +- FastTunnel.Core/Utilitys/WebSocketUtility.cs | 191 +++++++++--------- 9 files changed, 211 insertions(+), 142 deletions(-) diff --git a/.editorconfig b/.editorconfig index 1c59ad5..b8f1d20 100644 --- a/.editorconfig +++ b/.editorconfig @@ -50,7 +50,7 @@ csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true # Namespace settings -csharp_style_namespace_declarations = file_scoped +csharp_style_namespace_declarations = file_scoped:warning [*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}] indent_size = 2 @@ -218,6 +218,29 @@ dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_property = false:suggestion dotnet_style_qualification_for_method = false:silent dotnet_style_qualification_for_event = false:silent +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_code_quality_unused_parameters = all:suggestion +dotnet_style_readonly_field = true:suggestion +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion [**/{test,samples,perf}/**.{cs,vb}] # CA1018: Mark attributes with AttributeUsageAttribute @@ -324,6 +347,21 @@ csharp_style_expression_bodied_accessors = true:silent csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent csharp_style_conditional_delegate_call = true:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion [*.vb] #### ʽ #### diff --git a/FastTunnel.Core.Client/Extensions/ServicesExtensions.cs b/FastTunnel.Core.Client/Extensions/ServicesExtensions.cs index a9bf949..84f15f1 100644 --- a/FastTunnel.Core.Client/Extensions/ServicesExtensions.cs +++ b/FastTunnel.Core.Client/Extensions/ServicesExtensions.cs @@ -4,33 +4,30 @@ // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // Copyright (c) 2019 Gui.H -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using FastTunnel.Core.Config; using FastTunnel.Core.Handlers.Client; using FastTunnel.Core.Services; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace FastTunnel.Core.Client.Extensions; -public static class ServicesExtensions +namespace FastTunnel.Core.Client.Extensions { - /// - /// 客户端依赖及HostedService - /// - /// - public static void AddFastTunnelClient(this IServiceCollection services, IConfigurationSection configurationSection) + public static class ServicesExtensions { - services.Configure(configurationSection); + /// + /// 客户端依赖及HostedService + /// + /// + public static void AddFastTunnelClient(this IServiceCollection services, IConfigurationSection configurationSection) + { + services.Configure(configurationSection); - services.AddTransient() - .AddSingleton() - .AddSingleton(); + services.AddTransient() + .AddSingleton() + .AddSingleton(); + + services.AddHostedService(); + } - services.AddHostedService(); } - } diff --git a/FastTunnel.Core.Client/FastTunnel.Core.Client.csproj b/FastTunnel.Core.Client/FastTunnel.Core.Client.csproj index c790d86..39b4643 100644 --- a/FastTunnel.Core.Client/FastTunnel.Core.Client.csproj +++ b/FastTunnel.Core.Client/FastTunnel.Core.Client.csproj @@ -1,10 +1,10 @@ - + 2.1.1 - net6.0 - enable + netcoreapp3.1;net5.0;net6.0;net7.0; enable + preview @@ -28,6 +28,7 @@ + diff --git a/FastTunnel.Core.Client/FastTunnelClient.cs b/FastTunnel.Core.Client/FastTunnelClient.cs index d1f8820..0f94b99 100644 --- a/FastTunnel.Core.Client/FastTunnelClient.cs +++ b/FastTunnel.Core.Client/FastTunnelClient.cs @@ -140,7 +140,13 @@ public class FastTunnelClient : IFastTunnelClient throw new Exception($"未处理的消息:cmd={cmd}"); } +#if NETCOREAPP3_1 + var content = Encoding.UTF8.GetString(line.Slice(1).ToArray()); +#endif + +#if NET5_0_OR_GREATER var content = Encoding.UTF8.GetString(line.Slice(1)); +#endif handler.HandlerMsgAsync(this, content, cancellationToken); } catch (Exception ex) diff --git a/FastTunnel.Core.Client/Handlers/IClientHandler.cs b/FastTunnel.Core.Client/Handlers/IClientHandler.cs index f38df91..b3de45f 100644 --- a/FastTunnel.Core.Client/Handlers/IClientHandler.cs +++ b/FastTunnel.Core.Client/Handlers/IClientHandler.cs @@ -13,16 +13,18 @@ using System.Text; using System.Threading.Tasks; using System.Threading; -namespace FastTunnel.Core.Handlers.Client; - -public interface IClientHandler +namespace FastTunnel.Core.Handlers.Client { - /// - /// 处理消息 - /// - /// - /// - /// - /// - Task HandlerMsgAsync(FastTunnelClient cleint, string msg, CancellationToken cancellationToken); + public interface IClientHandler + { + /// + /// 处理消息 + /// + /// + /// + /// + /// + Task HandlerMsgAsync(FastTunnelClient cleint, string msg, CancellationToken cancellationToken); + } + } diff --git a/FastTunnel.Core.Client/IClientConfig.cs b/FastTunnel.Core.Client/IClientConfig.cs index 8874f5b..8f4256e 100644 --- a/FastTunnel.Core.Client/IClientConfig.cs +++ b/FastTunnel.Core.Client/IClientConfig.cs @@ -12,13 +12,16 @@ using System.Threading.Tasks; using FastTunnel.Core.Config; using FastTunnel.Core.Models; -namespace FastTunnel.Core.Client; - -public interface IClientConfig +namespace FastTunnel.Core.Client { - public SuiDaoServer Server { get; set; } + public interface IClientConfig + { + public SuiDaoServer Server { get; set; } - public IEnumerable Webs { get; set; } + public IEnumerable Webs { get; set; } + + public IEnumerable Forwards { get; set; } + } - public IEnumerable Forwards { get; set; } } + diff --git a/FastTunnel.Core.Client/Sockets/DnsSocketFactory.cs b/FastTunnel.Core.Client/Sockets/DnsSocketFactory.cs index 7d74743..e85f257 100644 --- a/FastTunnel.Core.Client/Sockets/DnsSocketFactory.cs +++ b/FastTunnel.Core.Client/Sockets/DnsSocketFactory.cs @@ -13,15 +13,18 @@ using System.Net.Sockets; using System.Text; using System.Threading.Tasks; -namespace FastTunnel.Core.Client.Sockets; - -public class DnsSocketFactory +namespace FastTunnel.Core.Client.Sockets { - public static async Task ConnectAsync(string host, int port) + + public class DnsSocketFactory { - var Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - var dnsEndPoint = new DnsEndPoint(host, port); - await Socket.ConnectAsync(dnsEndPoint); - return Socket; + public static async Task ConnectAsync(string host, int port) + { + var Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + var dnsEndPoint = new DnsEndPoint(host, port); + await Socket.ConnectAsync(dnsEndPoint); + return Socket; + } } + } diff --git a/FastTunnel.Core/Extensions/ObjectExtensions.cs b/FastTunnel.Core/Extensions/ObjectExtensions.cs index 5c17e0e..12aab42 100644 --- a/FastTunnel.Core/Extensions/ObjectExtensions.cs +++ b/FastTunnel.Core/Extensions/ObjectExtensions.cs @@ -3,13 +3,17 @@ // You may obtain a copy of the License at // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // Copyright (c) 2019 Gui.H - +#if NETCOREAPP3_1_OR_GREATER using System.Text.Json; +#else + +#endif namespace FastTunnel.Core.Extensions { public static class ObjectExtensions { +#if NETCOREAPP3_1_OR_GREATER public static string ToJson(this object message) { if (message == null) @@ -20,5 +24,17 @@ namespace FastTunnel.Core.Extensions var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; return JsonSerializer.Serialize(message, message.GetType(), jsonOptions); } +#else + public static string ToJson(this object message) + { + if (message == null) + { + return null; + } + + var jsonOptions = new JsonSerializerOptions { WriteIndented = false }; + return JsonSerializer.Serialize(message, message.GetType(), jsonOptions); + } +#endif } } diff --git a/FastTunnel.Core/Utilitys/WebSocketUtility.cs b/FastTunnel.Core/Utilitys/WebSocketUtility.cs index 89e599e..53c0fa9 100644 --- a/FastTunnel.Core/Utilitys/WebSocketUtility.cs +++ b/FastTunnel.Core/Utilitys/WebSocketUtility.cs @@ -12,121 +12,124 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -namespace FastTunnel.Core.Utilitys; - -public class WebSocketUtility +namespace FastTunnel.Core.Utilitys { - private readonly WebSocket webSocket; - public WebSocketUtility(WebSocket webSocket, Action, CancellationToken> processLine) + + public class WebSocketUtility { - this.webSocket = webSocket; - ProcessLine = processLine; - } + private readonly WebSocket webSocket; - public Action, CancellationToken> ProcessLine { get; } - - public async Task ProcessLinesAsync(CancellationToken cancellationToken) - { - var pipe = new Pipe(); - var writing = FillPipeAsync(webSocket, pipe.Writer, cancellationToken); - var reading = ReadPipeAsync(pipe.Reader, cancellationToken); - - await Task.WhenAll(reading, writing); - } - - /// - /// 读取socket收到的消息写入Pipe - /// - /// - /// - /// - /// - /// - private async Task FillPipeAsync(WebSocket socket, PipeWriter writer, CancellationToken cancellationToken) - { - const int minimumBufferSize = 512; - - while (true) + public WebSocketUtility(WebSocket webSocket, Action, CancellationToken> processLine) { - // Allocate at least 512 bytes from the PipeWriter. - var memory = writer.GetMemory(minimumBufferSize); + this.webSocket = webSocket; + ProcessLine = processLine; + } - try + public Action, CancellationToken> ProcessLine { get; } + + public async Task ProcessLinesAsync(CancellationToken cancellationToken) + { + var pipe = new Pipe(); + var writing = FillPipeAsync(webSocket, pipe.Writer, cancellationToken); + var reading = ReadPipeAsync(pipe.Reader, cancellationToken); + + await Task.WhenAll(reading, writing); + } + + /// + /// 读取socket收到的消息写入Pipe + /// + /// + /// + /// + /// + /// + private async Task FillPipeAsync(WebSocket socket, PipeWriter writer, CancellationToken cancellationToken) + { + const int minimumBufferSize = 512; + + while (true) { - var bytesRead = await socket.ReceiveAsync(memory, cancellationToken); - if (bytesRead.Count == 0 || bytesRead.EndOfMessage || bytesRead.MessageType == WebSocketMessageType.Close) + // Allocate at least 512 bytes from the PipeWriter. + var memory = writer.GetMemory(minimumBufferSize); + + try + { + var bytesRead = await socket.ReceiveAsync(memory, cancellationToken); + if (bytesRead.Count == 0 || bytesRead.EndOfMessage || bytesRead.MessageType == WebSocketMessageType.Close) + { + break; + } + // Tell the PipeWriter how much was read from the Socket. + writer.Advance(bytesRead.Count); + } + catch (Exception) + { + break; + } + + // Make the data available to the PipeReader. + var result = await writer.FlushAsync(cancellationToken); + + if (result.IsCompleted) { break; } - // Tell the PipeWriter how much was read from the Socket. - writer.Advance(bytesRead.Count); - } - catch (Exception) - { - break; } - // Make the data available to the PipeReader. - var result = await writer.FlushAsync(cancellationToken); - - if (result.IsCompleted) - { - break; - } + // By completing PipeWriter, tell the PipeReader that there's no more data coming. + await writer.CompleteAsync(); } - // By completing PipeWriter, tell the PipeReader that there's no more data coming. - await writer.CompleteAsync(); - } - - /// - /// 从Pipe中读取收到的消息 - /// - /// - /// - /// - private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken) - { - while (true) + /// + /// 从Pipe中读取收到的消息 + /// + /// + /// + /// + private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken) { - var result = await reader.ReadAsync(cancellationToken); - var buffer = result.Buffer; - - while (TryReadLine(ref buffer, out ReadOnlySequence line)) + while (true) { - // Process the line. - ProcessLine(line, cancellationToken); + var result = await reader.ReadAsync(cancellationToken); + var buffer = result.Buffer; + + while (TryReadLine(ref buffer, out ReadOnlySequence line)) + { + // Process the line. + ProcessLine(line, cancellationToken); + } + + // Tell the PipeReader how much of the buffer has been consumed. + reader.AdvanceTo(buffer.Start, buffer.End); + + // Stop reading if there's no more data coming. + if (result.IsCompleted) + { + break; + } } - // Tell the PipeReader how much of the buffer has been consumed. - reader.AdvanceTo(buffer.Start, buffer.End); - - // Stop reading if there's no more data coming. - if (result.IsCompleted) - { - break; - } + // Mark the PipeReader as complete. + await reader.CompleteAsync(); } - // Mark the PipeReader as complete. - await reader.CompleteAsync(); - } - - bool TryReadLine(ref ReadOnlySequence buffer, out ReadOnlySequence line) - { - // Look for a EOL in the buffer. - SequencePosition? position = buffer.PositionOf((byte)'\n'); - - if (position == null) + bool TryReadLine(ref ReadOnlySequence buffer, out ReadOnlySequence line) { - line = default; - return false; - } + // Look for a EOL in the buffer. + SequencePosition? position = buffer.PositionOf((byte)'\n'); - // Skip the line + the \n. - line = buffer.Slice(0, position.Value); - buffer = buffer.Slice(buffer.GetPosition(1, position.Value)); - return true; + if (position == null) + { + line = default; + return false; + } + + // Skip the line + the \n. + line = buffer.Slice(0, position.Value); + buffer = buffer.Slice(buffer.GetPosition(1, position.Value)); + return true; + } } }