private async Task<UdpClient> PerformNATPunchthroughInternal(TempSessionWithSecrets userSession, UdpClient specificUdpClient, int timeout)
{
var natPunchthroughApi = new NATPunchthroughApi();
natPunchthroughApi.Configuration.ApiKey["api_key"] = userSession.ApiKey;
var start = DateTime.UtcNow;
var udpClient = specificUdpClient ?? new UdpClient();
while (true)
{
var negotation = await natPunchthroughApi.PunchthroughPutAsync(userSession.Id);
if (negotation.Port == null)
{
throw new InvalidOperationException();
}
await udpClient.SendAsync(
negotation.Message,
negotation.Message.Length,
negotation.Host,
negotation.Port.Value);
await Task.Delay(100);
if (await natPunchthroughApi.PunchthroughGetAsync(userSession.Id) == true)
{
// NAT punchthrough completed successfully.
return udpClient;
}
if (timeout > 0 && (DateTime.UtcNow - start).TotalMilliseconds > timeout)
{
throw new TimeoutException("Unable to perform NAT punchthrough before the timeout occurred.");
}
await Task.Delay(100);
}
}
}