private async Task ProcessConsumeRequestAsync(int consumerPort, string clientApp, TcpClient consumerClient, CancellationToken ct) { TcpTunnel tunnel = new TcpTunnel { ConsumerClient = consumerClient }; ServerContext.PortAppMap[consumerPort].Tunnels.Add(tunnel); //Logger.Debug("consumer已连接:" + consumerClient.Client.RemoteEndPoint.ToString()); ServerContext.ConnectCount += 1; //II.弹出先前已经准备好的socket TcpClient s2pClient = await ConnectionManager.GetClient(consumerPort); if (s2pClient == null) { Logger.Debug($"端口{consumerPort}获取反弹连接超时,关闭传输。"); //获取clientid //关闭本次连接 ServerContext.CloseAllSourceByClient(ServerContext.PortAppMap[consumerPort].ClientId); } tunnel.ClientServerClient = s2pClient; //✳关键过程✳ //III.发送一个字节过去促使客户端建立转发隧道,至此隧道已打通 //客户端接收到此消息后,会另外分配一个备用连接 s2pClient.GetStream().WriteAndFlushAsync(new byte[] { 0x01 }, 0, 1); await TcpTransferAsync(consumerClient, s2pClient, clientApp, ct); }
private async Task ProcessConsumeRequestAsync(int consumerPort, string clientApp, TcpClient consumerClient, CancellationToken ct) { TcpTunnel tunnel = new TcpTunnel(); tunnel.ConsumerClient = consumerClient; ServerContext.PortAppMap[consumerPort].Tunnels.Add(tunnel); Logger.Debug("consumer已连接:" + consumerClient.Client.RemoteEndPoint.ToString()); //II.弹出先前已经准备好的socket TcpClient s2pClient = await ConnectionManager.GetClient(consumerPort); tunnel.ClientServerClient = s2pClient; //✳关键过程✳ //III.发送一个字节过去促使客户端建立转发隧道,至此隧道已打通 //客户端接收到此消息后,会另外分配一个备用连接 s2pClient.GetStream().WriteAndFlushAsync(new byte[] { 0x01 }, 0, 1); await TcpTransferAsync(consumerClient, s2pClient, clientApp, ct); }
/// <summary> /// 同时侦听来自consumer的链接和到provider的链接 /// </summary> /// <param name="consumerlistener"></param> /// <param name="ct"></param> /// <returns></returns> async Task ListenConsumeAsync(int consumerPort, CancellationToken ct) { try { var consumerlistener = new TcpListener(IPAddress.Any, consumerPort); consumerlistener.Start(1000); //给两个listen,同时监听3端 var clientCounter = 0; while (!ct.IsCancellationRequested) { //目标的代理服务联通了,才去处理consumer端的请求。 Logger.Debug("listening serviceClient....Port:" + consumerPort); TcpClient consumerClient = await consumerlistener.AcceptTcpClientAsync(); //记录tcp隧道,消费端 TcpTunnel tunnel = new TcpTunnel(); tunnel.ConsumerClient = consumerClient; ClientConnectionManager.GetInstance().PortAppMap[consumerPort].Tunnels.Add(tunnel); Logger.Debug("consumer已连接:" + consumerClient.Client.RemoteEndPoint.ToString()); //消费端连接成功,连接 //需要端口 TcpClient s2pClient = await ConnectionManager.GetClient(consumerPort); //记录tcp隧道,客户端 tunnel.ClientServerClient = s2pClient; //✳关键过程✳ //连接完之后发送一个字节过去促使客户端建立转发隧道 await s2pClient.GetStream().WriteAsync(new byte[] { 1 }, 0, 1); clientCounter++; TcpTransferAsync(consumerlistener, consumerClient, s2pClient, clientCounter, ct); } } catch (Exception e) { Logger.Debug(e); } }
private async Task ProcessConsumeRequestAsync(int consumerPort, string clientApp, TcpClient consumerClient, CancellationToken ct) { TcpTunnel tunnel = new TcpTunnel { ConsumerClient = consumerClient }; var nspApp = ServerContext.PortAppMap[consumerPort]; TcpClient s2pClient = null; Stream consumerStream = consumerClient.GetStream(); //; = consumerClient.GetStream().ProcessSSL(TestCert); Stream providerStream = null; // = s2pClient.GetStream(); byte[] restBytes = null; //int restBytesLength = 0; try { if (nspApp.ProtocolInGroup == Protocol.HTTP || nspApp.ProtocolInGroup == Protocol.HTTPS) {//不论是http协议还是https协议,有证书就加密 if (ServerContext.PortCertMap.TryGetValue(consumerPort.ToString(), out X509Certificate cert2)) { consumerStream = consumerStream.ProcessSSL(cert2); } var tp = await ReadHostName(consumerStream); if (tp == null) { Server.Logger.Debug("未在请求中找到主机名"); return; } string host = tp.Item1; restBytes = Encoding.UTF8.GetBytes(tp.Item2); //预发送bytes,因为这部分用来抓host消费掉了 //restBytesLength = tp.Item3; s2pClient = await ConnectionManager.GetClient(consumerPort, host); nspApp[host].Tunnels.Add(tunnel);//bug修改:建立隧道 } else { s2pClient = await ConnectionManager.GetClient(consumerPort); nspApp.ActivateApp.Tunnels.Add(tunnel);//bug修改:建立隧道 } } catch (TimeoutException ex) { Logger.Debug($"端口{consumerPort}获取反弹连接超时,关闭传输。=>" + ex.Message); //获取clientid //关闭本次连接 ServerContext.CloseAllSourceByClient(ServerContext.PortAppMap[consumerPort].ActivateApp.ClientId); return; } catch (KeyNotFoundException ex) { Server.Logger.Debug("未绑定此host:=>" + ex.Message); consumerClient.Close(); return; } //Logger.Debug("consumer已连接:" + consumerClient.Client.RemoteEndPoint.ToString()); ServerContext.ConnectCount += 1; //TODO 如果NSPApp中是http,则需要进一步分离,通过GetHTTPClient来分出对应的client以建立隧道 //if() //II.弹出先前已经准备好的socket tunnel.ClientServerClient = s2pClient; CancellationTokenSource transfering = new CancellationTokenSource(); //✳关键过程✳ //III.发送一个字节过去促使客户端建立转发隧道,至此隧道已打通 //客户端接收到此消息后,会另外分配一个备用连接 providerStream = s2pClient.GetStream(); await providerStream.WriteAndFlushAsync(new byte[] { 0x01 }, 0, 1); //预发送bytes,因为这部分用来抓host消费掉了,所以直接转发 if (restBytes != null) { await providerStream.WriteAsync(restBytes, 0, restBytes.Length, transfering.Token); } try { await TcpTransferAsync(consumerStream, providerStream, clientApp, transfering.Token); } finally { consumerClient.Close(); s2pClient.Close(); transfering.Cancel(); } }
private async Task ProcessConsumeTcpRequestAsync(int consumerPort, TcpClient consumerClient, CancellationToken ct) { TcpTunnel tunnel = new TcpTunnel { ConsumerClient = consumerClient }; var nspAppGroup = ServerContext.PortAppMap[consumerPort]; NSPApp nspApp = null; TcpClient s2pClient = null; Stream consumerStream = consumerClient.GetStream(); Stream providerStream = null; byte[] restBytes = null; try { if (nspAppGroup.ProtocolInGroup == Protocol.HTTP /*|| nspAppGroup.ProtocolInGroup == Protocol.HTTPS*/) {//不论是http协议还是https协议,有证书就加密 if (ServerContext.PortCertMap.TryGetValue(consumerPort.ToString(), out X509Certificate cert2)) { consumerStream = consumerStream.ProcessSSL(cert2); } var tp = await ReadHostName(consumerStream); if (tp == null) { Server.Logger.Debug("未在请求中找到主机名"); return; } string host = tp.Item1; restBytes = Encoding.UTF8.GetBytes(tp.Item2); //预发送bytes,因为这部分用来抓host消费掉了 //restBytesLength = tp.Item3; s2pClient = await ConnectionManager.GetClientForTcp(consumerPort, host); if (nspAppGroup.ContainsKey(host)) { nspAppGroup[host].Tunnels.Add(tunnel); //bug修改:建立隧道 } else { Server.Logger.Debug($"不存在host为“{host}”的主机名,但访问端依然以此主机名访问。"); } nspApp = nspAppGroup[host]; } else if (nspAppGroup.ProtocolInGroup == Protocol.TCP) //TCP { s2pClient = await ConnectionManager.GetClientForTcp(consumerPort); nspAppGroup.ActivateApp.Tunnels.Add(tunnel);//bug修改:建立隧道 nspApp = nspAppGroup.ActivateApp; } } catch (TimeoutException ex) { Logger.Debug($"端口{consumerPort}获取反弹连接超时,关闭传输。=>" + ex.Message); //获取clientid //关闭本次连接 ServerContext.CloseAllSourceByClient(ServerContext.PortAppMap[consumerPort].ActivateApp.ClientId); return; } catch (KeyNotFoundException ex) { Server.Logger.Debug("未绑定此host:=>" + ex.Message); consumerClient.Close(); return; } ServerContext.ConnectCount += 1; //TODO 如果NSPApp中是http,则需要进一步分离,通过GetHTTPClient来分出对应的client以建立隧道 //II.弹出先前已经准备好的socket tunnel.ClientServerClient = s2pClient; CancellationTokenSource transfering = new CancellationTokenSource(); //✳关键过程✳ //III.发送一个字节过去促使客户端建立转发隧道,至此隧道已打通 //客户端接收到此消息后,会另外分配一个备用连接 //TODO 4 增加一个udp转发的选项 providerStream = s2pClient.GetStream(); //TODO 5 这里会出错导致无法和客户端通信 try { await providerStream.WriteAndFlushAsync(new byte[] { (byte)ControlMethod.TCPTransfer }, 0, 1);//双端标记S0001 } catch { Logger.Debug($"client:{nspApp.ClientId} app:{nspApp.AppId}写入失败,尝试切断该客户端"); ServerContext.CloseAllSourceByClient(nspApp.ClientId); return; } //预发送bytes,因为这部分用来抓host消费掉了,所以直接转发 if (restBytes != null) { await providerStream.WriteAsync(restBytes, 0, restBytes.Length, transfering.Token); } //TODO 4 TCP则打通隧道进行转发,UDP直接转发 // if tcp try { await OpenTcpTransmission(consumerStream, providerStream, nspApp, transfering.Token); } finally { consumerClient.Close(); s2pClient.Close(); transfering.Cancel(); } }
private async Task ProcessConsumeRequestAsync(int consumerPort, string clientApp, TcpClient consumerClient, CancellationToken ct) { TcpTunnel tunnel = new TcpTunnel { ConsumerClient = consumerClient }; var nspApp = ServerContext.PortAppMap[consumerPort]; TcpClient s2pClient = null; byte[] restBytes = null; int restBytesLength = 0; //byte[] ToStaticBytes; try { if (nspApp.ProtocolInGroup == Protocol.HTTP) { var tp = await ReadHostName(consumerClient); string host = tp.Item1; restBytes = tp.Item2; //预发送bytes,因为这部分用来抓host消费掉了 restBytesLength = tp.Item3; s2pClient = await ConnectionManager.GetClient(consumerPort, host); //if (s2pClient == null) //TODO 2 关注!不要同时使用一种返回结果 如client为null //{ //} } else { s2pClient = await ConnectionManager.GetClient(consumerPort); } } catch (TimeoutException ex) { Logger.Debug($"端口{consumerPort}获取反弹连接超时,关闭传输。=>" + ex.Message); //获取clientid //关闭本次连接 ServerContext.CloseAllSourceByClient(ServerContext.PortAppMap[consumerPort].ActivateApp.ClientId); return; } catch (KeyNotFoundException ex) { Server.Logger.Debug("未绑定此host:=>" + ex.Message); consumerClient.Close(); return; } //Logger.Debug("consumer已连接:" + consumerClient.Client.RemoteEndPoint.ToString()); ServerContext.ConnectCount += 1; //TODO 如果NSPApp中是http,则需要进一步分离,通过GetHTTPClient来分出对应的client以建立隧道 //if() //II.弹出先前已经准备好的socket tunnel.ClientServerClient = s2pClient; //✳关键过程✳ //III.发送一个字节过去促使客户端建立转发隧道,至此隧道已打通 //客户端接收到此消息后,会另外分配一个备用连接 await s2pClient.GetStream().WriteAndFlushAsync(new byte[] { 0x01 }, 0, 1); //预发送bytes,因为这部分用来抓host消费掉了,所以直接转发 if (restBytes != null) { _ = s2pClient.GetStream().WriteAsync(restBytes, 0, restBytesLength, ct); } await TcpTransferAsync(consumerClient, s2pClient, clientApp, ct); }