Beispiel #1
0
 /// <summary>查询</summary>
 /// <param name="request"></param>
 /// <param name="remoteEndPoint"></param>
 /// <returns></returns>
 public StunMessage Query(StunMessage request, IPEndPoint remoteEndPoint)
 {
     EnsureSocket();
     return(Query(Socket, request, remoteEndPoint));
 }
Beispiel #2
0
        ///// <summary>在指定服务器上执行查询</summary>
        ///// <param name="host"></param>
        ///// <param name="port"></param>
        ///// <returns></returns>
        //public StunResult QueryWithServer(String host, Int32 port = 3478)
        //{
        //    try
        //    {
        //        return QueryWithServer(NetHelper.ParseAddress(host), port);
        //    }
        //    catch { return null; }
        //}

        /// <summary>在指定服务器上执行查询</summary>
        /// <param name="address"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public StunResult QueryWithServer(IPAddress address, Int32 port)
        {
            EnsureSocket();
            var client = Socket as ISocketClient;
            var remote = new IPEndPoint(address, port);

            // Test I
            // 测试网络是否畅通
            var msg = new StunMessage
            {
                Type = StunMessageType.BindingRequest
            };
            var rs = Query(client, msg, remote);

            // UDP blocked.
            if (rs == null)
            {
                return(new StunResult(StunNetType.Blocked, null));
            }

            WriteLog("服务器:{0}", rs.ServerName);
            WriteLog("映射地址:{0}", rs.MappedAddress);
            WriteLog("源地址:{0}", rs.SourceAddress);
            WriteLog("新地址:{0}", rs.ChangedAddress);
            var remote2 = rs.ChangedAddress;

            // Test II
            // 要求改变IP和端口
            msg.ChangeIP   = true;
            msg.ChangePort = true;
            msg.ResetTransactionID();

            // 如果本地地址就是映射地址,表示没有NAT。这里的本地地址应该有问题,永远都会是0.0.0.0
            //if (client.LocalEndPoint.Equals(test1response.MappedAddress))
            var pub = rs.MappedAddress;

            if (pub != null && client.Local.Port == pub.Port && pub.Address.IsLocal())
            {
                // 要求STUN服务器从另一个地址和端口向当前映射端口发送消息。如果收到,表明是完全开放网络;如果没收到,可能是防火墙阻止了。
                rs = Query(client, msg, remote);
                // Open Internet.
                if (rs != null)
                {
                    return(new StunResult(StunNetType.OpenInternet, pub));
                }

                // Symmetric UDP firewall.
                return(new StunResult(StunNetType.SymmetricUdpFirewall, pub));
            }
            else
            {
                rs = Query(client, msg, remote);
                if (rs != null && pub == null)
                {
                    pub = rs.MappedAddress;
                }
                // Full cone NAT.
                if (rs != null)
                {
                    return(new StunResult(StunNetType.FullCone, pub));
                }

                // Test II
                msg.ChangeIP   = false;
                msg.ChangePort = false;
                msg.ResetTransactionID();

                // 如果是Tcp,这里需要准备第二个重用的Socket
                if (client.Local.IsTcp)
                {
                    EnsureSocket2();
                    client = Socket2 as ISocketClient;
                }

                rs = Query(client, msg, remote2);
                // 如果第二服务器没响应,重试
                if (rs == null)
                {
                    rs = Query(client, msg, remote2);
                }
                if (rs != null && pub == null)
                {
                    pub = rs.MappedAddress;
                }
                if (rs == null)
                {
                    return(new StunResult(StunNetType.Blocked, pub));
                }

                // 两次映射地址不一样,对称网络
                if (!rs.MappedAddress.Equals(pub))
                {
                    return(new StunResult(StunNetType.Symmetric, pub));
                }

                // Test III
                msg.ChangeIP   = false;
                msg.ChangePort = true;
                msg.ResetTransactionID();

                rs = Query(client, msg, remote2);
                if (rs != null && pub == null)
                {
                    pub = rs.MappedAddress;
                }
                // 受限
                if (rs != null)
                {
                    return(new StunResult(StunNetType.AddressRestrictedCone, pub));
                }

                // 端口受限
                return(new StunResult(StunNetType.PortRestrictedCone, pub));
            }
        }