This commit is contained in:
springhgui 2021-10-11 00:14:55 +08:00
parent 3f43810ef3
commit 3b3f3a5c73
11 changed files with 46 additions and 205 deletions

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.0</Version>
<Version>1.0.1</Version>
<PackageProjectUrl>https://github.com/FastTunnel/FastTunnel/tree/v2/FastTunnel.Api</PackageProjectUrl>
<RepositoryUrl>https://github.com/FastTunnel/FastTunnel/tree/v2/FastTunnel.Api</RepositoryUrl>
</PropertyGroup>

View File

@ -39,7 +39,6 @@ namespace FastTunnel.Core
services.AddTransient<IFastTunnelClient, FastTunnelClient>()
.AddSingleton<IExceptionFilter, FastTunnelExceptionFilter>()
.AddSingleton<LogHandler>()
.AddTransient<TunnelClient>()
.AddSingleton<SwapHandler>();
services.AddHostedService<ServiceFastTunnelClient>();
@ -57,7 +56,7 @@ namespace FastTunnel.Core
services.Configure<DefaultServerConfig>(configurationSection)
.AddSingleton<IExceptionFilter, FastTunnelExceptionFilter>()
.AddTransient<ILoginHandler, LoginHandler>()
.AddTransient<TunnelClient>()
.AddSingleton<TunnelClientHandler>()
.AddSingleton<FastTunnelClientHandler>()
.AddSingleton<FastTunnelSwapHandler>()
.AddSingleton<FastTunnelServer>();

View File

@ -30,6 +30,7 @@
<Compile Remove="Listener\HttpListener.cs" />
<Compile Remove="Server.cs" />
<Compile Remove="Sockets\AsyncSocketSwap.cs" />
<Compile Remove="Sockets\SocketSwap.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -25,11 +25,13 @@ namespace FastTunnel.Core.MiddleWares
ILogger<FastTunnelClientHandler> logger;
FastTunnelServer fastTunnelServer;
Version serverVersion;
TunnelClientHandler tunnelClient;
public FastTunnelClientHandler(ILogger<FastTunnelClientHandler> logger, FastTunnelServer fastTunnelServer)
public FastTunnelClientHandler(ILogger<FastTunnelClientHandler> logger, FastTunnelServer fastTunnelServer, TunnelClientHandler tunnelClient)
{
this.logger = logger;
this.fastTunnelServer = fastTunnelServer;
this.tunnelClient = tunnelClient;
serverVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
@ -48,7 +50,6 @@ namespace FastTunnel.Core.MiddleWares
private async Task handleClient(HttpContext context, Func<Task> next, string clientVersion)
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
var tunnelClient = context.RequestServices.GetRequiredService<TunnelClient>().SetSocket(webSocket);
if (Version.Parse(clientVersion).Major != serverVersion.Major)
{
@ -66,7 +67,7 @@ namespace FastTunnel.Core.MiddleWares
{
Interlocked.Increment(ref fastTunnelServer.ConnectedClientCount);
logger.LogInformation($"客户端连接 {context.TraceIdentifier}:{context.Connection.RemoteIpAddress} 当前在线数:{fastTunnelServer.ConnectedClientCount}");
await tunnelClient.ReviceAsync(CancellationToken.None);
await tunnelClient.ReviceAsync(webSocket, CancellationToken.None);
logOut(context);
}

View File

@ -31,9 +31,11 @@ namespace FastTunnel.Core.Forwarder.MiddleWare
}
var requestId = context.Request.Path.Value.Trim('/');
logger.LogError($"[PROXY]:Start {requestId}");
if (!fastTunnelServer.ResponseTasks.TryRemove(requestId, out var responseAwaiter))
{
logger.LogError($"requestId不存在:{requestId}");
logger.LogError($"[PROXY]:RequestId不存在 {requestId}");
return;
};
@ -50,9 +52,13 @@ namespace FastTunnel.Core.Forwarder.MiddleWare
responseAwaiter.TrySetResult(reverseConnection);
var closedAwaiter = new TaskCompletionSource<object>();
lifetime.ConnectionClosed.Register((task) => { (task as TaskCompletionSource<object>).SetResult(null); }, closedAwaiter);
lifetime.ConnectionClosed.Register((task) =>
{
(task as TaskCompletionSource<object>).SetResult(null);
}, closedAwaiter);
await closedAwaiter.Task;
logger.LogError($"[PROXY]:Closed {requestId}");
}
}
}

View File

