mirror of
https://github.com/FastTunnel/FastTunnel.git
synced 2024-09-20 23:48:30 +08:00
客户端兼容netcore3
This commit is contained in:
parent
839861fed9
commit
8422fa8043
|
@ -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]
|
||||
#### ÃüÃûÑùʽ ####
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 客户端依赖及HostedService
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
public static void AddFastTunnelClient(this IServiceCollection services, IConfigurationSection configurationSection)
|
||||
public static class ServicesExtensions
|
||||
{
|
||||
services.Configure<DefaultClientConfig>(configurationSection);
|
||||
/// <summary>
|
||||
/// 客户端依赖及HostedService
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
public static void AddFastTunnelClient(this IServiceCollection services, IConfigurationSection configurationSection)
|
||||
{
|
||||
services.Configure<DefaultClientConfig>(configurationSection);
|
||||
|
||||
services.AddTransient<IFastTunnelClient, FastTunnelClient>()
|
||||
.AddSingleton<LogHandler>()
|
||||
.AddSingleton<SwapHandler>();
|
||||
services.AddTransient<IFastTunnelClient, FastTunnelClient>()
|
||||
.AddSingleton<LogHandler>()
|
||||
.AddSingleton<SwapHandler>();
|
||||
|
||||
services.AddHostedService<ServiceFastTunnelClient>();
|
||||
}
|
||||
|
||||
services.AddHostedService<ServiceFastTunnelClient>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>2.1.1</Version>
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0;net7.0;</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -28,6 +28,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
|
||||
<PackageReference Include="System.IO.Pipelines" Version="5.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理消息
|
||||
/// </summary>
|
||||
/// <param name="cleint"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task HandlerMsgAsync(FastTunnelClient cleint, string msg, CancellationToken cancellationToken);
|
||||
public interface IClientHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理消息
|
||||
/// </summary>
|
||||
/// <param name="cleint"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task HandlerMsgAsync(FastTunnelClient cleint, string msg, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<WebConfig> Webs { get; set; }
|
||||
public IEnumerable<WebConfig> Webs { get; set; }
|
||||
|
||||
public IEnumerable<ForwardConfig> Forwards { get; set; }
|
||||
}
|
||||
|
||||
public IEnumerable<ForwardConfig> Forwards { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Socket> 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<Socket> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ReadOnlySequence<byte>, CancellationToken> processLine)
|
||||
|
||||
public class WebSocketUtility
|
||||
{
|
||||
this.webSocket = webSocket;
|
||||
ProcessLine = processLine;
|
||||
}
|
||||
private readonly WebSocket webSocket;
|
||||
|
||||
public Action<ReadOnlySequence<byte>, 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取socket收到的消息写入Pipe
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private async Task FillPipeAsync(WebSocket socket, PipeWriter writer, CancellationToken cancellationToken)
|
||||
{
|
||||
const int minimumBufferSize = 512;
|
||||
|
||||
while (true)
|
||||
public WebSocketUtility(WebSocket webSocket, Action<ReadOnlySequence<byte>, CancellationToken> processLine)
|
||||
{
|
||||
// Allocate at least 512 bytes from the PipeWriter.
|
||||
var memory = writer.GetMemory(minimumBufferSize);
|
||||
this.webSocket = webSocket;
|
||||
ProcessLine = processLine;
|
||||
}
|
||||
|
||||
try
|
||||
public Action<ReadOnlySequence<byte>, 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取socket收到的消息写入Pipe
|
||||
/// </summary>
|
||||
/// <param name="socket"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Pipe中读取收到的消息
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken)
|
||||
{
|
||||
while (true)
|
||||
/// <summary>
|
||||
/// 从Pipe中读取收到的消息
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await reader.ReadAsync(cancellationToken);
|
||||
var buffer = result.Buffer;
|
||||
|
||||
while (TryReadLine(ref buffer, out ReadOnlySequence<byte> 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<byte> 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<byte> buffer, out ReadOnlySequence<byte> line)
|
||||
{
|
||||
// Look for a EOL in the buffer.
|
||||
SequencePosition? position = buffer.PositionOf((byte)'\n');
|
||||
|
||||
if (position == null)
|
||||
bool TryReadLine(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user