This commit is contained in:
Gui.H 2022-05-03 09:34:54 +08:00
parent d22084f6ce
commit 401276cb6a
22 changed files with 177 additions and 68 deletions

View File

@ -8,9 +8,9 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using FastTunnel.Core;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Serilog; using Serilog;
using FastTunnel.Core.Extensions;
namespace FastTunnel.Client; namespace FastTunnel.Client;

View File

@ -1,4 +1,4 @@
// Licensed under the Apache License, Version 2.0 (the "License"). // Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License. // You may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE
@ -16,6 +16,7 @@ using FastTunnel.Core.Handlers.Client;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Net.WebSockets; using System.Net.WebSockets;
using FastTunnel.Core.Utilitys; using FastTunnel.Core.Utilitys;
using FastTunnel.Core.Models.Massage;
namespace FastTunnel.Core.Client namespace FastTunnel.Core.Client
{ {

View File

@ -10,7 +10,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FastTunnel.Core.Client; using FastTunnel.Core.Client;
using FastTunnel.Core.Forwarder.MiddleWare; using FastTunnel.Core.Forwarder.Kestrel;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -19,13 +19,17 @@ namespace FastTunnel.Core.Extensions;
public static class ListenOptionsSwapExtensions public static class ListenOptionsSwapExtensions
{ {
public static ListenOptions UseFastTunnelSwap(this ListenOptions listenOptions) public static ListenOptions UseConnectionFastTunnel(this ListenOptions listenOptions)
{ {
var loggerFactory = listenOptions.KestrelServerOptions.ApplicationServices.GetRequiredService<ILoggerFactory>(); var loggerFactory = listenOptions.KestrelServerOptions.ApplicationServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<SwapConnectionMiddleware>(); var logger = loggerFactory.CreateLogger<SwapConnectionMiddleware>();
var loggerClient = loggerFactory.CreateLogger<ClientConnectionMiddleware>();
var fastTunnelServer = listenOptions.KestrelServerOptions.ApplicationServices.GetRequiredService<FastTunnelServer>(); var fastTunnelServer = listenOptions.KestrelServerOptions.ApplicationServices.GetRequiredService<FastTunnelServer>();
listenOptions.Use(next => new SwapConnectionMiddleware(next, logger, fastTunnelServer).OnConnectionAsync); listenOptions.Use(next => new SwapConnectionMiddleware(next, logger, fastTunnelServer).OnConnectionAsync);
// 登录频率低,放在后面
//listenOptions.Use(next => new ClientConnectionMiddleware(next, loggerClient, fastTunnelServer).OnConnectionAsync);
return listenOptions; return listenOptions;
} }
} }

View File

@ -9,12 +9,10 @@ using FastTunnel.Core.Config;
using FastTunnel.Core.Forwarder.MiddleWare; using FastTunnel.Core.Forwarder.MiddleWare;
using FastTunnel.Core.Forwarder; using FastTunnel.Core.Forwarder;
using FastTunnel.Core.Handlers.Client; using FastTunnel.Core.Handlers.Client;
using FastTunnel.Core.MiddleWares;
using FastTunnel.Core.Services; using FastTunnel.Core.Services;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Yarp.ReverseProxy.Forwarder; using Yarp.ReverseProxy.Forwarder;
using Yarp.Sample;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using FastTunnel.Core.Filters; using FastTunnel.Core.Filters;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
@ -26,7 +24,7 @@ using System.Threading.Tasks;
using System.Threading; using System.Threading;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace FastTunnel.Core namespace FastTunnel.Core.Extensions
{ {
public static class ServicesExtensions public static class ServicesExtensions
{ {
@ -78,7 +76,6 @@ namespace FastTunnel.Core
var swapHandler = app.ApplicationServices.GetRequiredService<FastTunnelSwapHandler>(); var swapHandler = app.ApplicationServices.GetRequiredService<FastTunnelSwapHandler>();
var clientHandler = app.ApplicationServices.GetRequiredService<FastTunnelClientHandler>(); var clientHandler = app.ApplicationServices.GetRequiredService<FastTunnelClientHandler>();
app.Use(clientHandler.Handle); app.Use(clientHandler.Handle);
app.Use(swapHandler.Handle);
} }
public static void MapFastTunnelServer(this IEndpointRouteBuilder endpoints) public static void MapFastTunnelServer(this IEndpointRouteBuilder endpoints)

View File

@ -5,6 +5,7 @@
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
using FastTunnel.Core.Models; using FastTunnel.Core.Models;
using FastTunnel.Core.Models.Massage;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Sockets; using System.Net.Sockets;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019-2022 Gui.H. https://github.com/FastTunnel/FastTunnel // Copyright (c) 2019-2022 Gui.H. https://github.com/FastTunnel/FastTunnel
// The FastTunnel licenses this file to you under the Apache License Version 2.0. // The FastTunnel licenses this file to you under the Apache License Version 2.0.
// For more details,You may obtain License file at: https://github.com/FastTunnel/FastTunnel/blob/v2/LICENSE // For more details,You may obtain License file at: https://github.com/FastTunnel/FastTunnel/blob/v2/LICENSE
@ -48,8 +48,9 @@ namespace FastTunnel.Core.Forwarder
var res = await proxyAsync(host, context, cancellationToken); var res = await proxyAsync(host, context, cancellationToken);
return res; return res;
} }
catch (Exception) catch (Exception ex)
{ {
logger.LogError(ex, "ConnectCallback Error");
throw; throw;
} }
} }

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yarp.ReverseProxy.Configuration;
namespace FastTunnel.Core.Forwarder
{
public class FastTunnelProxyConfigProvider : IProxyConfigProvider
{
public IProxyConfig GetConfig()
{
return new FastTunnelProxyConfig();
}
}
}

