first commit
This commit is contained in:
174
Ultron.Proxy.Client/Router.cs
Normal file
174
Ultron.Proxy.Client/Router.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Ultron.Proxy.Interfaces;
|
||||
using Ultron.Proxy.Models;
|
||||
|
||||
namespace Ultron.Proxy
|
||||
{
|
||||
public class Router
|
||||
{
|
||||
CancellationTokenSource CANCEL_TOKEN = new CancellationTokenSource();
|
||||
CancellationTokenSource TRANSFERING_TOKEN = new CancellationTokenSource();
|
||||
ServerConnnectionManager ConnnectionManager;
|
||||
|
||||
internal static Config ClientConfig;
|
||||
|
||||
//inject
|
||||
internal static ILogger Logger;
|
||||
|
||||
public Router(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public void SetConifiguration(Config config)
|
||||
{
|
||||
ClientConfig = config;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重要:连接服务端
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task ConnectToProvider()
|
||||
{
|
||||
var appIdIpPortConfig = ClientConfig.Clients;
|
||||
|
||||
ConnnectionManager = ServerConnnectionManager.Create();
|
||||
ConnnectionManager.ClientGroupConnected += ServerConnnectionManager_ClientGroupConnected;
|
||||
var clientModel = await ConnnectionManager.InitConfig();
|
||||
int counter = 0;
|
||||
//appid为0时说明没有分配appid,所以需要分配一个
|
||||
foreach (var app in appIdIpPortConfig)
|
||||
{
|
||||
if (app.AppID == 0)
|
||||
{
|
||||
app.AppID = clientModel.AppList[counter].AppId;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
Logger.Debug("****************port list*************");
|
||||
|
||||
foreach (var ap in clientModel.AppList)
|
||||
{
|
||||
var cApp = appIdIpPortConfig.First(obj => obj.AppID == ap.AppId);
|
||||
Logger.Debug(ap.AppId.ToString() + ": " + ClientConfig.ProviderAddress + ":" + ap.Port.ToString() + "=>" +
|
||||
cApp.IP + ":" + cApp.Port);
|
||||
}
|
||||
Logger.Debug("**************************************");
|
||||
Task pollingTask = ConnnectionManager.PollingToProvider();
|
||||
try
|
||||
{
|
||||
await pollingTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Thread:" + Thread.CurrentThread.ManagedThreadId + " crashed.\n", ex);
|
||||
throw;
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromHours(24), CANCEL_TOKEN.Token);
|
||||
}
|
||||
|
||||
private void ServerConnnectionManager_ClientGroupConnected(object sender, EventArgs e)
|
||||
{
|
||||
var args = (ClientGroupEventArgs)e;
|
||||
foreach (TcpClient providerClient in args.NewClients)
|
||||
{
|
||||
|
||||
Router.Logger.Debug("Open server connection.");
|
||||
OpenTrasferation(args.App.AppId, providerClient);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async Task OpenTrasferation(int appId, TcpClient providerClient)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[1];
|
||||
NetworkStream providerClientStream = providerClient.GetStream();
|
||||
//接收首条消息,首条消息中返回的是appid和客户端
|
||||
int readByteCount = await providerClientStream.ReadAsync(buffer, 0, buffer.Length);
|
||||
//从空闲连接列表中移除
|
||||
ConnnectionManager.RemoveClient(appId, providerClient);
|
||||
//每移除一个链接则发起一个新的链接
|
||||
Logger.Debug(appId + "接收到连接请求");
|
||||
TcpClient toTargetServer = new TcpClient();
|
||||
//根据clientid_appid发送到固定的端口
|
||||
ClientApp item = ClientConfig.Clients.First((obj) => obj.AppID == appId);
|
||||
|
||||
//只发送一次,需要在链接成功移除时加入
|
||||
await ConnnectionManager.ConnectAppToServer(appId);
|
||||
Logger.Debug("已建立反向连接:" + appId);
|
||||
// item1:app编号,item2:ip地址,item3:目标服务端口
|
||||
toTargetServer.Connect(item.IP, item.Port);
|
||||
Logger.Debug("已连接目标服务:" + item.IP.ToString() + ":" + item.Port.ToString());
|
||||
|
||||
NetworkStream targetServerStream = toTargetServer.GetStream();
|
||||
//targetServerStream.Write(buffer, 0, readByteCount);
|
||||
TcpTransferAsync(providerClientStream, targetServerStream, providerClient, toTargetServer);
|
||||
//already close connection
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Debug(e);
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async Task TcpTransferAsync(NetworkStream providerStream, NetworkStream targetServceStream, TcpClient providerClient, TcpClient toTargetServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Debug("Looping start.");
|
||||
//创建相互转发流
|
||||
var taskT2PLooping = ToStaticTransfer(TRANSFERING_TOKEN.Token, targetServceStream, providerStream, "T2P");
|
||||
var taskP2TLooping = StreamTransfer(TRANSFERING_TOKEN.Token, providerStream, targetServceStream, "P2T");
|
||||
|
||||
//close connnection,whether client or server stopped transferring.
|
||||
var comletedTask = await Task.WhenAny(taskT2PLooping, taskP2TLooping);
|
||||
//Router.Logger.Debug(comletedTask.Result + "传输关闭,重新读取字节");
|
||||
providerClient.Close();
|
||||
Logger.Debug("已关闭toProvider连接。");
|
||||
toTargetServer.Close();
|
||||
Logger.Debug("已关闭toTargetServer连接。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Debug(ex.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task<string> StreamTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func<byte[], Task<bool>> beforeTransfer = null)
|
||||
{
|
||||
await fromStream.CopyToAsync(toStream, 4096, ct);
|
||||
return signal;
|
||||
}
|
||||
|
||||
|
||||
private async Task<string> ToStaticTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func<byte[], Task<bool>> beforeTransfer = null)
|
||||
{
|
||||
|
||||
await fromStream.CopyToAsync(toStream, 4096, ct);
|
||||
return signal;
|
||||
}
|
||||
|
||||
private void SendZero(int port)
|
||||
{
|
||||
TcpClient tc = new TcpClient();
|
||||
tc.Connect("127.0.0.1", port);
|
||||
tc.Client.Send(new byte[] { 0 });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user