Beispiel #1
0
        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;
            }
            }
        }