diff --git a/FastTunnel.Client/appsettings.json b/FastTunnel.Client/appsettings.json index d0c6540..1975247 100644 --- a/FastTunnel.Client/appsettings.json +++ b/FastTunnel.Client/appsettings.json @@ -27,7 +27,7 @@ // [必选] 内网站点所在内网的ip "LocalIp": "127.0.0.1", // [必选] 内网站点监听的端口号 - "LocalPort": 8080, + "LocalPort": 8090, // [必选] 子域名, 访问本站点时的url为 http://${SubDomain}.${WebDomain}:${ServerPort} "SubDomain": "test" diff --git a/FastTunnel.Core/FastTunnel.Core.csproj b/FastTunnel.Core/FastTunnel.Core.csproj index e1716d9..a2ec8f9 100644 --- a/FastTunnel.Core/FastTunnel.Core.csproj +++ b/FastTunnel.Core/FastTunnel.Core.csproj @@ -4,6 +4,9 @@ README.md net6.0;net7.0 + + + diff --git a/FastTunnel.Core/Forwarder/Kestrel/FastTunnelConnectionContext.cs b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunelProtocol.cs similarity index 74% rename from FastTunnel.Core/Forwarder/Kestrel/FastTunnelConnectionContext.cs rename to FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunelProtocol.cs index 4723f77..4ab9406 100644 --- a/FastTunnel.Core/Forwarder/Kestrel/FastTunnelConnectionContext.cs +++ b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunelProtocol.cs @@ -8,59 +8,43 @@ using System; using System.Buffers; using System.Collections.Generic; using System.IO.Pipelines; +using System.Linq; +using System.Reflection.PortableExecutable; using System.Text; using System.Threading.Tasks; using FastTunnel.Core.Models; using FastTunnel.Core.Protocol; using FastTunnel.Core.Server; using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.FileSystemGlobbing; -namespace FastTunnel.Core.Forwarder.Kestrel; -internal class FastTunnelConnectionContext : ConnectionContext +namespace FastTunnel.Core.Forwarder.Kestrel.MiddleWare; + +public class FastTunelProtocol { - private readonly ConnectionContext _inner; - private readonly FastTunnelServer fastTunnelServer; - private readonly ILogger _logger; - - public FastTunnelConnectionContext(ConnectionContext context, FastTunnelServer fastTunnelServer, ILogger logger) + public FastTunelProtocol(ConnectionContext context, FastTunnelServer fastTunnelServer) { + this.context = context; this.fastTunnelServer = fastTunnelServer; - this._inner = context; - this._logger = logger; } - public override IDuplexPipe Transport { get => _inner.Transport; set => _inner.Transport = value; } - - public override string ConnectionId { get => _inner.ConnectionId; set => _inner.ConnectionId = value; } - - public override IFeatureCollection Features => _inner.Features; - - public override IDictionary Items { get => _inner.Items; set => _inner.Items = value; } - - public bool IsFastTunnel => Method == ProtocolConst.HTTP_METHOD_SWAP || MatchWeb != null; + bool IsFastTunnel => Method == ProtocolConst.HTTP_METHOD_SWAP || MatchWeb != null; public WebInfo MatchWeb { get; private set; } - public override ValueTask DisposeAsync() - { - return _inner.DisposeAsync(); - } + ConnectionContext context { get; } + + IDuplexPipe Transport => context.Transport; - /// - /// 解析FastTunnel协议 - /// internal async Task TryAnalysisPipeAsync() { - var reader = Transport.Input; + var _input = Transport.Input; ReadResult result; ReadOnlySequence readableBuffer; - while (true) { - result = await reader.ReadAsync(); + result = await _input.ReadAsync(); var tempBuffer = readableBuffer = result.Buffer; SequencePosition? position = null; @@ -72,17 +56,28 @@ internal class FastTunnelConnectionContext : ConnectionContext if (position != null) { var readedPosition = readableBuffer.GetPosition(1, position.Value); - if (ProcessLine(tempBuffer.Slice(0, position.Value))) + if (ProcessLine(tempBuffer.Slice(0, position.Value), out string line)) { if (Method == ProtocolConst.HTTP_METHOD_SWAP) { - reader.AdvanceTo(readedPosition, readedPosition); + _input.AdvanceTo(readedPosition, readedPosition); } else { - reader.AdvanceTo(readableBuffer.Start, readableBuffer.Start); + _input.AdvanceTo(readableBuffer.Start, readableBuffer.Start); } + if (IsFastTunnel) + { + context.Features.Set(new FastTunnelFeature() + { + MatchWeb = MatchWeb, + HasReadLInes = HasReadLInes, + Method = Method, + Host = Host, + MessageId = MessageId, + }); + } return; } @@ -93,12 +88,10 @@ internal class FastTunnelConnectionContext : ConnectionContext if (result.IsCompleted) { - reader.AdvanceTo(readableBuffer.End, readableBuffer.End); - break; + _input.AdvanceTo(readableBuffer.End, readableBuffer.End); + return; } } - - return; } public string Method; @@ -107,6 +100,7 @@ internal class FastTunnelConnectionContext : ConnectionContext private bool isFirstLine = true; public IList HasReadLInes { get; private set; } = new List(); + public FastTunnelServer fastTunnelServer { get; } /// /// @@ -122,9 +116,9 @@ internal class FastTunnelConnectionContext : ConnectionContext /// /// /// Header读取完毕? - private bool ProcessLine(ReadOnlySequence readOnlySequence) + private bool ProcessLine(ReadOnlySequence readOnlySequence, out string lineStr) { - var lineStr = Encoding.UTF8.GetString(readOnlySequence); + lineStr = Encoding.UTF8.GetString(readOnlySequence); HasReadLInes.Add(lineStr); if (isFirstLine) diff --git a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunnelFeature.cs b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunnelFeature.cs new file mode 100644 index 0000000..67f4535 --- /dev/null +++ b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/FastTunnelFeature.cs @@ -0,0 +1,24 @@ +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// 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.Models; + +namespace FastTunnel.Core.Forwarder.Kestrel.MiddleWare; + +public class FastTunnelFeature : IFastTunnelFeature +{ + public WebInfo MatchWeb { get; set; } + + public IList HasReadLInes { get; set; } + public string Method { get; set; } + public string Host { get; set; } + public string MessageId { get; set; } +} diff --git a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/ForwarderMiddleware.cs b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/ForwarderMiddleware.cs index 5639b56..59851c6 100644 --- a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/ForwarderMiddleware.cs +++ b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/ForwarderMiddleware.cs @@ -41,35 +41,45 @@ internal class ForwarderMiddleware internal async Task OnConnectionAsync(ConnectionContext context) { - var ctx = context as FastTunnelConnectionContext; - if (ctx != null && ctx.IsFastTunnel) + logger.LogInformation("=========ForwarderMiddleware SART==========="); + + var feat = context.Features.Get(); + if (feat == null) { - if (ctx.Method == ProtocolConst.HTTP_METHOD_SWAP) + logger.LogInformation("=========ForwarderMiddleware END==========="); + // not fasttunnel request + await next(context); + return; + } + else + { + logger.LogInformation("=========Swap STRART==========="); + if (feat.Method == ProtocolConst.HTTP_METHOD_SWAP) { - await doSwap(ctx); + await doSwap(context); } - else if (ctx.MatchWeb != null) + else if (feat.MatchWeb != null) { - await waitSwap(ctx); + await waitSwap(context); } else { throw new NotSupportedException(); } - } - else - { - await next(context); + + logger.LogInformation("=========Swap END==========="); + logger.LogInformation("=========ForwarderMiddleware END==========="); } } - private async Task waitSwap(FastTunnelConnectionContext context) + private async Task waitSwap(ConnectionContext context) { + var feat = context.Features.Get(); var requestId = Guid.NewGuid().ToString().Replace("-", ""); - var web = context.MatchWeb; + var web = feat.MatchWeb; TaskCompletionSource tcs = new(); - logger.LogDebug($"[Http]Swap开始 {requestId}|{context.Host}=>{web.WebConfig.LocalIp}:{web.WebConfig.LocalPort}"); + logger.LogDebug($"[Http]Swap开始 {requestId}|{feat.Host}=>{web.WebConfig.LocalIp}:{web.WebConfig.LocalPort}"); tcs.SetTimeOut(10000, () => { logger.LogDebug($"[Proxy TimeOut]:{requestId}"); }); fastTunnelServer.ResponseTasks.TryAdd(requestId, tcs); @@ -111,9 +121,10 @@ internal class ForwarderMiddleware } } - private async Task doSwap(FastTunnelConnectionContext context) + private async Task doSwap(ConnectionContext context) { - var requestId = context.MessageId; + var feat = context.Features.Get(); + var requestId = feat.MessageId; if (!fastTunnelServer.ResponseTasks.TryRemove(requestId, out var responseStream)) { throw new Exception($"[PROXY]:RequestId不存在 {requestId}"); diff --git a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/IFastTunnelFeature.cs b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/IFastTunnelFeature.cs new file mode 100644 index 0000000..8e8dbe1 --- /dev/null +++ b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/IFastTunnelFeature.cs @@ -0,0 +1,26 @@ +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// 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.Models; +using FastTunnel.Core.Protocol; + +namespace FastTunnel.Core.Forwarder.Kestrel.MiddleWare; + +internal interface IFastTunnelFeature +{ + public WebInfo MatchWeb { get; set; } + + public IList HasReadLInes { get; set; } + + public string Method { get; set; } + public string Host { get; set; } + public string MessageId { get; set; } +} diff --git a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/InitializerMiddleware.cs b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/InitializerMiddleware.cs index fc8d041..93aab9e 100644 --- a/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/InitializerMiddleware.cs +++ b/FastTunnel.Core/Forwarder/Kestrel/MiddleWare/InitializerMiddleware.cs @@ -30,11 +30,10 @@ internal class InitializerMiddleware internal async Task OnConnectionAsync(ConnectionContext context) { - logger.LogInformation("=========OnConnectionAsync==========="); - var ftContext = new FastTunnelConnectionContext(context, fastTunnelServer, logger); - await ftContext.TryAnalysisPipeAsync(); - + logger.LogInformation("=========TryAnalysisPipeAsync SART==========="); + await new FastTunelProtocol(context, fastTunnelServer).TryAnalysisPipeAsync(); logger.LogInformation("=========TryAnalysisPipeAsync END==========="); - await next(ftContext.IsFastTunnel ? ftContext : context); + + await next(context); } } diff --git a/FastTunnel.Hosting/FastTunnelHostingStartup.cs b/FastTunnel.Hosting/FastTunnelHostingStartup.cs index dec9033..2c64e8c 100644 --- a/FastTunnel.Hosting/FastTunnelHostingStartup.cs +++ b/FastTunnel.Hosting/FastTunnelHostingStartup.cs @@ -31,9 +31,9 @@ public class FastTunnelHostingStartup : IHostingStartup }); }); - builder.Configure((webHostBuilderContext, app) => - { - app.UseFastTunnelServer(); - }); + //builder.Configure((webHostBuilderContext, app) => + //{ + // app.UseFastTunnelServer(); + //}); } } diff --git a/FastTunnel.Server/Startup.cs b/FastTunnel.Server/Startup.cs index 8619b23..eacfd70 100644 --- a/FastTunnel.Server/Startup.cs +++ b/FastTunnel.Server/Startup.cs @@ -102,9 +102,15 @@ public class Startup app.UseAuthorization(); // --------------------- Custom UI ---------------- + app.UseFastTunnelServer(); + app.UseEndpoints(endpoints => { endpoints.MapControllers(); + endpoints.MapFallback(async (HttpContext ctx) => + { + await ctx.Response.Body.WriteAsync(Encoding.UTF8.GetBytes("hello~")); + }); }); } }