private void ContinuousNATPunchthrough(BackgroundNATPunchthrough punchthrough)
        {
            var natPunchthroughApi = new NATPunchthroughApi();

            natPunchthroughApi.Configuration.ApiKey["api_key"] = punchthrough.UserSession.ApiKey;

            while (!punchthrough.ShouldStop)
            {
                var udpClient = punchthrough.UdpClient;

                while (true)
                {
                    NATNegotation negotation;
                    try
                    {
                        negotation = natPunchthroughApi.PunchthroughPut(punchthrough.UserSession.Id);
                    }
                    catch
                    {
                        continue;
                    }

                    if (negotation.Port == null)
                    {
                        throw new InvalidOperationException();
                    }

                    udpClient.Send(
                        negotation.Message,
                        negotation.Message.Length,
                        negotation.Host,
                        negotation.Port.Value);

                    Thread.Sleep(1000);

                    try
                    {
                        if (natPunchthroughApi.PunchthroughGet(punchthrough.UserSession.Id) == true)
                        {
                            // NAT punchthrough completed successfully.
                            continue;
                        }
                    }
                    catch
                    {
                        continue;
                    }

                    Thread.Sleep(1000);
                }
            }
        }
        public async Task<BackgroundNATPunchthrough> StartBackgroundNATPunchthrough(TempSessionWithSecrets userSession, UdpClient udpClient)
        {
            // Do the first operation inline, because we need to send at least one packet to
            // give the UDP client a port.
            await PerformNATPunchthroughInternal(userSession, udpClient, 60000);

            var backgroundPunchthrough = new BackgroundNATPunchthrough(userSession, udpClient);
            var thread = new Thread(() => ContinuousNATPunchthrough(backgroundPunchthrough));
            thread.Name = "NAT Punchthrough";
            thread.IsBackground = true;
            thread.Start();
            return backgroundPunchthrough;
        }
        public async Task<BackgroundNATPunchthrough> StartBackgroundNATPunchthrough(TempSessionWithSecrets userSession, UdpClient udpClient)
        {
            // Do the first operation inline, because we need to send at least one packet to
            // give the UDP client a port.
            await PerformNATPunchthroughInternal(userSession, udpClient, 60000);

            var backgroundPunchthrough = new BackgroundNATPunchthrough(userSession, udpClient);
            var thread = new Thread(() => ContinuousNATPunchthrough(backgroundPunchthrough));
            thread.Name = "NAT Punchthrough";
            thread.IsBackground = true;
            thread.Start();
            return backgroundPunchthrough;
        }
        private void ContinuousNATPunchthrough(BackgroundNATPunchthrough punchthrough)
        {
            var natPunchthroughApi = new NATPunchthroughApi();
            natPunchthroughApi.Configuration.ApiKey["api_key"] = punchthrough.UserSession.ApiKey;

            while (!punchthrough.ShouldStop)
            {
                var udpClient = punchthrough.UdpClient;

                while (true)
                {
                    NATNegotation negotation;
                    try
                    {
                        negotation = natPunchthroughApi.PunchthroughPut(punchthrough.UserSession.Id);
                    }
                    catch
                    {
                        continue;
                    }

                    if (negotation.Port == null)
                    {
                        throw new InvalidOperationException();
                    }

                    udpClient.Send(
                        negotation.Message,
                        negotation.Message.Length,
                        negotation.Host,
                        negotation.Port.Value);

                    Thread.Sleep(1000);

                    try
                    {
                        if (natPunchthroughApi.PunchthroughGet(punchthrough.UserSession.Id) == true)
                        {
                            // NAT punchthrough completed successfully.
                            continue;
                        }
                    }
                    catch
                    {
                        continue;
                    }

                    Thread.Sleep(1000);
                }
            }
        }
 public async Task StopBackgroundNATPunchthrough(BackgroundNATPunchthrough backgroundNatPunchthrough)
 {
     backgroundNatPunchthrough.ShouldStop = true;
 }
 public async Task StopBackgroundNATPunchthrough(BackgroundNATPunchthrough backgroundNatPunchthrough)
 {
     backgroundNatPunchthrough.ShouldStop = true;
 }