private static void CheckConnectTimeout(this RouterComponent self, long timeNow) { // 检查连接过程超时 using (ListComponent <long> listComponent = ListComponent <long> .Create()) { foreach (var kv in self.ConnectIdNodes) { if (timeNow < kv.Value.LastRecvOuterTime + 10 * 1000) { continue; } listComponent.Add(kv.Value.Id); } foreach (long id in listComponent) { self.OnError(id, ErrorCore.ERR_KcpRouterConnectFail); } } // 外网消息超时就断开,内网因为会一直重发,没有重连之前内网连接一直存在,会导致router一直收到内网消息 using (ListComponent <long> listComponent = ListComponent <long> .Create()) { foreach (var kv in self.OuterNodes) { // 比session超时应该多10秒钟 if (timeNow < kv.Value.LastRecvOuterTime + ConstValue.SessionTimeoutTime + 10 * 1000) { continue; } listComponent.Add(kv.Value.Id); } foreach (long id in listComponent) { self.OnError(id, ErrorCore.ERR_KcpRouterTimeout); } } }
private static void RecvOuterHandler(this RouterComponent self, int messageLength, long timeNow) { // 长度小于1,不是正常的消息 if (messageLength < 1) { return; } // accept byte flag = self.Cache[0]; switch (flag) { case KcpProtocalType.RouterReconnectSYN: { if (messageLength < 13) { break; } uint outerConn = BitConverter.ToUInt32(self.Cache, 1); uint innerConn = BitConverter.ToUInt32(self.Cache, 5); uint connectId = BitConverter.ToUInt32(self.Cache, 9); string realAddress = self.Cache.ToStr(13, messageLength - 13); RouterNode routerNode; // RouterAck之后ConnectIdNodes会删除,加入到OuterNodes中来 if (!self.OuterNodes.TryGetValue(outerConn, out routerNode)) { self.ConnectIdNodes.TryGetValue(connectId, out routerNode); if (routerNode == null) { Log.Info($"router create reconnect: {self.IPEndPoint} {realAddress} {connectId} {outerConn} {innerConn}"); routerNode = self.New(realAddress, connectId, outerConn, innerConn, self.CloneAddress()); // self.OuterNodes 这里不能add,因为还没验证完成,要在RouterAck中加入 } } if (routerNode.ConnectId != connectId) { Log.Warning($"kcp router router reconnect connectId diff1: {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}"); break; } // 不是自己的,outerConn冲突, 直接break,也就是说这个软路由上有个跟自己outerConn冲突的连接,就不能连接了 // 这个路由连接不上,客户端会换个软路由,所以没关系 if (routerNode.InnerConn != innerConn) { Log.Warning($"kcp router router reconnect inner conn diff1: {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}"); break; } if (routerNode.OuterConn != outerConn) { Log.Warning($"kcp router router reconnect outer conn diff1: {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}"); break; } // 校验ip,连接过程中ip不能变化 if (!Equals(routerNode.SyncIpEndPoint, self.IPEndPoint)) { Log.Warning($"kcp router syn ip is diff1: {routerNode.SyncIpEndPoint} {(IPEndPoint) self.IPEndPoint}"); break; } // 校验内网地址 if (routerNode.InnerAddress != realAddress) { Log.Warning($"router sync error2: {routerNode.OuterConn} {routerNode.InnerAddress} {outerConn} {realAddress}"); break; } if (++routerNode.RouterSyncCount > 40) { self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterRouterSyncCountTooMuchTimes); break; } // 转发到内网 self.Cache.WriteTo(0, KcpProtocalType.RouterReconnectSYN); self.Cache.WriteTo(1, outerConn); self.Cache.WriteTo(5, innerConn); self.Cache.WriteTo(9, connectId); self.InnerSocket.SendTo(self.Cache, 0, 13, SocketFlags.None, routerNode.InnerIpEndPoint); if (!routerNode.CheckOuterCount(timeNow)) { self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterTooManyPackets); } break; } case KcpProtocalType.RouterSYN: { if (messageLength < 13) { break; } uint outerConn = BitConverter.ToUInt32(self.Cache, 1); uint innerConn = BitConverter.ToUInt32(self.Cache, 5); uint connectId = BitConverter.ToUInt32(self.Cache, 9); string realAddress = self.Cache.ToStr(13, messageLength - 13); RouterNode routerNode; self.ConnectIdNodes.TryGetValue(connectId, out routerNode); if (routerNode == null) { outerConn = RandomHelper.RandUInt32(); routerNode = self.New(realAddress, connectId, outerConn, innerConn, self.CloneAddress()); Log.Info($"router create: {realAddress} {connectId} {outerConn} {innerConn} {routerNode.SyncIpEndPoint}"); self.OuterNodes.Add(routerNode.OuterConn, routerNode); } if (++routerNode.RouterSyncCount > 40) { self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterRouterSyncCountTooMuchTimes); break; } // 校验ip,连接过程中ip不能变化 if (!Equals(routerNode.SyncIpEndPoint, self.IPEndPoint)) { Log.Warning($"kcp router syn ip is diff1: {routerNode.SyncIpEndPoint} {self.IPEndPoint}"); break; } // 校验内网地址 if (routerNode.InnerAddress != realAddress) { Log.Warning($"router sync error2: {routerNode.OuterConn} {routerNode.InnerAddress} {outerConn} {realAddress}"); break; } self.Cache.WriteTo(0, KcpProtocalType.RouterACK); self.Cache.WriteTo(1, routerNode.InnerConn); self.Cache.WriteTo(5, routerNode.OuterConn); self.OuterSocket.SendTo(self.Cache, 0, 9, SocketFlags.None, routerNode.SyncIpEndPoint); if (!routerNode.CheckOuterCount(timeNow)) { self.OnError(routerNode.Id, ErrorCore.ERR_KcpRouterTooManyPackets); } break; } case KcpProtocalType.SYN: { // 长度!=13,不是accpet消息 if (messageLength != 9) { break; } uint outerConn = BitConverter.ToUInt32(self.Cache, 1); // remote uint innerConn = BitConverter.ToUInt32(self.Cache, 5); if (!self.OuterNodes.TryGetValue(outerConn, out RouterNode kcpRouter)) { Log.Warning($"kcp router syn not found outer nodes: {outerConn} {innerConn}"); break; } if (++kcpRouter.SyncCount > 40) { self.OnError(kcpRouter.Id, ErrorCore.ERR_KcpRouterSyncCountTooMuchTimes); break; } // 校验ip,连接过程中ip不能变化 IPEndPoint ipEndPoint = (IPEndPoint)self.IPEndPoint; if (!Equals(kcpRouter.SyncIpEndPoint.Address, ipEndPoint.Address)) { Log.Warning($"kcp router syn ip is diff3: {kcpRouter.SyncIpEndPoint.Address} {ipEndPoint.Address}"); break; } // 发了syn过来,那么RouterSyn就成功了,可以删除ConnectId self.ConnectIdNodes.Remove(kcpRouter.ConnectId); kcpRouter.LastRecvOuterTime = timeNow; kcpRouter.OuterIpEndPoint = self.CloneAddress(); // 转发到内网, 带上客户端的地址 self.Cache.WriteTo(0, KcpProtocalType.SYN); self.Cache.WriteTo(1, outerConn); self.Cache.WriteTo(5, innerConn); byte[] addressBytes = ipEndPoint.ToString().ToByteArray(); Array.Copy(addressBytes, 0, self.Cache, 9, addressBytes.Length); Log.Info($"kcp router syn: {outerConn} {innerConn} {kcpRouter.InnerIpEndPoint} {kcpRouter.OuterIpEndPoint}"); self.InnerSocket.SendTo(self.Cache, 0, 9 + addressBytes.Length, SocketFlags.None, kcpRouter.InnerIpEndPoint); if (!kcpRouter.CheckOuterCount(timeNow)) { self.OnError(kcpRouter.Id, ErrorCore.ERR_KcpRouterTooManyPackets); } break; } case KcpProtocalType.FIN: // 断开 { // 长度!=13,不是DisConnect消息 if (messageLength != 13) { break; } uint outerConn = BitConverter.ToUInt32(self.Cache, 1); uint innerConn = BitConverter.ToUInt32(self.Cache, 5); if (!self.OuterNodes.TryGetValue(outerConn, out RouterNode kcpRouter)) { Log.Warning($"kcp router outer fin not found outer nodes: {outerConn} {innerConn}"); break; } // 比对innerConn if (kcpRouter.InnerConn != innerConn) { Log.Warning($"router node innerConn error: {innerConn} {outerConn} {kcpRouter.Status}"); break; } kcpRouter.LastRecvOuterTime = timeNow; Log.Info($"kcp router outer fin: {outerConn} {innerConn} {kcpRouter.InnerIpEndPoint}"); self.InnerSocket.SendTo(self.Cache, 0, messageLength, SocketFlags.None, kcpRouter.InnerIpEndPoint); if (!kcpRouter.CheckOuterCount(timeNow)) { self.OnError(kcpRouter.Id, ErrorCore.ERR_KcpRouterTooManyPackets); } break; } case KcpProtocalType.MSG: { // 长度<9,不是Msg消息 if (messageLength < 9) { break; } // 处理chanel uint outerConn = BitConverter.ToUInt32(self.Cache, 1); // remote uint innerConn = BitConverter.ToUInt32(self.Cache, 5); // local if (!self.OuterNodes.TryGetValue(outerConn, out RouterNode kcpRouter)) { Log.Warning($"kcp router msg not found outer nodes: {outerConn} {innerConn}"); break; } if (kcpRouter.Status != RouterStatus.Msg) { Log.Warning($"router node status error: {innerConn} {outerConn} {kcpRouter.Status}"); break; } // 比对innerConn if (kcpRouter.InnerConn != innerConn) { Log.Warning($"router node innerConn error: {innerConn} {outerConn} {kcpRouter.Status}"); break; } // 重连的时候,没有经过syn阶段,可能没有设置OuterIpEndPoint,重连请求Router的Socket跟发送消息的Socket不是同一个,所以udp出来的公网地址可能会变化 if (!Equals(kcpRouter.OuterIpEndPoint, self.IPEndPoint)) { kcpRouter.OuterIpEndPoint = self.CloneAddress(); } kcpRouter.LastRecvOuterTime = timeNow; self.InnerSocket.SendTo(self.Cache, 0, messageLength, SocketFlags.None, kcpRouter.InnerIpEndPoint); if (!kcpRouter.CheckOuterCount(timeNow)) { self.OnError(kcpRouter.Id, ErrorCore.ERR_KcpRouterTooManyPackets); } break; } } }