@ -54,17 +54,14 @@ namespace FastTunnel.Core.Handlers.Client
private async Task<Stream> createLocal(string requestId, string localhost, CancellationToken cancellationToken)
{
var localConnecter = new DnsSocket(localhost.Split(":")[0], int.Parse(localhost.Split(":")[1]));
await localConnecter.ConnectAsync();
return new NetworkStream(localConnecter.Socket, true);
var socket = await DnsSocketFactory.ConnectAsync(localhost.Split(":")[0], int.Parse(localhost.Split(":")[1]));
return new NetworkStream(socket, true);
}
private async Task<Stream> createRemote(string requestId, FastTunnelClient cleint, CancellationToken cancellationToken)
{
var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort);
await connecter.ConnectAsync();
Stream serverStream = new NetworkStream(connecter.Socket, true);
var socket = await DnsSocketFactory.ConnectAsync(cleint.Server.ServerAddr, cleint.Server.ServerPort);
Stream serverStream = new NetworkStream(socket, true);
if (cleint.Server.Protocol == "wss")
{
var sslStream = new SslStream(serverStream, false, delegate { return true; });

View File

@ -17,27 +17,20 @@ using Yarp.ReverseProxy.Configuration;
namespace FastTunnel.Core.Models
{
public class TunnelClient
public class TunnelClientHandler
{
readonly ILoginHandler _loginHandler;
FastTunnelServer fastTunnelServer;
ILogger logger;
WebSocket webSocket;
public TunnelClient(ILogger<TunnelClient> logger, FastTunnelServer fastTunnelServer, ILoginHandler loginHandler)
public TunnelClientHandler(ILogger<TunnelClientHandler> logger, FastTunnelServer fastTunnelServer, ILoginHandler loginHandler)
{
this.logger = logger;
this.fastTunnelServer = fastTunnelServer;
this._loginHandler = loginHandler;
}
public TunnelClient SetSocket(WebSocket webSocket)
{
this.webSocket = webSocket;
return this;
}
public async Task ReviceAsync(CancellationToken cancellationToken)
public async Task ReviceAsync(WebSocket webSocket, CancellationToken cancellationToken)
{
var buffer = new byte[FastTunnelConst.MAX_CMD_LENGTH];
var tunnelProtocol = new TunnelProtocol();

View File

@ -1,34 +0,0 @@
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace FastTunnel.Core.Sockets
{
public class DnsSocket
{
private string _host;
private int _port;
public Socket Socket { get; }
public DnsSocket(string host, int port)
{
this._host = host;
this._port = port;
Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket.NoDelay = true;
}
public async Task ConnectAsync()
{
DnsEndPoint dnsEndPoint = new DnsEndPoint(_host, _port);
await Socket.ConnectAsync(dnsEndPoint);
}
}
}

View File

@ -0,0 +1,22 @@
using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace FastTunnel.Core.Sockets
{
public class DnsSocketFactory
{
public static async Task<Socket> ConnectAsync(string host, int port)
{
var Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
DnsEndPoint dnsEndPoint = new DnsEndPoint(host, port);
await Socket.ConnectAsync(dnsEndPoint);
return Socket;
}
}
}

View File

@ -1,143 +0,0 @@
using FastTunnel.Core.Dispatchers;
using FastTunnel.Core.Utility.Extensions;
using Microsoft.Extensions.Logging;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FastTunnel.Core.Sockets
{
public class SocketSwap
{
private readonly Socket m_sockt1;
private readonly Socket m_sockt2;
private readonly string m_msgId = null;
private readonly ILogger m_logger;
private bool swapeStarted = false;
private class Channel
{
public Socket Send { get; set; }
public Socket Receive { get; set; }
}
public SocketSwap(Socket sockt1, Socket sockt2, ILogger logger, string msgId)
{
//sockt1.NoDelay = true;
//sockt2.NoDelay = true;
m_sockt1 = sockt1;
m_sockt2 = sockt2;
m_msgId = msgId;
m_logger = logger;
}
public void StartSwap()
{
m_logger?.LogDebug($"[StartSwapStart] {m_msgId}");
swapeStarted = true;
ThreadPool.QueueUserWorkItem(swapCallback, new Channel
{
Send = m_sockt1,
Receive = m_sockt2
});
ThreadPool.QueueUserWorkItem(swapCallback, new Channel
{
Send = m_sockt2,
Receive = m_sockt1
});
m_logger?.LogDebug($"[StartSwapEnd] {m_msgId}");
}
private void swapCallback(object state)
{
m_logger?.LogDebug($"swapCallback {m_msgId}");
var chanel = state as Channel;
byte[] result = new byte[512];
while (true)
{
int num;
try
{
try
{
num = chanel.Receive.Receive(result, 0, result.Length, SocketFlags.None);
}
catch (Exception)
{
closeSocket("Revice Fail");
break;
}
if (num == 0)
{
closeSocket("Normal Close");
break;
}
try
{
chanel.Send.Send(result, 0, num, SocketFlags.None);
}
catch (Exception)
{
closeSocket("Send Fail");
break;
}
}
catch (Exception ex)
{
m_logger.LogCritical(ex, "致命异常");
break;
}
}
if (m_msgId.Contains("_"))
{
var interval = long.Parse(DateTime.Now.GetChinaTicks()) - long.Parse(m_msgId.Split('_')[0]);
m_logger?.LogDebug($"endSwap {m_msgId} 交互时常:{interval}ms");
}
}
private void closeSocket(string msg)
{
m_logger.LogDebug($"【closeSocket】{msg}");
try
{
m_sockt1.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
}
finally
{
m_sockt1.Close();
}
try
{
m_sockt2.Shutdown(SocketShutdown.Both);
}
catch (Exception)
{
}
finally
{
m_sockt2.Close();
}
}
}
}

View File

@ -1,6 +1,5 @@
using FastTunnel.Core;
using FastTunnel.Core.Extensions;
using FastTunnel.Server.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@ -57,9 +56,9 @@ namespace FastTunnel.Server
context.Response.ContentType = "application/json;charset=utf-8";
context.Response.StatusCode = StatusCodes.Status200OK;
await context.Response.WriteAsync(new ApiResponse
await context.Response.WriteAsync(new
{
errorCode = ErrorCodeEnum.AuthError,
errorCode = 1,
errorMessage = context.Error ?? "Token is Required"
}.ToJson());
},