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;
+ }
}
}