/// <summary> /// Called when the media channels are no longer required, such as when the VoIP call using it has terminated, and all resources can be shutdown /// and closed. /// </summary> public void Close() { try { logger.Debug("RTP Manager closing."); _stop = true; if (_rtpAudioChannel != null) { _rtpAudioChannel.OnFrameReady -= AudioFrameReady; _rtpAudioChannel.Close(); } if (_rtpVideoChannel != null) { _rtpVideoChannel.OnFrameReady -= VideoFrameReady; _rtpVideoChannel.Close(); } } catch (Exception excp) { logger.Error("Exception RTP Manager Close. " + excp); } }
public void MultipleRtpChannelLoopbackUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); const int PACKET_LENGTH = 100; List <Task> tasks = new List <Task>(); for (int i = 0; i < 3; i++) { var t = Task.Run(async() => { RTPChannel channel1 = new RTPChannel(false, null); bool testResult = false; ManualResetEventSlim testCompleteEvent = new ManualResetEventSlim(false); RTPChannel channel2 = new RTPChannel(false, null); channel2.OnRTPDataReceived += (lep, rep, pkt) => { logger.LogDebug($"RTP data receive packet length {pkt.Length}."); testResult = pkt.Length == PACKET_LENGTH; testCompleteEvent.Set(); }; channel1.Start(); channel2.Start(); // Give the socket receive tasks time to fire up. await Task.Delay(2000); IPAddress channel2Address = (channel2.RTPLocalEndPoint.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Loopback : IPAddress.Loopback; IPEndPoint channel2Dst = new IPEndPoint(channel2Address, channel2.RTPPort); logger.LogDebug($"Attempting to send packet from {channel1.RTPLocalEndPoint} to {channel2Dst}."); var sendResult = channel1.SendAsync(RTPChannelSocketsEnum.RTP, channel2Dst, new byte[PACKET_LENGTH]); logger.LogDebug($"Send result {sendResult}."); testCompleteEvent.Wait(TimeSpan.FromSeconds(TEST_TIMEOUT_SECONDS)); Assert.True(testResult); channel1.Close("normal"); channel2.Close("normal"); }); tasks.Add(t); } CancellationTokenSource cts = new CancellationTokenSource(); Assert.True(Task.WaitAll(tasks.ToArray(), 10000, cts.Token)); logger.LogDebug($"Test complete."); }
public void Stop() { logger.Debug($"{ prefix } Stop consumer for { endpoint }"); if (uac.IsUACAnswered && uac.SIPDialogue != null) { uac.SIPDialogue.Hangup(transport, null); } rtpChannel.OnFrameReady -= RtpChannel_OnFrameReady; if (!rtpChannel.IsClosed) { rtpChannel.Close(); } StateChanged?.Invoke(this, new ConsumerStateEventArgs(State.Ready, endpoint, SessionId)); }
/// <summary> /// 实时视频取消 /// </summary> public void RealVideoBye() { SipInitialize(); _rtpChannel.Close(); if (_realReqSession == null) { return; } SIPRequest req = ByeRequest(); _m_sipTransport.SendRequest(_remoteEndPoint, req); }
public async void RtpChannelLoopbackUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); RTPChannel channel1 = new RTPChannel(false, null); bool testResult = false; ManualResetEventSlim testCompleteEvent = new ManualResetEventSlim(false); RTPChannel channel2 = new RTPChannel(false, null); channel2.OnRTPDataReceived += (lep, rep, pkt) => { logger.LogDebug($"RTP data receive packet length {pkt.Length}."); testResult = true; testCompleteEvent.Set(); }; channel1.Start(); channel2.Start(); // Give the socket receive tasks time to fire up. await Task.Delay(1000); IPAddress channel2Address = (channel2.RTPLocalEndPoint.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Loopback : IPAddress.Loopback; IPEndPoint channel2Dst = new IPEndPoint(channel2Address, channel2.RTPPort); logger.LogDebug($"Attempting to send packet from {channel1.RTPLocalEndPoint} to {channel2Dst}."); var sendResult = channel1.SendAsync(RTPChannelSocketsEnum.RTP, channel2Dst, new byte[] { 0x00 }); logger.LogDebug($"Send result {sendResult}."); testCompleteEvent.Wait(TimeSpan.FromSeconds(TEST_TIMEOUT_SECONDS)); Assert.True(testResult); channel1.Close("normal"); channel2.Close("normal"); logger.LogDebug($"Test complete."); }
public void RtpChannelCreateManyUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); List <RTPChannel> channels = new List <RTPChannel>(); for (int i = 0; i < 10; i++) { RTPChannel channel = new RTPChannel(true, null); channels.Add(channel); } Assert.Equal(10, channels.Count); foreach (var channel in channels) { channel.Close("normal"); } }
/// <summary> /// Called when the audo channel is no longer required, such as when the VoIP call using it has terminated, and all resources can be shutdown /// and closed. /// </summary> public void Close() { try { _audioLogger.Debug("Closing audio channel."); m_rtpChannel.Close(); if (m_recordingStarted) { m_waveInEvent.StopRecording(); } if (m_waveOut.PlaybackState == PlaybackState.Playing) { m_waveOut.Stop(); m_waveOut.Dispose(); } } catch (Exception excp) { _audioLogger.Error("Exception AudioChannel Close. " + excp.Message); } }
/// <summary> /// 停止计时器/关闭RTP通道 /// </summary> public void Stop() { if (_realTask != null) { _realTask.OnCloseRTPChannel -= Task_OnCloseRTPChannel; _realTask.Stop(); } if (_byeTask != null) { _byeTask.OnCloseRTPChannel -= Task_OnCloseRTPChannel; _byeTask.Stop(); } if (_rtpChannel != null) { _rtpChannel.OnFrameReady -= _rtpChannel_OnFrameReady; _rtpChannel.Close(); } if (m_fs != null) { m_fs.Close(); m_fs.Dispose(); m_fs = null; } }
private void Transport_SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) { var endpoint = new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, localSIPEndPoint.Port); if (sipRequest.Method == SIPMethodsEnum.INVITE) { if (transaction != null) { return; } logger.DebugFormat("{0} Incoming call from {1}", prefix, sipRequest.Header.From.FromURI.User); transaction = transport.CreateUASTransaction(sipRequest, remoteEndPoint, endpoint, null); agent = new SIPServerUserAgent( transport, null, sipRequest.Header.From.FromURI.User, null, SIPCallDirection.In, null, null, null, transaction); agent.CallCancelled += Agent_CallCancelled; agent.TransactionComplete += Agent_TransactionComplete; agent.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null); agent.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null); var answer = SDP.ParseSDPDescription(agent.CallRequest.Body); var address = IPAddress.Parse(answer.Connection.ConnectionAddress); var port = answer.Media.FirstOrDefault(m => m.Media == SDPMediaTypesEnum.audio).Port; var random = Crypto.GetRandomInt(5).ToString(); var sdp = new SDP { Version = 2, Username = "******", SessionId = random, Address = localIPEndPoint.Address.ToString(), SessionName = "redfox_" + random, Timing = "0 0", Connection = new SDPConnectionInformation(publicIPAddress.ToString()) }; rtpChannel = new RTPChannel { DontTimeout = true, RemoteEndPoint = new IPEndPoint(address, port) }; rtpChannel.SetFrameType(FrameTypesEnum.Audio); // TODO Fix hardcoded ports rtpChannel.ReservePorts(15000, 15090); rtpChannel.OnFrameReady += Channel_OnFrameReady; rtpChannel.Start(); // Send some setup parameters to punch a hole in the firewall/router rtpChannel.SendRTPRaw(new byte[] { 80, 95, 198, 88, 55, 96, 225, 141, 215, 205, 185, 242, 00 }); rtpChannel.OnControlDataReceived += (b) => { logger.Debug($"{prefix} Control Data Received; {b.Length} bytes"); }; rtpChannel.OnControlSocketDisconnected += () => { logger.Debug($"{prefix} Control Socket Disconnected"); }; var announcement = new SDPMediaAnnouncement { Media = SDPMediaTypesEnum.audio, MediaFormats = new List <SDPMediaFormat>() { new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU, "PCMU", 8000) }, Port = rtpChannel.RTPPort }; sdp.Media.Add(announcement); SetState(State.Listening, sipRequest.Header.From.FromURI.User); agent.Progress(SIPResponseStatusCodesEnum.Accepted, null, null, null, null); agent.Answer(SDP.SDP_MIME_CONTENTTYPE, sdp.ToString(), null, SIPDialogueTransferModesEnum.NotAllowed); SetState(State.Busy, ""); return; } if (sipRequest.Method == SIPMethodsEnum.BYE) { if (State != State.Busy) { return; } logger.DebugFormat("{0} Hangup from {1}", prefix, sipRequest.Header.From.FromURI.User); var noninvite = transport.CreateNonInviteTransaction(sipRequest, remoteEndPoint, endpoint, null); var response = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); noninvite.SendFinalResponse(response); SetState(State.Finished, Endpoint); rtpChannel.OnFrameReady -= Channel_OnFrameReady; rtpChannel.Close(); agent.TransactionComplete -= Agent_TransactionComplete; agent.CallCancelled -= Agent_CallCancelled; agent = null; transaction = null; SetState(State.Ready, Endpoint); return; } if (sipRequest.Method == SIPMethodsEnum.ACK) { } if (sipRequest.Method == SIPMethodsEnum.CANCEL) { } }