public async Task <bool> CheckUdpHolePunchingAvailable()
        {
            if (!_remoteConnectionInformation.UdpConnectionInformation.IsHolePunchingPossible)
            {
                return(false);
            }

            return(await Task.Run(() =>
            {
                var ipAddress = NetworkUtilities.GetLanIp();
                using (var socket = new Socket(SocketType.Dgram, ProtocolType.Udp))
                {
                    socket.Bind(new IPEndPoint(ipAddress, 3478));

                    IPEndPoint ipEndPoint;

                    if (SessionTraversalUtilitiesForNAT.IsHolePunchingPossible(socket, out ipEndPoint))
                    {
                        return true;
                    }

                    socket.Close();
                }

                return false;
            }));
        }
        public IConnection InitializeUdpHolePunchingConnection(out Guid connectionGuid)
        {
            var config = new NetPeerConfiguration("RemoteDesktopUdpHolePunching")
            {
                LocalAddress = _localIpAddress.Value
            };

            config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);

            var netClient = new NetClient(config);

            netClient.InitializeSocket();

            var isBlocking = netClient.Socket.Blocking;

            netClient.Socket.Blocking = true;

            var result = SessionTraversalUtilitiesForNAT.TestStun(SessionTraversalUtilitiesForNAT.GoogleStunServer,
                                                                  SessionTraversalUtilitiesForNAT.GoogleStunServerPort, netClient.Socket);

            netClient.Socket.Blocking = isBlocking;

            if (!SessionTraversalUtilitiesForNAT.IsHolePunchingPossible(result.NetType))
            {
                throw new ConnectionException(
                          "STUN server responded with: " + result.NetType + ". Hole punching not possible",
                          ConnectionType.UdpHolePunching);
            }

            netClient.InitializeLoop();

            UdpHolePunchingFeedback holePunchingFeedback;

            try
            {
                holePunchingFeedback = _dtpFactory.ExecuteFunction <UdpHolePunchingFeedback>("InitializeUdpPunchHolingConnection");
            }
            catch (Exception ex)
            {
                throw new ConnectionException("(Client) " + ex.Message, ConnectionType.UdpHolePunching);
            }

            connectionGuid = holePunchingFeedback.ConnectionGuid;

            netClient.NatIntroduction(true, null, holePunchingFeedback.PublicEndPoint, "GARYFUCKINGWASHINGTON");
            _dtpFactory.ExecuteProcedure("ConnectUdpPunchHolingConnection", connectionGuid, result.PublicEndPoint);

            netClient.WaitMessage(int.MaxValue);

            return(new ServerConnection());
        }
        public RemoteConnectionInformation GetCoreInformation(ConnectionProtocol connectionProtocol)
        {
            var information = new RemoteConnectionInformation {
                LocalIpAddress = NetworkUtilities.GetLanIp()
            };

            if ((connectionProtocol & ConnectionProtocol.Tcp) == ConnectionProtocol.Tcp)
            {
                //nothing available currently
            }

            if ((connectionProtocol & ConnectionProtocol.Udp) == ConnectionProtocol.Udp)
            {
                information.UdpConnectionInformation = new UdpConnectionInformation();

                try
                {
                    var ipAddress = NetworkUtilities.GetLanIp();
                    var socket    = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    socket.Bind(new IPEndPoint(ipAddress, 3478));

                    IPEndPoint ipEndPoint;

                    if (SessionTraversalUtilitiesForNAT.IsHolePunchingPossible(socket, out ipEndPoint))
                    {
                        information.UdpConnectionInformation.IsHolePunchingPossible = true;
                    }
                    socket.Close();
                }
                catch (Exception)
                {
                    // ignored
                }
            }

            return(information);
        }
        public UdpHolePunchingFeedback InitializeUdpPunchHolingConnection()
        {
            var config = new NetPeerConfiguration("RemoteDesktopUdpHolePunching")
            {
                LocalAddress = LocalAddress
            };

            config.EnableMessageType(NetIncomingMessageType.NatIntroductionSuccess);

            var netClient = new NetClient(config);

            netClient.InitializeSocket();

            var isBlocking = netClient.Socket.Blocking;

            netClient.Socket.Blocking = true;

            var result = SessionTraversalUtilitiesForNAT.TestStun(SessionTraversalUtilitiesForNAT.GoogleStunServer,
                                                                  SessionTraversalUtilitiesForNAT.GoogleStunServerPort, netClient.Socket);

            netClient.Socket.Blocking = isBlocking;

            if (!SessionTraversalUtilitiesForNAT.IsHolePunchingPossible(result.NetType))
            {
                throw new Exception(
                          "STUN server responded with: " + result.NetType + ". Hole punching not possible");
            }

            netClient.InitializeLoop();

            var connectionGuid = Guid.NewGuid();

            _connections.Add(connectionGuid, new UdpHolePunchingConnection(netClient));
            return(new UdpHolePunchingFeedback {
                ConnectionGuid = connectionGuid, PublicEndPoint = result.PublicEndPoint
            });
        }