public async void CheckSuccessfulConnectionForRelayCandidatesUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            using (MockTurnServer mockTurnServer = new MockTurnServer())
            {
                var iceServers = new List <RTCIceServer> {
                    new RTCIceServer
                    {
                        urls = $"turn:{mockTurnServer.ListeningEndPoint}",
                    }
                };
                var rtpIceChannelRelay = new RtpIceChannel(null, RTCIceComponent.rtp, iceServers, RTCIceTransportPolicy.relay);
                rtpIceChannelRelay.IsController = true;
                logger.LogDebug($"RTP ICE channel RTP socket local end point {rtpIceChannelRelay.RTPLocalEndPoint}.");

                var rtpIceChannelHost = new RtpIceChannel();
                logger.LogDebug($"RTP ICE channel RTP socket local end point {rtpIceChannelHost.RTPLocalEndPoint}.");

                rtpIceChannelRelay.StartGathering();
                rtpIceChannelHost.StartGathering();

                // Need to give some time for the relay channel to connect to the mock TURN server.
                await Task.Delay(200);

                Assert.Single(rtpIceChannelRelay.Candidates);   // Should only have the single local relay candidate.
                Assert.NotEmpty(rtpIceChannelHost.Candidates);
                Assert.Equal(RTCIceGatheringState.complete, rtpIceChannelRelay.IceGatheringState);
                Assert.Equal(RTCIceConnectionState.@new, rtpIceChannelRelay.IceConnectionState);
                Assert.Equal(RTCIceGatheringState.complete, rtpIceChannelHost.IceGatheringState);
                Assert.Equal(RTCIceConnectionState.@new, rtpIceChannelHost.IceConnectionState);

                // Exchange ICE user and passwords.
                rtpIceChannelRelay.SetRemoteCredentials(rtpIceChannelHost.LocalIceUser, rtpIceChannelHost.LocalIcePassword);
                rtpIceChannelHost.SetRemoteCredentials(rtpIceChannelRelay.LocalIceUser, rtpIceChannelRelay.LocalIcePassword);

                Assert.Equal(RTCIceConnectionState.checking, rtpIceChannelRelay.IceConnectionState);
                Assert.Equal(RTCIceConnectionState.checking, rtpIceChannelHost.IceConnectionState);

                // Exchange ICE candidates.
                rtpIceChannelRelay.Candidates.ForEach(x => rtpIceChannelHost.AddRemoteCandidate(x));
                rtpIceChannelHost.Candidates.ForEach(x => rtpIceChannelRelay.AddRemoteCandidate(x));

                await Task.Delay(1000);

                Assert.Equal(RTCIceConnectionState.connected, rtpIceChannelRelay.IceConnectionState);
                Assert.Equal(RTCIceConnectionState.connected, rtpIceChannelHost.IceConnectionState);
                Assert.NotNull(rtpIceChannelRelay.NominatedEntry);
                Assert.NotNull(rtpIceChannelHost.NominatedEntry);
            }
        }
        public async void CheckIPAddressOnlyStunServerUnitTest()
        {
            logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);
            logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name);

            using (MockTurnServer mockStunServer = new MockTurnServer())
            {
                // Give the TURN server socket receive tasks time to fire up.
                await Task.Delay(1000);

                var iceServers = new List <RTCIceServer> {
                    new RTCIceServer
                    {
                        urls = $"stun:{mockStunServer.ListeningEndPoint}",
                    }
                };
                var rtpIceChannel = new RtpIceChannel(null, RTCIceComponent.rtp, iceServers);
                logger.LogDebug($"RTP ICE channel RTP socket local end point {rtpIceChannel.RTPLocalEndPoint}.");

                ManualResetEventSlim gatheringCompleted = new ManualResetEventSlim();
                rtpIceChannel.OnIceGatheringStateChange += (state) => { if (state == RTCIceGatheringState.complete)
                                                                        {
                                                                            gatheringCompleted.Set();
                                                                        }
                };

                rtpIceChannel.StartGathering();

                Assert.NotEmpty(rtpIceChannel.Candidates);

                // Because there is an ICE server gathering should still be in progress.
                Assert.Equal(RTCIceGatheringState.gathering, rtpIceChannel.IceGatheringState);
                Assert.Equal(RTCIceConnectionState.@new, rtpIceChannel.IceConnectionState);

                Assert.True(gatheringCompleted.Wait(3000));

                // The STUN server check should now have completed and a server reflexive candidate
                // been acquired

                Assert.Equal(RTCIceGatheringState.complete, rtpIceChannel.IceGatheringState);
                // The connection state stays in "new" because no remote ICE user and password has been set.
                Assert.Equal(RTCIceConnectionState.@new, rtpIceChannel.IceConnectionState);
                Assert.Contains(rtpIceChannel.Candidates, x => x.type == RTCIceCandidateType.srflx);
            }
        }