2025-07-17 18:26:28 +08:00

92 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Net;
namespace ET.Client
{
public static partial class RouterHelper
{
// 注册router
public static async ETTask<Session> CreateRouterSession(this NetComponent netComponent, IPEndPoint address, string account, string password)
{
uint localConn = (uint)(account.GetLongHashCode() ^ password.GetLongHashCode() ^ RandomGenerator.RandUInt32());
(uint recvLocalConn, IPEndPoint routerAddress) = await GetRouterAddress(netComponent, address, localConn, 0);
if (recvLocalConn == 0)
{
throw new Exception($"get router fail: {netComponent.Root().Id} {address}");
}
Log.Info($"get router: {recvLocalConn} {routerAddress}");
Session routerSession = netComponent.Create(routerAddress, address, recvLocalConn);
routerSession.AddComponent<PingComponent>();
routerSession.AddComponent<RouterCheckComponent>();
return routerSession;
}
public static async ETTask<(uint, IPEndPoint)> GetRouterAddress(this NetComponent netComponent, IPEndPoint address, uint localConn, uint remoteConn)
{
Log.Info($"start get router address: {netComponent.Root().Id} {address} {localConn} {remoteConn}");
//return (RandomHelper.RandUInt32(), address);
RouterAddressComponent routerAddressComponent = netComponent.Root().GetComponent<RouterAddressComponent>();
IPEndPoint routerInfo = routerAddressComponent.GetAddress();
uint recvLocalConn = await netComponent.Connect(routerInfo, address, localConn, remoteConn);
Log.Info($"finish get router address: {netComponent.Root().Id} {address} {localConn} {remoteConn} {recvLocalConn} {routerInfo}");
return (recvLocalConn, routerInfo);
}
// 向router申请
private static async ETTask<uint> Connect(this NetComponent netComponent, IPEndPoint routerAddress, IPEndPoint realAddress, uint localConn, uint remoteConn)
{
uint synFlag = remoteConn == 0? KcpProtocalType.RouterSYN : KcpProtocalType.RouterReconnectSYN;
// 注意session也以localConn作为id所以这里不能用localConn作为id
long id = (long)(((ulong)localConn << 32) | remoteConn);
using RouterConnector routerConnector = netComponent.AddChildWithId<RouterConnector>(id);
int count = 20;
byte[] sendCache = new byte[512];
uint connectId = RandomGenerator.RandUInt32();
sendCache.WriteTo(0, synFlag);
sendCache.WriteTo(1, localConn);
sendCache.WriteTo(5, remoteConn);
sendCache.WriteTo(9, connectId);
byte[] addressBytes = realAddress.ToString().ToByteArray();
Array.Copy(addressBytes, 0, sendCache, 13, addressBytes.Length);
TimerComponent timerComponent = netComponent.Root().GetComponent<TimerComponent>();
Log.Info($"router connect: {localConn} {remoteConn} {routerAddress} {realAddress}");
long lastSendTimer = 0;
while (true)
{
long timeNow = TimeInfo.Instance.ClientFrameTime();
if (timeNow - lastSendTimer > 300)
{
if (--count < 0)
{
Log.Error($"router connect timeout fail! {localConn} {remoteConn} {routerAddress} {realAddress}");
return 0;
}
lastSendTimer = timeNow;
// 发送
routerConnector.Connect(sendCache, 0, addressBytes.Length + 13, routerAddress);
}
await timerComponent.WaitFrameAsync();
if (routerConnector.Flag == 0)
{
continue;
}
return localConn;
}
}
}
}