View File

@ -9,7 +9,7 @@ using Microsoft.Extensions.Primitives;
using Yarp.ReverseProxy.Configuration; using Yarp.ReverseProxy.Configuration;
using System.Linq; using System.Linq;
namespace Yarp.Sample namespace FastTunnel.Core.Forwarder
{ {
/// <summary> /// <summary>
/// Extends the IReverseProxyBuilder to support the InMemoryConfigProvider /// Extends the IReverseProxyBuilder to support the InMemoryConfigProvider

View File

@ -0,0 +1,110 @@
// 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.Buffers;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FastTunnel.Core.Client;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.Extensions.Logging;
namespace FastTunnel.Core.Forwarder.Kestrel;
internal class ClientConnectionMiddleware
{
readonly ConnectionDelegate next;
readonly ILogger<ClientConnectionMiddleware> logger;
FastTunnelServer fastTunnelServer;
public ClientConnectionMiddleware(ConnectionDelegate next, ILogger<ClientConnectionMiddleware> logger, FastTunnelServer fastTunnelServer)
{
this.next = next;
this.logger = logger;
this.fastTunnelServer = fastTunnelServer;
}
internal async Task OnConnectionAsync(ConnectionContext context)
{
var oldTransport = context.Transport;
try
{
if (!await ReadPipeAsync(context))
{
await next(context);
}
await next(context);
}
finally
{
context.Transport = oldTransport;
}
}
async Task<bool> ReadPipeAsync(ConnectionContext context)
{
var reader = context.Transport.Input;
var isProxy = false;
while (true)
{
var result = await reader.ReadAsync();
var buffer = result.Buffer;
SequencePosition? position = null;
do
{
position = buffer.PositionOf((byte)'\n');
if (position != null)
{
isProxy = ProcessProxyLine(buffer.Slice(0, position.Value));
if (isProxy)
{
await Login(buffer, position.Value, context);
return true;
}
else
{
context.Transport.Input.AdvanceTo(buffer.Start, buffer.Start);
return false;
}
}
}
while (position != null);
if (result.IsCompleted)
{
break;
}
}
return false;
}
private async Task Login(ReadOnlySequence<byte> buffer, SequencePosition position, ConnectionContext context)
{
}
/// <summary>
///
/// </summary>
/// <param name="readOnlySequence"></param>
private bool ProcessProxyLine(ReadOnlySequence<byte> readOnlySequence)
{
var str = Encoding.UTF8.GetString(readOnlySequence);
return str.StartsWith("LOGIN");
}
}

View File

@ -12,11 +12,12 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FastTunnel.Core.Client; using FastTunnel.Core.Client;
using FastTunnel.Core.Forwarder.MiddleWare;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Connections.Features;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace FastTunnel.Core.Forwarder.MiddleWare; namespace FastTunnel.Core.Forwarder.Kestrel;
internal class SwapConnectionMiddleware internal class SwapConnectionMiddleware
{ {
@ -35,30 +36,21 @@ internal class SwapConnectionMiddleware
{ {
var oldTransport = context.Transport; var oldTransport = context.Transport;
try if (!await ReadPipeAsync(context))
{ {
if (!await ReadPipeAsync(context))
{
await next(context);
}
await next(context); await next(context);
} }
finally
{
context.Transport = oldTransport;
}
} }
async Task<bool> ReadPipeAsync(ConnectionContext context) async Task<bool> ReadPipeAsync(ConnectionContext context)
{ {
var reader = context.Transport.Input; var reader = context.Transport.Input;
bool isProxy = false; var isProxy = false;
while (true) while (true)
{ {
ReadResult result = await reader.ReadAsync(); var result = await reader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer; var buffer = result.Buffer;
SequencePosition? position = null; SequencePosition? position = null;
do do
@ -121,9 +113,20 @@ internal class SwapConnectionMiddleware
(task as TaskCompletionSource<object>).SetResult(null); (task as TaskCompletionSource<object>).SetResult(null);
}, closedAwaiter); }, closedAwaiter);
await closedAwaiter.Task; try
{
logger.LogDebug($"[PROXY]:Closed {requestId}"); await closedAwaiter.Task;
}
catch (Exception ex)
{
logger.LogError(ex, "");
}
finally
{
context.Transport.Input.Complete();
context.Transport.Output.Complete();
logger.LogInformation($"=====================Swap End:{requestId}================== ");
}
} }
/// <summary> /// <summary>

View File

@ -122,8 +122,12 @@ internal class DuplexPipeStream : Stream
{ {
while (true) while (true)
{ {
var result = await _input.ReadAsync(cancellationToken); ReadResult result;
var readableBuffer = result.Buffer; ReadOnlySequence<byte> readableBuffer;
result = await _input.ReadAsync(cancellationToken);
readableBuffer = result.Buffer;
try try
{ {
if (_throwOnCancelled && result.IsCanceled && _cancelCalled) if (_throwOnCancelled && result.IsCanceled && _cancelCalled)
@ -138,10 +142,6 @@ internal class DuplexPipeStream : Stream
// buffer.Count is int // buffer.Count is int
var count = (int)Math.Min(readableBuffer.Length, destination.Length); var count = (int)Math.Min(readableBuffer.Length, destination.Length);
readableBuffer = readableBuffer.Slice(0, count); readableBuffer = readableBuffer.Slice(0, count);
var str = Encoding.UTF8.GetString(readableBuffer);
Console.WriteLine($"[ReadAsyncInternal]:{str}");
readableBuffer.CopyTo(destination.Span); readableBuffer.CopyTo(destination.Span);
return count; return count;
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019-2022 Gui.H. https://github.com/FastTunnel/FastTunnel // Copyright (c) 2019-2022 Gui.H. https://github.com/FastTunnel/FastTunnel
// The FastTunnel licenses this file to you under the Apache License Version 2.0. // The FastTunnel licenses this file to you under the Apache License Version 2.0.
// For more details,You may obtain License file at: https://github.com/FastTunnel/FastTunnel/blob/v2/LICENSE // For more details,You may obtain License file at: https://github.com/FastTunnel/FastTunnel/blob/v2/LICENSE
@ -13,7 +13,7 @@ using System.Net.WebSockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FastTunnel.Core.MiddleWares namespace FastTunnel.Core.Forwarder.MiddleWare
{ {
public class FastTunnelClientHandler public class FastTunnelClientHandler
{ {
@ -91,7 +91,7 @@ namespace FastTunnel.Core.MiddleWares
private bool checkToken(HttpContext context) private bool checkToken(HttpContext context)
{ {
bool checkToken = false; var checkToken = false;
if (fastTunnelServer.ServerOption.CurrentValue.Tokens != null && fastTunnelServer.ServerOption.CurrentValue.Tokens.Count != 0) if (fastTunnelServer.ServerOption.CurrentValue.Tokens != null && fastTunnelServer.ServerOption.CurrentValue.Tokens.Count != 0)
{ {
checkToken = true; checkToken = true;

View File

@ -1,6 +1,5 @@
using FastTunnel.Core.Client; using FastTunnel.Core.Client;
using FastTunnel.Core.Extensions; using FastTunnel.Core.Extensions;
using FastTunnel.Core.MiddleWares;
using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -38,7 +38,18 @@ namespace FastTunnel.Core.Handlers.Client
var taskX = serverStream.CopyToAsync(localStream, cancellationToken); var taskX = serverStream.CopyToAsync(localStream, cancellationToken);
var taskY = localStream.CopyToAsync(serverStream, cancellationToken); var taskY = localStream.CopyToAsync(serverStream, cancellationToken);
await Task.WhenAny(taskX, taskY); try
{
await Task.WhenAll(taskX, taskY);
}
catch (Exception ex)
{
}
finally
{
_logger.LogError($"=====================Swap End:{requestId}================== ");
}
} }
} }
catch (Exception ex) catch (Exception ex)
@ -66,6 +77,8 @@ namespace FastTunnel.Core.Handlers.Client
} }
var reverse = $"PROXY /{requestId} HTTP/1.1\r\n"; var reverse = $"PROXY /{requestId} HTTP/1.1\r\n";
//var reverse = $"PROXY /{requestId} HTTP/1.1\r\nHost: {cleint.Server.ServerAddr}:{cleint.Server.ServerPort}\r\n\r\n";
var requestMsg = Encoding.UTF8.GetBytes(reverse); var requestMsg = Encoding.UTF8.GetBytes(reverse);
await serverStream.WriteAsync(requestMsg, cancellationToken); await serverStream.WriteAsync(requestMsg, cancellationToken);
return serverStream; return serverStream;

View File

@ -5,7 +5,6 @@
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
using FastTunnel.Core.Client; using FastTunnel.Core.Client;
using FastTunnel.Core.Dispatchers;
using FastTunnel.Core.Exceptions; using FastTunnel.Core.Exceptions;
using FastTunnel.Core.Extensions; using FastTunnel.Core.Extensions;
using FastTunnel.Core.Models; using FastTunnel.Core.Models;
@ -21,7 +20,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FastTunnel.Core.Dispatchers namespace FastTunnel.Core.Handlers.Server
{ {
public class ForwardDispatcher public class ForwardDispatcher
{ {

View File

@ -13,7 +13,7 @@ using System.Net.WebSockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FastTunnel.Core.Handlers namespace FastTunnel.Core.Handlers.Server
{ {
public interface IClientMessageHandler public interface IClientMessageHandler
{ {

View File

@ -5,10 +5,11 @@
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
using FastTunnel.Core.Client; using FastTunnel.Core.Client;
using FastTunnel.Core.Dispatchers;
using FastTunnel.Core.Extensions; using FastTunnel.Core.Extensions;
using FastTunnel.Core.Forwarder;
using FastTunnel.Core.Listener; using FastTunnel.Core.Listener;
using FastTunnel.Core.Models; using FastTunnel.Core.Models;
using FastTunnel.Core.Models.Massage;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Linq; using System.Linq;
@ -16,7 +17,6 @@ using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yarp.ReverseProxy.Configuration; using Yarp.ReverseProxy.Configuration;
using Yarp.Sample;
namespace FastTunnel.Core.Handlers.Server namespace FastTunnel.Core.Handlers.Server
{ {

View File

@ -4,7 +4,7 @@
// https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
using FastTunnel.Core.Dispatchers; using FastTunnel.Core.Handlers.Server;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Net; using System.Net;

View File

@ -6,7 +6,7 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace FastTunnel.Core.Models namespace FastTunnel.Core.Models.Massage
{ {
public class LogInMassage : TunnelMassage public class LogInMassage : TunnelMassage
{ {

View File

@ -4,7 +4,7 @@
// https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
namespace FastTunnel.Core.Models namespace FastTunnel.Core.Models.Massage
{ {
public class TunnelMassage public class TunnelMassage
{ {

View File

@ -65,8 +65,7 @@ public class Program
var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 1270; var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 1270;
options.ListenAnyIP(basePort, listenOptions => options.ListenAnyIP(basePort, listenOptions =>
{ {
//listenOptions.UseConnectionLogging(); listenOptions.UseConnectionFastTunnel();
listenOptions.UseFastTunnelSwap();
}); });
}); });

View File

@ -4,7 +4,6 @@
// https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE // https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE
// Copyright (c) 2019 Gui.H // Copyright (c) 2019 Gui.H
using FastTunnel.Core;
using FastTunnel.Core.Extensions; using FastTunnel.Core.Extensions;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;