/// <summary> /// Does STUN transaction. Returns transaction response or null if transaction failed. /// </summary> /// <param name="request">STUN message.</param> /// <param name="socket">Socket to use for send/receive.</param> /// <param name="remoteEndPoint">Remote end point.</param> /// <param name="timeout">Timeout in milliseconds.</param> /// <returns>Returns transaction response or null if transaction failed.</returns> private static StunMessage DoTransaction(StunMessage request, Socket socket, IPEndPoint remoteEndPoint, int timeout) { var requestBytes = request.ToByteData(); var startTime = DateTime.Now; // Retransmit with 500 ms. while (startTime.AddMilliseconds(timeout) > DateTime.Now) { try { socket.SendTo(requestBytes, remoteEndPoint); // We got response. if (socket.Poll(500 * 1000, SelectMode.SelectRead)) { var receiveBuffer = new byte[512]; socket.Receive(receiveBuffer); // Parse message var response = new StunMessage(); response.Parse(receiveBuffer); // Check that transaction ID matches or not response what we want. if (NetUtils.CompareArray(request.TransactionId, response.TransactionId)) { return(response); } } } catch { // ignored } } return(null); }