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; } /// /// 重要:连接服务端 /// /// 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 StreamTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func> beforeTransfer = null) { await fromStream.CopyToAsync(toStream, 4096, ct); return signal; } private async Task ToStaticTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func> 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 }); } } }