/// <summary>
        /// Resolves local IP to public IP using STUN.
        /// </summary>
        /// <param name="stunServer">STUN server.</param>
        /// <param name="port">STUN server port. Default port is 3478.</param>
        /// <param name="localIP">Local IP address.</param>
        /// <returns>Returns public IP address.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>stunServer</b> or <b>localIP</b> is null reference.</exception>
        /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception>
        /// <exception cref="IOException">Is raised when no connection to STUN server.</exception>
        public static IPAddress GetPublicIP(string stunServer, int port, IPAddress localIP)
        {
            if (stunServer == null)
            {
                throw new ArgumentNullException("stunServer");
            }
            if (stunServer == "")
            {
                throw new ArgumentException("Argument 'stunServer' value must be specified.");
            }
            if (port < 1)
            {
                throw new ArgumentException("Invalid argument 'port' value.");
            }
            if (localIP == null)
            {
                throw new ArgumentNullException("localIP");
            }

            if (!Net_Utils.IsPrivateIP(localIP))
            {
                return(localIP);
            }

            STUN_Result result = Query(stunServer, port, Net_Utils.CreateSocket(new IPEndPoint(localIP, 0), ProtocolType.Udp));

            if (result.PublicEndPoint != null)
            {
                return(result.PublicEndPoint.Address);
            }
            else
            {
                throw new IOException("Failed to STUN public IP address. STUN server name is invalid or firewall blocks STUN.");
            }
        }
示例#2
0
        /// <summary>
        /// Starts UDP server.
        /// </summary>
        public void Start()
        {
            if (m_IsRunning)
            {
                return;
            }
            m_IsRunning = true;

            m_StartTime      = DateTime.Now;
            m_pDataReceivers = new List <UDP_DataReceiver>();

            // Run only if we have some listening point.
            if (m_pBindings != null)
            {
                // We must replace IPAddress.Any to all available IPs, otherwise it's impossible to send
                // reply back to UDP packet sender on same local EP where packet received. This is very
                // important when clients are behind NAT.
                List <IPEndPoint> listeningEPs = new List <IPEndPoint>();
                foreach (IPEndPoint ep in m_pBindings)
                {
                    if (ep.Address.Equals(IPAddress.Any))
                    {
                        // Add localhost.
                        IPEndPoint epLocalhost = new IPEndPoint(IPAddress.Loopback, ep.Port);
                        if (!listeningEPs.Contains(epLocalhost))
                        {
                            listeningEPs.Add(epLocalhost);
                        }
                        // Add all host IPs.
                        foreach (IPAddress ip in System.Net.Dns.GetHostAddresses(""))
                        {
                            IPEndPoint epNew = new IPEndPoint(ip, ep.Port);
                            if (!listeningEPs.Contains(epNew))
                            {
                                listeningEPs.Add(epNew);
                            }
                        }
                    }
                    else
                    {
                        if (!listeningEPs.Contains(ep))
                        {
                            listeningEPs.Add(ep);
                        }
                    }
                }

                uint IOC_IN            = 0x80000000;
                uint IOC_VENDOR        = 0x18000000;
                uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;

                // Create sockets.
                m_pSockets = new List <Socket>();
                foreach (IPEndPoint ep in listeningEPs)
                {
                    try{
                        Socket socket = Net_Utils.CreateSocket(ep, ProtocolType.Udp);

                        // To avoid : "An existing connection was forcibly closed by the remote host"

                        socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);

                        m_pSockets.Add(socket);

                        // Create UDP data receivers.
                        for (int i = 0; i < m_ReceiversPerSocket; i++)
                        {
                            UDP_DataReceiver receiver = new UDP_DataReceiver(socket);
                            receiver.PacketReceived += delegate(object s, UDP_e_PacketReceived e){
                                try{
                                    ProcessUdpPacket(e);
                                }
                                catch (Exception x) {
                                    OnError(x);
                                }
                            };
                            receiver.Error += delegate(object s, ExceptionEventArgs e){
                                OnError(e.Exception);
                            };
                            m_pDataReceivers.Add(receiver);
                            receiver.Start();
                        }
                    }
                    catch (Exception x) {
                        OnError(x);
                    }
                }

                // Create round-robin send sockets. NOTE: We must skip localhost, it can't be used
                // for sending out of server.
                m_pSendSocketsIPv4 = new CircleCollection <Socket>();
                m_pSendSocketsIPv6 = new CircleCollection <Socket>();
                foreach (Socket socket in m_pSockets)
                {
                    if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetwork)
                    {
                        if (!((IPEndPoint)socket.LocalEndPoint).Address.Equals(IPAddress.Loopback))
                        {
                            m_pSendSocketsIPv4.Add(socket);
                        }
                    }
                    else if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        m_pSendSocketsIPv6.Add(socket);
                    }
                }
            }
        }
示例#3
0
        /// <summary>
        /// Starts UDP server.
        /// </summary>
        public void Start()
        {
            if (m_IsRunning)
            {
                return;
            }
            m_IsRunning = true;

            m_StartTime      = DateTime.Now;
            m_pQueuedPackets = new Queue <UdpPacket>();

            // Run only if we have some listening point.
            if (m_pBindings != null)
            {
                // We must replace IPAddress.Any to all available IPs, otherwise it's impossible to send
                // reply back to UDP packet sender on same local EP where packet received. This is very
                // important when clients are behind NAT.
                List <IPEndPoint> listeningEPs = new List <IPEndPoint>();
                foreach (IPEndPoint ep in m_pBindings)
                {
                    if (ep.Address.Equals(IPAddress.Any))
                    {
                        // Add localhost.
                        IPEndPoint epLocalhost = new IPEndPoint(IPAddress.Loopback, ep.Port);
                        if (!listeningEPs.Contains(epLocalhost))
                        {
                            listeningEPs.Add(epLocalhost);
                        }
                        // Add all host IPs.
                        foreach (IPAddress ip in System.Net.Dns.GetHostAddresses(""))
                        {
                            IPEndPoint epNew = new IPEndPoint(ip, ep.Port);
                            if (!listeningEPs.Contains(epNew))
                            {
                                listeningEPs.Add(epNew);
                            }
                        }
                    }
                    else
                    {
                        if (!listeningEPs.Contains(ep))
                        {
                            listeningEPs.Add(ep);
                        }
                    }
                }

                // Create sockets.
                m_pSockets = new List <Socket>();
                foreach (IPEndPoint ep in listeningEPs)
                {
                    try{
                        m_pSockets.Add(Net_Utils.CreateSocket(ep, ProtocolType.Udp));
                    }
                    catch (Exception x) {
                        OnError(x);
                    }
                }

                // Create round-robin send sockets. NOTE: We must skip localhost, it can't be used
                // for sending out of server.
                m_pSendSocketsIPv4 = new CircleCollection <Socket>();
                m_pSendSocketsIPv6 = new CircleCollection <Socket>();
                foreach (Socket socket in m_pSockets)
                {
                    if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetwork)
                    {
                        if (!((IPEndPoint)socket.LocalEndPoint).Address.Equals(IPAddress.Loopback))
                        {
                            m_pSendSocketsIPv4.Add(socket);
                        }
                    }
                    else if (((IPEndPoint)socket.LocalEndPoint).AddressFamily == AddressFamily.InterNetworkV6)
                    {
                        m_pSendSocketsIPv6.Add(socket);
                    }
                }

                Thread tr = new Thread(new ThreadStart(this.ProcessIncomingUdp));
                tr.Start();
                Thread tr2 = new Thread(new ThreadStart(this.ProcessQueuedPackets));
                tr2.Start();
            }
        }