static async Task Main() { Console.WriteLine("SIPSorcery Getting Started PortAudio Demo (YMMV)"); AddConsoleLogger(); var userAgent = new SIPUserAgent(); var portAudioEndPoint = new PortAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(portAudioEndPoint.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); await Task.Delay(1000); } }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, null); var rtpSession = new WindowsAudioRtpSession(); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); Task.Delay(1000).Wait(); } // Clean up. sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(new MediaEndPoints { AudioSink = winAudio, AudioSource = winAudio }); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var rtpSession = new RtpAVSession(new AudioOptions { AudioSource = AudioSourcesEnum.Microphone }, null); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
public async Task CancelCallUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPTransport aliceTransport = new SIPTransport(); aliceTransport.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); var alice = new SIPUserAgent(aliceTransport, null, true); SIPServerUserAgent uas = null; // Auto accept but NOT answering. alice.OnIncomingCall += (ua, req) => uas = ua.AcceptCall(req); SIPTransport bobTransport = new SIPTransport(); bobTransport.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); var bob = new SIPUserAgent(bobTransport, null, true); var callTask = bob.Call(alice.ContactURI.ToString(), null, null, CreateMediaSession()); await Task.Delay(500); Assert.True(bob.IsRinging); Assert.NotNull(uas); Assert.False(uas.IsCancelled); bob.Cancel(); await Task.Delay(500); Assert.False(alice.IsCallActive); Assert.False(bob.IsCallActive); Assert.True(uas.IsCancelled); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); _waveFile = new WaveFileWriter("output.mp3", _waveFormat); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.ClientCallFailed += (uac, err, resp) => { Console.WriteLine($"Call failed {err}"); _waveFile?.Close(); }; userAgent.OnCallHungup += (dialog) => _waveFile?.Close(); WindowsAudioEndPoint winAudioEP = new WindowsAudioEndPoint(new AudioEncoder()); VoIPMediaSession voipSession = new VoIPMediaSession(winAudioEP.ToMediaEndPoints()); voipSession.OnRtpPacketReceived += OnRtpPacketReceived; // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } else { Console.WriteLine("Cancelling call"); userAgent.Cancel(); } }; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
/// <summary> /// An asynchronous task that attempts to initiate a new call to a listening UAS. /// </summary> /// <param name="sipTransport">The transport object to use for the send.</param> /// <param name="dst">The destination end point to send the request to.</param> /// <returns>True if the expected response was received, false otherwise.</returns> private static async Task <bool> InitiateCallTaskAsync(SIPTransport sipTransport, SIPURI dst) { //UdpClient hepClient = new UdpClient(0, AddressFamily.InterNetwork); try { //sipTransport.SIPRequestOutTraceEvent += (localEP, remoteEP, req) => //{ // logger.LogDebug($"Request sent: {localEP}->{remoteEP}"); // logger.LogDebug(req.ToString()); // //var hepBuffer = HepPacket.GetBytes(localEP, remoteEP, DateTimeOffset.Now, 333, "myHep", req.ToString()); // //hepClient.SendAsync(hepBuffer, hepBuffer.Length, "192.168.11.49", 9060); //}; //sipTransport.SIPResponseInTraceEvent += (localEP, remoteEP, resp) => //{ // logger.LogDebug($"Response received: {localEP}<-{remoteEP}"); // logger.LogDebug(resp.ToString()); // //var hepBuffer = HepPacket.GetBytes(remoteEP, localEP, DateTimeOffset.Now, 333, "myHep", resp.ToString()); // //hepClient.SendAsync(hepBuffer, hepBuffer.Length, "192.168.11.49", 9060); //}; var ua = new SIPUserAgent(sipTransport, null); ua.ClientCallTrying += (uac, resp) => logger.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallRinging += (uac, resp) => logger.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallFailed += (uac, err, resp) => logger.LogWarning($"{uac.CallDescriptor.To} Failed: {err}"); ua.ClientCallAnswered += (uac, resp) => logger.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); var audioOptions = new AudioSourceOptions { AudioSource = AudioSourcesEnum.Silence }; var audioExtrasSource = new AudioExtrasSource(new AudioEncoder(), audioOptions); audioExtrasSource.RestrictCodecs(new List <AudioCodecsEnum> { AudioCodecsEnum.PCMU }); var voipMediaSession = new VoIPMediaSession(new MediaEndPoints { AudioSource = audioExtrasSource }); var result = await ua.Call(dst.ToString(), null, null, voipMediaSession); ua.Hangup(); await Task.Delay(200); return(result); } catch (Exception excp) { logger.LogError($"Exception InitiateCallTaskAsync. {excp.Message}"); return(false); } }
static async Task Main() { Console.WriteLine("SIPSorcery Convert Audio"); Log = AddConsoleLogger(); //WaveFormatConversionStream converter = new WaveFormatConversionStream(_format_s16le48k, ) _waveFile = new WaveFileWriter("output_s16le48k.mp3", _format_s16le48k); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.OnCallHungup += (dialog) => { Console.WriteLine("Call hungup."); _waveFile?.Close(); }; //EnableTraceLogs(sipTransport); var audioOptions = new AudioSourceOptions { AudioSource = AudioSourcesEnum.Silence }; AudioExtrasSource audioExtrasSource = new AudioExtrasSource(new AudioEncoder(), audioOptions); audioExtrasSource.RestrictFormats((format) => format.Codec == AudioCodecsEnum.PCMU); var rtpSession = new VoIPMediaSession(new MediaEndPoints { AudioSource = audioExtrasSource }); rtpSession.OnAudioFormatsNegotiated += (formats) => { _ratio = (double)(OUT_SAMPLE_RATE / formats.First().RtpClockRate); }; rtpSession.OnRtpPacketReceived += RtpSession_OnRtpPacketReceived; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
public async Task PlaceCallUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPTransport serverTransport = new SIPTransport(); SIPUDPChannel udpChannel = new SIPUDPChannel(IPAddress.Loopback, 0); serverTransport.AddSIPChannel(udpChannel); // Set up two user agents: one to answer the test call and one to place it. SIPUserAgent userAgentServer = new SIPUserAgent(serverTransport, null); SIPUserAgent userAgentClient = new SIPUserAgent(new SIPTransport(), null); serverTransport.SIPTransportRequestReceived += async(lep, rep, req) => { logger.LogDebug("Request received: " + req.StatusLine); var uas = userAgentServer.AcceptCall(req); RtpAudioSession serverAudioSession = new RtpAudioSession( new AudioSourceOptions { AudioSource = AudioSourcesEnum.None }, new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU }); var answerResult = await userAgentServer.Answer(uas, serverAudioSession); logger.LogDebug($"Server agent answer result {answerResult}."); Assert.True(answerResult); }; var dstUri = udpChannel.GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Loopback, 0))); logger.LogDebug($"Attempting call to {dstUri.ToString()}."); RtpAudioSession clientAudioSession = new RtpAudioSession( new AudioSourceOptions { AudioSource = AudioSourcesEnum.None }, new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU }); var callResult = await userAgentClient.Call(dstUri.ToString(), null, null, clientAudioSession); logger.LogDebug($"Client agent answer result {callResult }."); Assert.True(callResult); Assert.Equal(SIPDialogueStateEnum.Confirmed, userAgentClient.Dialogue.DialogueState); Assert.Equal(SIPDialogueStateEnum.Confirmed, userAgentServer.Dialogue.DialogueState); }
static async Task DialNumber() { string fromHeader = (new SIPFromHeader(USERNAME, new SIPURI(USERNAME, DOMAIN, null), null)).ToString(); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(USERNAME, PASSWORD, DEFAULT_CALL_DESTINATION, fromHeader, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, null, null); callDescriptor.CallId = "12028883999"; userAgent = new SIPUserAgent(sipTransport, null); userAgent.ClientCallTrying += (uac, resp) => Console.WriteLine($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); userAgent.ClientCallRinging += (uac, resp) => Console.WriteLine($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); userAgent.ClientCallFailed += (uac, err, resp) => Console.WriteLine($"{uac.CallDescriptor.To} Failed: {err}, Status code: {resp?.StatusCode}"); userAgent.ClientCallAnswered += (uac, resp) => Console.WriteLine($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); userAgent.OnDtmfTone += (key, duration) => OnDtmfTone(userAgent, key, duration); userAgent.OnRtpEvent += (evt, hdr) => Console.WriteLine($"rtp event {evt.EventID}, duration {evt.Duration}, end of event {evt.EndOfEvent}, timestamp {hdr.Timestamp}, marker {hdr.MarkerBit}."); userAgent.OnCallHungup += OnHangup; var rtpSession = new RtpAVSession( new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice, AudioCodecs = new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU, SDPMediaFormatsEnum.PCMA } }, null); rtpSession.OnRtpPacketReceived += OnRtpPacketReceived; var callResult = await userAgent.Call(callDescriptor, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); if (callResult) { Console.WriteLine("Enter digits one after another"); for (int i = 0; i < 11; i++) { var p = Console.ReadLine(); await userAgent.SendDtmf(byte.Parse(p)); } } Console.WriteLine("Enter ?"); Console.ReadLine(); await userAgent.SendDtmf(35); Thread.Sleep(60000); userAgent.Hangup(); _waveFile.Dispose(); Console.WriteLine("Hangup"); }
static async Task Main() { Console.WriteLine("SIPSorcery Convert Audio"); AddConsoleLogger(); //WaveFormatConversionStream converter = new WaveFormatConversionStream(_format_s16le48k, ) _waveFile = new WaveFileWriter("output_s16le48k.mp3", _format_s16le48k); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.OnCallHungup += (dialog) => { Console.WriteLine("Call hungup."); _waveFile?.Close(); }; //EnableTraceLogs(sipTransport); var audioOptions = new AudioSourceOptions { AudioSource = AudioSourcesEnum.Silence }; var audioFormats = new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU }; var rtpSession = new RtpAudioSession(audioOptions, audioFormats); rtpSession.OnRtpPacketReceived += RtpSession_OnRtpPacketReceived; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
static async Task Main() { Console.WriteLine("SIPSorcery Play Sounds Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, null); var rtpSession = new WindowsAudioRtpSession(); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); if (callResult) { await Task.Delay(1000); await rtpSession.SendAudioFromStream(new FileStream(WELCOME_16K, FileMode.Open), AudioSamplingRatesEnum.SampleRate16KHz); await Task.Delay(1000); await rtpSession.SendAudioFromStream(new FileStream(GOODBYE_16K, FileMode.Open), AudioSamplingRatesEnum.SampleRate16KHz); } Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Give the hangup a chance to complete. await Task.Delay(1000); // Clean up. sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
static async Task Main() { Console.WriteLine("SIP Get Started"); var userAgent = new SIPUserAgent(); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); var voipMediaSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("Press any key to hangup and exit."); Console.ReadLine(); }
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); SetContentView(Resource.Layout.activity_main); var callButton = FindViewById <Button>(Resource.Id.callButton); var cancelButton = FindViewById <Button>(Resource.Id.cancelButton); var destination = FindViewById <TextView>(Resource.Id.callDestination); var statusScroll = FindViewById <ScrollView>(Resource.Id.statusScroll); var statusText = FindViewById <TextView>(Resource.Id.statusTextView); Action <string> logDelegate = (str) => { this.RunOnUiThread(() => { statusText.Append(str); statusScroll.FullScroll(FocusSearchDirection.Down); }); }; SIPSorcery.LogFactory.Set(new TextViewLoggerFactory(logDelegate)); var userAgent = new SIPUserAgent(); callButton.Click += async(sender, e) => { callButton.Enabled = false; cancelButton.Enabled = true; logDelegate($"Calling {destination.Text}...\n"); var callResult = await userAgent.Call(destination.Text, null, null, new AudioSendOnlyMediaSession()); logDelegate($"Call result {callResult}...\n"); }; cancelButton.Click += (sender, e) => { cancelButton.Enabled = false; callButton.Enabled = true; logDelegate("Cancelled.\n"); }; }
public async Task PlaceCallMismatchedCapabilitiesUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPTransport serverTransport = new SIPTransport(); SIPUDPChannel udpChannel = new SIPUDPChannel(IPAddress.Loopback, 0); serverTransport.AddSIPChannel(udpChannel); // Set up two user agents: one to answer the test call and one to place it. SIPUserAgent userAgentServer = new SIPUserAgent(serverTransport, null); SIPUserAgent userAgentClient = new SIPUserAgent(new SIPTransport(), null); serverTransport.SIPTransportRequestReceived += async(lep, rep, req) => { logger.LogDebug("Request received: " + req.StatusLine); var uas = userAgentServer.AcceptCall(req); var serverAudioSession = CreateMockVoIPMediaEndPoint(new List <AudioCodecsEnum> { AudioCodecsEnum.PCMU }); var answerResult = await userAgentServer.Answer(uas, serverAudioSession); logger.LogDebug($"Server agent answer result {answerResult}."); Assert.False(answerResult); }; var dstUri = udpChannel.GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Loopback, 0))); logger.LogDebug($"Attempting call to {dstUri.ToString()}."); var clientMediaEndPoint = CreateMockVoIPMediaEndPoint(new List <AudioCodecsEnum> { AudioCodecsEnum.G722 }); var callResult = await userAgentClient.Call(dstUri.ToString(), null, null, clientMediaEndPoint); logger.LogDebug($"Client agent answer result {callResult }."); Assert.False(callResult); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var rtpSession = new RTPMediaSession((int)SDPMediaFormatsEnum.PCMU, AddressFamily.InterNetwork); // Connect audio devices to RTP session. WaveInEvent microphone = GetAudioInputDevice(); var speaker = GetAudioOutputDevice(); ConnectAudioDevicesToRtp(rtpSession, microphone, speaker); // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); if (callResult) { Console.WriteLine("Call attempt successful."); microphone.StartRecording(); } else { Console.WriteLine("Call attempt failed."); } Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. microphone.StopRecording(); sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); _waveFile = new WaveFileWriter("output.mp3", _waveFormat); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.OnCallHungup += (dialog) => _waveFile?.Close(); var rtpSession = new RtpAVSession( new AudioOptions { AudioSource = AudioSourcesEnum.Microphone, AudioCodecs = new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU, SDPMediaFormatsEnum.PCMA } }, null); rtpSession.OnRtpPacketReceived += OnRtpPacketReceived; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
/// <summary> /// Process user key presses. /// </summary> /// <param name="exit">The cancellation token to set if the user requests to quit the application.</param> private static async Task OnKeyPress(CancellationToken exit) { try { while (!exit.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { // Place an outgoing call. var ua = new SIPUserAgent(_sipTransport, null); ua.ClientCallTrying += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallRinging += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallFailed += (uac, err) => Log.LogWarning($"{uac.CallDescriptor.To} Failed: {err}"); ua.ClientCallAnswered += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); ua.OnDtmfTone += (key, duration) => OnDtmfTone(ua, key, duration); ua.OnRtpEvent += (evt, hdr) => Log.LogDebug($"rtp event {evt.EventID}, duration {evt.Duration}, end of event {evt.EndOfEvent}, timestamp {hdr.Timestamp}, marker {hdr.MarkerBit}."); ua.OnCallHungup += OnHangup; var rtpSession = CreateRtpSession(ua, null); var callResult = await ua.Call(DEFAULT_CALL_DESTINATION, null, null, rtpSession); if (callResult) { await rtpSession.Start(); _calls.TryAdd(ua.Dialogue.CallId, ua); } } else if (keyProps.KeyChar == 'd') { if (_calls.Count == 0) { Log.LogWarning("There are no active calls."); } else { var newestCall = _calls.OrderByDescending(x => x.Value.Dialogue.Inserted).First(); byte randomDtmf = (byte)Crypto.GetRandomInt(0, 15); Log.LogInformation($"Sending DTMF {randomDtmf} to {newestCall.Key}."); await newestCall.Value.SendDtmf(randomDtmf); } } else if (keyProps.KeyChar == 'h') { if (_calls.Count == 0) { Log.LogWarning("There are no active calls."); } else { var oldestCall = _calls.OrderBy(x => x.Value.Dialogue.Inserted).First(); Log.LogInformation($"Hanging up call {oldestCall.Key}."); oldestCall.Value.OnCallHungup -= OnHangup; oldestCall.Value.Hangup(); _calls.TryRemove(oldestCall.Key, out _); } } else if (keyProps.KeyChar == 'H') { if (_calls.Count == 0) { Log.LogWarning("There are no active calls."); } else { foreach (var call in _calls) { Log.LogInformation($"Hanging up call {call.Key}."); call.Value.Hangup(); } _calls.Clear(); } } else if (keyProps.KeyChar == 'l') { if (_calls.Count == 0) { Log.LogInformation("There are no active calls."); } else { Log.LogInformation("Current call list:"); foreach (var call in _calls) { Log.LogInformation($"{call.Key}: {call.Value.Dialogue.RemoteTarget}"); } } } else if (keyProps.KeyChar == 'r') { if (_registrations.Count == 0) { Log.LogInformation("There are no active registrations."); } else { Log.LogInformation("Current registration list:"); foreach (var registration in _registrations) { Log.LogInformation($"{registration.Key}: is registered {registration.Value.IsRegistered}, last attempt at {registration.Value.LastRegisterAttemptAt}"); } } } else if (keyProps.KeyChar == 't') { if (_calls.Count == 0) { Log.LogWarning("There are no active calls."); } else { var newestCall = _calls.OrderByDescending(x => x.Value.Dialogue.Inserted).First(); Log.LogInformation($"Transferring call {newestCall.Key} to {DEFAULT_TRANSFER_DESTINATION}."); bool transferResult = await newestCall.Value.BlindTransfer(SIPURI.ParseSIPURI(DEFAULT_TRANSFER_DESTINATION), TimeSpan.FromSeconds(3), exit); if (transferResult) { Log.LogInformation($"Transferring succeeded."); // The remote party will often put us on hold after the transfer. await Task.Delay(1000); newestCall.Value.OnCallHungup -= OnHangup; newestCall.Value.Hangup(); _calls.TryRemove(newestCall.Key, out _); } else { Log.LogWarning($"Transfer attempt failed."); } } } else if (keyProps.KeyChar == 'q') { // Quit application. Log.LogInformation("Quitting"); break; } } } catch (Exception excp) { Log.LogError($"Exception OnKeyPress. {excp.Message}."); } }
static async Task Main(string[] args) { Console.WriteLine("SIPSorcery Video Phone Command Line Demo"); Console.WriteLine("Press ctrl-c to exit."); Log = AddConsoleLogger(); ManualResetEvent exitMRE = new ManualResetEvent(false); ManualResetEvent waitForCallMre = new ManualResetEvent(false); var parseResult = Parser.Default.ParseArguments <Options>(args); _options = (parseResult as Parsed <Options>)?.Value; if (parseResult.Tag != ParserResultType.NotParsed) { if (_options.ListCameras) { #region List webcams. var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); } else { var index = 0; foreach (var webcam in webcams) { Console.WriteLine($"{index}: \"{webcam.Name}\", use --cam={index}."); index++; } } #endregion } else if (_options.ListFormats != null) { #region List webcam formats. var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); } else if (_options.ListFormats >= webcams.Count) { Console.WriteLine($"No webcam available for index {_options.ListFormats}."); } else { string webcamName = webcams[_options.ListFormats.Value].Name; var formats = await WindowsVideoEndPoint.GetDeviceFrameFormats(webcamName); Console.WriteLine($"Video frame formats for {webcamName}."); foreach (var vidFmt in formats) { float vidFps = vidFmt.MediaFrameFormat.FrameRate.Numerator / vidFmt.MediaFrameFormat.FrameRate.Denominator; string pixFmt = vidFmt.MediaFrameFormat.Subtype == WindowsVideoEndPoint.MF_I420_PIXEL_FORMAT ? "I420" : vidFmt.MediaFrameFormat.Subtype; Console.WriteLine($"{vidFmt.Width}x{vidFmt.Height} {vidFps:0.##}fps {pixFmt}"); } } #endregion } else { string webcamName = null; if (_options.WebcamIndex != null) { var webcams = await WindowsVideoEndPoint.GetVideoCatpureDevices(); if (webcams == null || webcams.Count == 0) { Console.WriteLine("No webcams were found."); Application.Exit(); } else if (webcams.Count < _options.WebcamIndex) { Console.WriteLine($"No webcam available for index {_options.WebcamIndex}."); Application.Exit(); } else { webcamName = webcams[_options.WebcamIndex.Value].Name; Console.WriteLine($"Using webcam {webcamName}."); } } _sipTransport = new SIPTransport(); if (string.IsNullOrEmpty(_options.CallDestination)) { // We haven't been asked to place a call so we're listening. IPAddress listenAddress = (System.Net.Sockets.Socket.OSSupportsIPv6) ? IPAddress.IPv6Any : IPAddress.Any; var listenEndPoint = new IPEndPoint(listenAddress, SIP_PORT_DEFAULT); try { SIPUDPChannel udpChannel = new SIPUDPChannel(listenEndPoint, true); _sipTransport.AddSIPChannel(udpChannel); } catch (ApplicationException appExcp) { Console.WriteLine($"Failed to create UDP SIP channel on {listenEndPoint}, error {appExcp.Message}."); SIPUDPChannel udpChannel = new SIPUDPChannel(new IPEndPoint(listenAddress, 0), true); _sipTransport.AddSIPChannel(udpChannel); } var listeningEP = _sipTransport.GetSIPChannels().First().ListeningSIPEndPoint; Console.WriteLine($"Listening for incoming call on {listeningEP}."); } EnableTraceLogs(_sipTransport); // Open a window to display the video feed from the remote SIP party. _form = new Form(); _form.Text = string.IsNullOrEmpty(_options.CallDestination) ? "Listener" : "Caller"; _form.AutoSize = true; _form.BackgroundImageLayout = ImageLayout.Center; _localVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, 0), Visible = true }; _remoteVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, VIDEO_FRAME_HEIGHT), Visible = true }; _form.Controls.Add(_localVideoPicBox); _form.Controls.Add(_remoteVideoPicBox); var userAgent = new SIPUserAgent(_sipTransport, null, true); userAgent.OnCallHungup += (dialog) => exitMRE.Set(); WindowsAudioEndPoint windowsAudioEndPoint = null; if (!_options.NoAudio) { windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder()); windowsAudioEndPoint.RestrictFormats(x => x.Codec == AudioCodecsEnum.G722); } MediaEndPoints mediaEndPoints = null; if (_options.TestPattern && _options.WebcamIndex == null) { var testPattern = new VideoTestPatternSource(new FFmpegVideoEncoder()); var decoderSink = new DecoderVideoSink(new FFmpegVideoEncoder()); //var decoderSink = new DecoderVideoSink(new VpxVideoEncoder()); testPattern.RestrictFormats(format => format.Codec == VIDEO_CODEC); decoderSink.RestrictFormats(format => format.Codec == VIDEO_CODEC); mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = decoderSink, VideoSource = testPattern, }; } else { WindowsVideoEndPoint windowsVideoEndPoint = webcamName switch { null => new WindowsVideoEndPoint(new FFmpegVideoEncoder()), _ => new WindowsVideoEndPoint(new FFmpegVideoEncoder(), webcamName), }; windowsVideoEndPoint.RestrictFormats(format => format.Codec == VIDEO_CODEC); mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; } mediaEndPoints.VideoSource.OnVideoSourceRawSample += (uint durationMilliseconds, int width, int height, byte[] sample, VideoPixelFormatsEnum pixelFormat) => { if (_isFormActivated) { _form?.BeginInvoke(new Action(() => { if (_form.Handle != IntPtr.Zero) { int stride = width * 3; if (pixelFormat == VideoPixelFormatsEnum.I420) { sample = PixelConverter.I420toBGR(sample, width, height, out stride); } if (_localVideoPicBox.Width != width || _localVideoPicBox.Height != height) { Log.LogDebug($"Adjusting local video display from {_localVideoPicBox.Width}x{_localVideoPicBox.Height} to {width}x{height}."); _localVideoPicBox.Width = width; _localVideoPicBox.Height = height; } unsafe { fixed(byte *s = sample) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _localVideoPicBox.Image = bmpImage; } } } })); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; Log.LogInformation("Exiting..."); waitForCallMre.Set(); exitMRE.Set(); }; if (string.IsNullOrEmpty(_options.CallDestination)) { ActivateForm(); userAgent.OnIncomingCall += async(ua, req) => { var voipMediaSession = new VoIPMediaSession(mediaEndPoints); voipMediaSession.AcceptRtpFromAny = true; if (voipMediaSession.VideoLocalTrack != null) { voipMediaSession.VideoLocalTrack.MaximumBandwidth = MAXIMUM_VIDEO_BANDWIDTH; } var uas = userAgent.AcceptCall(req); await userAgent.Answer(uas, voipMediaSession); Console.WriteLine("Starting local video source..."); await mediaEndPoints.VideoSource.StartVideo().ConfigureAwait(false); waitForCallMre.Set(); }; Console.WriteLine("Waiting for incoming call..."); waitForCallMre.WaitOne(); } else { var voipMediaSession = new VoIPMediaSession(mediaEndPoints); voipMediaSession.AcceptRtpFromAny = true; if (voipMediaSession.VideoLocalTrack != null) { voipMediaSession.VideoLocalTrack.MaximumBandwidth = MAXIMUM_VIDEO_BANDWIDTH; } ActivateForm(); Console.WriteLine("Starting local video source..."); await mediaEndPoints.VideoSource.StartVideo().ConfigureAwait(false); // Place the call and wait for the result. Task <bool> callTask = userAgent.Call(_options.CallDestination, null, null, voipMediaSession); callTask.Wait(CALL_TIMEOUT_SECONDS * 1000); } if (userAgent.IsCallActive) { Log.LogInformation("Call attempt successful."); mediaEndPoints.VideoSink.OnVideoSinkDecodedSample += (byte[] bmp, uint width, uint height, int stride, VideoPixelFormatsEnum pixelFormat) => { if (_isFormActivated) { _form?.BeginInvoke(new Action(() => { if (_form.Handle != IntPtr.Zero) { unsafe { if (_remoteVideoPicBox.Width != (int)width || _remoteVideoPicBox.Height != (int)height) { Log.LogDebug($"Adjusting remote video display from {_remoteVideoPicBox.Width}x{_remoteVideoPicBox.Height} to {width}x{height}."); _remoteVideoPicBox.Width = (int)width; _remoteVideoPicBox.Height = (int)height; } fixed(byte *s = bmp) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap((int)width, (int)height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _remoteVideoPicBox.Image = bmpImage; } } } })); } }; } else { Log.LogWarning("Call attempt failed."); Console.WriteLine("Press ctrl-c to exit."); } exitMRE.WaitOne(); if (userAgent.IsCallActive) { Log.LogInformation("Hanging up."); userAgent.Hangup(); } Task.Delay(1000).Wait(); // Clean up. if (_form.Handle != IntPtr.Zero) { _form.BeginInvoke(new Action(() => _form.Close())); } _sipTransport.Shutdown(); } } }
static async Task Main() { Console.WriteLine("SIPSorcery Asterisk + ICE Demo"); AddConsoleLogger(); CancellationTokenSource exitCts = new CancellationTokenSource(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.ClientCallFailed += (uac, error, sipResponse) => Console.WriteLine($"Call failed {error}."); userAgent.OnCallHungup += async(dialog) => { // Give time for the BYE response before exiting. await Task.Delay(1000); exitCts.Cancel(); }; var audioExtras = new AudioExtrasSource(); audioExtras.SetSource(AudioSourcesEnum.PinkNoise); var testPattern = new VideoTestPatternSource(new VpxVideoEncoder()); var pc = new RTCPeerConnection(null); pc.OnAudioFormatsNegotiated += (formats) => audioExtras.SetAudioSourceFormat(formats.First()); pc.OnVideoFormatsNegotiated += (formats) => testPattern.SetVideoSourceFormat(formats.First()); var audioTrack = new MediaStreamTrack(audioExtras.GetAudioSourceFormats(), MediaStreamStatusEnum.SendOnly); pc.addTrack(audioTrack); audioExtras.OnAudioSourceEncodedSample += pc.SendAudio; var videoTrack = new MediaStreamTrack(testPattern.GetVideoSourceFormats(), MediaStreamStatusEnum.SendOnly); pc.addTrack(videoTrack); testPattern.OnVideoSourceEncodedSample += pc.SendVideo; // Diagnostics. pc.OnReceiveReport += (re, media, rr) => Console.WriteLine($"RTCP Receive for {media} from {re}\n{rr.GetDebugSummary()}"); pc.OnSendReport += (media, sr) => Console.WriteLine($"RTCP Send for {media}\n{sr.GetDebugSummary()}"); pc.GetRtpChannel().OnStunMessageReceived += (msg, ep, isRelay) => Console.WriteLine($"STUN {msg.Header.MessageType} received from {ep}."); pc.oniceconnectionstatechange += (state) => Console.WriteLine($"ICE connection state change to {state}."); // ICE connection state handler. pc.onconnectionstatechange += (state) => { Console.WriteLine($"Peer connection state change to {state}."); if (state == RTCPeerConnectionState.connected) { audioExtras.StartAudio(); testPattern.StartVideo(); } else if (state == RTCPeerConnectionState.failed) { if (userAgent.IsCallActive) { Console.WriteLine("ICE connection failed, hanging up active call."); userAgent.Hangup(); } } }; // Place the call and wait for the result. var callTask = userAgent.Call(DESTINATION, USERNAME, PASSWORD, pc); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent != null) { if (userAgent.IsCalling || userAgent.IsRinging) { Console.WriteLine("Cancelling in progress call."); userAgent.Cancel(); } else if (userAgent.IsCallActive) { Console.WriteLine("Hanging up established call."); userAgent.Hangup(); } } ; exitCts.Cancel(); }; Console.WriteLine("press ctrl-c to exit..."); bool callResult = await callTask; if (callResult) { Console.WriteLine($"Call to {DESTINATION} succeeded."); exitCts.Token.WaitHandle.WaitOne(); } else { Console.WriteLine($"Call to {DESTINATION} failed."); } Console.WriteLine("Exiting..."); if (userAgent?.IsHangingUp == true) { Console.WriteLine("Waiting 1s for the call hangup or cancel to complete..."); await Task.Delay(1000); } // Clean up. sipTransport.Shutdown(); }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Video Call Demo"); Console.WriteLine("Press ctrl-c to exit."); Log = AddConsoleLogger(); ManualResetEvent exitMRE = new ManualResetEvent(false); _sipTransport = new SIPTransport(); EnableTraceLogs(_sipTransport); // Open a window to display the video feed from the remote SIP party. _form = new Form(); _form.AutoSize = true; _form.BackgroundImageLayout = ImageLayout.Center; _localVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, 0), Visible = true }; _remoteVideoPicBox = new PictureBox { Size = new Size(VIDEO_FRAME_WIDTH, VIDEO_FRAME_HEIGHT), Location = new Point(0, VIDEO_FRAME_HEIGHT), Visible = true }; _form.Controls.Add(_localVideoPicBox); _form.Controls.Add(_remoteVideoPicBox); Application.EnableVisualStyles(); ThreadPool.QueueUserWorkItem(delegate { Application.Run(_form); }); ManualResetEvent formMre = new ManualResetEvent(false); _form.Activated += (object sender, EventArgs e) => formMre.Set(); Console.WriteLine("Waiting for form activation."); formMre.WaitOne(); _sipTransport.SIPTransportRequestReceived += OnSIPTransportRequestReceived; string executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); var userAgent = new SIPUserAgent(_sipTransport, null, true); userAgent.OnCallHungup += (dialog) => exitMRE.Set(); var windowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder()); windowsAudioEndPoint.RestrictFormats(format => format.Codec == AudioCodecsEnum.PCMU); var windowsVideoEndPoint = new WindowsVideoEndPoint(new VpxVideoEncoder()); // Fallback to a test pattern source if accessing the Windows webcam fails. var testPattern = new VideoTestPatternSource(new VpxVideoEncoder()); MediaEndPoints mediaEndPoints = new MediaEndPoints { AudioSink = windowsAudioEndPoint, AudioSource = windowsAudioEndPoint, VideoSink = windowsVideoEndPoint, VideoSource = windowsVideoEndPoint, }; var voipMediaSession = new VoIPMediaSession(mediaEndPoints, testPattern); voipMediaSession.AcceptRtpFromAny = true; windowsVideoEndPoint.OnVideoSourceRawSample += (uint durationMilliseconds, int width, int height, byte[] sample, VideoPixelFormatsEnum pixelFormat) => { _form?.BeginInvoke(new Action(() => { unsafe { fixed(byte *s = sample) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(width, height, width * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _localVideoPicBox.Image = bmpImage; } } })); }; Console.WriteLine("Starting local video source..."); await windowsVideoEndPoint.StartVideo().ConfigureAwait(false); // Place the call and wait for the result. Task <bool> callTask = userAgent.Call(DESTINATION, null, null, voipMediaSession); callTask.Wait(CALL_TIMEOUT_SECONDS * 1000); if (callTask.Result) { Log.LogInformation("Call attempt successful."); windowsVideoEndPoint.OnVideoSinkDecodedSample += (byte[] bmp, uint width, uint height, int stride, VideoPixelFormatsEnum pixelFormat) => { _form?.BeginInvoke(new Action(() => { unsafe { fixed(byte *s = bmp) { System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap((int)width, (int)height, stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)s); _remoteVideoPicBox.Image = bmpImage; } } })); }; windowsAudioEndPoint.PauseAudio().Wait(); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Music); } else { Log.LogWarning("Call attempt failed."); Console.WriteLine("Press ctrl-c to exit."); } Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; Log.LogInformation("Exiting..."); exitMRE.Set(); }; exitMRE.WaitOne(); if (userAgent.IsCallActive) { Log.LogInformation("Hanging up."); userAgent.Hangup(); Task.Delay(1000).Wait(); } // Clean up. _form.BeginInvoke(new Action(() => _form.Close())); _sipTransport.Shutdown(); }
static void Main(string[] args) { Console.WriteLine("SIPSorcery call hold example."); Console.WriteLine("Press ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. bool isCallHungup = false; bool hasCallFailed = false; AddConsoleLogger(); // Check whether an override desination has been entered on the command line. SIPURI callUri = SIPURI.ParseSIPURI(DEFAULT_DESTINATION_SIP_URI); if (args != null && args.Length > 0) { if (!SIPURI.TryParse(args[0])) { Log.LogWarning($"Command line argument could not be parsed as a SIP URI {args[0]}"); } else { callUri = SIPURI.ParseSIPURIRelaxed(args[0]); } } Log.LogInformation($"Call destination {callUri}."); // Set up a default SIP transport. _sipTransport = new SIPTransport(); _sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, 0))); EnableTraceLogs(_sipTransport); var lookupResult = SIPDNSManager.ResolveSIPService(callUri, false); Log.LogDebug($"DNS lookup result for {callUri}: {lookupResult?.GetSIPEndPoint()}."); var dstAddress = lookupResult.GetSIPEndPoint().Address; IPAddress localIPAddress = NetServices.GetLocalAddressForRemote(dstAddress); // Initialise an RTP session to receive the RTP packets from the remote SIP server. _ourRtpSocket = null; Socket controlSocket = null; NetServices.CreateRtpSocket(localIPAddress, 48000, 48100, false, out _ourRtpSocket, out controlSocket); var rtpRecvSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null); var rtpSendSession = new RTPSession((int)RTPPayloadTypesEnum.PCMU, null, null); _ourSDP = GetSDP(_ourRtpSocket.LocalEndPoint as IPEndPoint, RTP_ATTRIBUTE_SENDRECV); // Create a client/server user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var userAgent = new SIPUserAgent(_sipTransport, null); userAgent.ClientCallTrying += (uac, resp) => { Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); }; userAgent.ClientCallRinging += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); userAgent.ClientCallFailed += (uac, err) => { Log.LogWarning($"{uac.CallDescriptor.To} Failed: {err}"); hasCallFailed = true; exitCts.Cancel(); }; userAgent.ClientCallAnswered += (uac, resp) => { if (resp.Status == SIPResponseStatusCodesEnum.Ok) { Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); // Only set the remote RTP end point if there hasn't already been a packet received on it. if (_remoteRtpEndPoint == null) { _remoteRtpEndPoint = SDP.GetSDPRTPEndPoint(resp.Body); Log.LogDebug($"Remote RTP socket {_remoteRtpEndPoint}."); } } else { Log.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); } }; userAgent.CallHungup += () => { Log.LogInformation($"Call hungup by remote party."); exitCts.Cancel(); }; userAgent.OnReinviteRequest += ReinviteRequestReceived; // The only incoming requests that need to be explicitly in this example program are in-dialog // re-INVITE requests that are being used to place the call on/off hold. _sipTransport.SIPTransportRequestReceived += (localSIPEndPoint, remoteEndPoint, sipRequest) => { try { if (sipRequest.Header.From != null && sipRequest.Header.From.FromTag != null && sipRequest.Header.To != null && sipRequest.Header.To.ToTag != null) { userAgent.InDialogRequestReceivedAsync(sipRequest).Wait(); } else if (sipRequest.Method == SIPMethodsEnum.OPTIONS) { SIPResponse optionsResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); _sipTransport.SendResponse(optionsResponse); } } catch (Exception excp) { Log.LogError($"Exception processing request. {excp.Message}"); } }; // It's a good idea to start the RTP receiving socket before the call request is sent. // A SIP server will generally start sending RTP as soon as it has processed the incoming call request and // being ready to receive will stop any ICMP error response being generated. Task.Run(() => RecvRtp(_ourRtpSocket, rtpRecvSession, exitCts)); Task.Run(() => SendRtp(_ourRtpSocket, rtpSendSession, exitCts)); // Start the thread that places the call. SIPCallDescriptor callDescriptor = new SIPCallDescriptor( SIP_USERNAME, SIP_PASSWORD, callUri.ToString(), $"sip:{SIP_USERNAME}@localhost", callUri.CanonicalAddress, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, _ourSDP.ToString(), null); userAgent.Call(callDescriptor); // At this point the call has been initiated and everything will be handled in an event handler. Task.Run(() => { try { while (!exitCts.Token.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'h') { // Place call on/off hold. if (userAgent.IsAnswered) { if (_holdStatus == HoldStatus.None) { Log.LogInformation("Placing the remote call party on hold."); _holdStatus = HoldStatus.WePutOnHold; _ourSDP = GetSDP(_ourRtpSocket.LocalEndPoint as IPEndPoint, RTP_ATTRIBUTE_SENDONLY); userAgent.SendReInviteRequest(_ourSDP); } else if (_holdStatus == HoldStatus.WePutOnHold) { Log.LogInformation("Removing the remote call party from hold."); _holdStatus = HoldStatus.None; _ourSDP = GetSDP(_ourRtpSocket.LocalEndPoint as IPEndPoint, RTP_ATTRIBUTE_SENDRECV); userAgent.SendReInviteRequest(_ourSDP); } else { Log.LogInformation("Sorry we're already on hold by the remote call party."); } } } else if (keyProps.KeyChar == 'q') { // Quit application. exitCts.Cancel(); } } } catch (Exception excp) { SIPSorcery.Sys.Log.Logger.LogError($"Exception Key Press listener. {excp.Message}."); } }); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); #region Cleanup. Log.LogInformation("Exiting..."); _ourRtpSocket?.Close(); controlSocket?.Close(); if (!isCallHungup && userAgent != null) { if (userAgent.IsAnswered) { Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}."); userAgent.Hangup(); } else if (!hasCallFailed) { Log.LogInformation($"Cancelling call to {userAgent?.CallDescriptor?.To}."); userAgent.Cancel(); } // Give the BYE or CANCEL request time to be transmitted. Log.LogInformation("Waiting 1s for call to clean up..."); Task.Delay(1000).Wait(); } SIPSorcery.Net.DNSManager.Stop(); if (_sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); _sipTransport.Shutdown(); } #endregion }
static void Main() { Console.WriteLine("SIPSorcery Call Hold and Blind Transfer example."); Console.WriteLine("Press 'c' to initiate a call to the default destination."); Console.WriteLine("Press 'h' to place an established call on and off hold."); Console.WriteLine("Press 'H' to hangup an established call."); Console.WriteLine("Press 't' to request a blind transfer on an established call."); Console.WriteLine("Press 'q' or ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); Console.WriteLine($"Listening for incoming calls on: {sipTransport.GetSIPChannels().First().ListeningEndPoint}."); EnableTraceLogs(sipTransport); _currentDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); RtpAVSession rtpAVSession = null; // Create a client/server user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var userAgent = new SIPUserAgent(sipTransport, null); userAgent.RemotePutOnHold += () => Log.LogInformation("Remote call party has placed us on hold."); userAgent.RemoteTookOffHold += () => Log.LogInformation("Remote call party took us off hold."); sipTransport.SIPTransportRequestReceived += async(localEndPoint, remoteEndPoint, sipRequest) => { if (sipRequest.Header.From != null && sipRequest.Header.From.FromTag != null && sipRequest.Header.To != null && sipRequest.Header.To.ToTag != null) { // This is an in-dialog request that will be handled directly by a user agent instance. } else if (sipRequest.Method == SIPMethodsEnum.INVITE) { if (userAgent?.IsCallActive == true) { Log.LogWarning($"Busy response returned for incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}."); // If we are already on a call return a busy response. UASInviteTransaction uasTransaction = new UASInviteTransaction(sipTransport, sipRequest, null); SIPResponse busyResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.BusyHere, null); uasTransaction.SendFinalResponse(busyResponse); } else { Log.LogInformation($"Incoming call request from {remoteEndPoint}: {sipRequest.StatusLine}."); var incomingCall = userAgent.AcceptCall(sipRequest); rtpAVSession = new RtpAVSession(new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice }, null); await userAgent.Answer(incomingCall, rtpAVSession); Log.LogInformation($"Answered incoming call from {sipRequest.Header.From.FriendlyDescription()} at {remoteEndPoint}."); } } else { Log.LogDebug($"SIP {sipRequest.Method} request received but no processing has been set up for it, rejecting."); SIPResponse notAllowedResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null); await sipTransport.SendResponseAsync(notAllowedResponse); } }; // At this point the call has been initiated and everything will be handled in an event handler. Task.Run(async() => { try { while (!exitCts.Token.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { if (!userAgent.IsCallActive) { rtpAVSession = new RtpAVSession(new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice }, null); bool callResult = await userAgent.Call(DEFAULT_DESTINATION_SIP_URI, SIP_USERNAME, SIP_PASSWORD, rtpAVSession); Log.LogInformation($"Call attempt {((callResult) ? "successfull" : "failed")}."); } else { Log.LogWarning("There is already an active call."); } } else if (keyProps.KeyChar == 'h') { // Place call on/off hold. if (userAgent.IsCallActive) { if (userAgent.IsOnLocalHold) { Log.LogInformation("Taking the remote call party off hold."); userAgent.TakeOffHold(); await(userAgent.MediaSession as RtpAVSession).SetSources(new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice }, null); } else { Log.LogInformation("Placing the remote call party on hold."); userAgent.PutOnHold(); await(userAgent.MediaSession as RtpAVSession).SetSources(new AudioOptions { AudioSource = AudioSourcesEnum.Music, SourceFiles = new Dictionary <SDPMediaFormatsEnum, string> { { SDPMediaFormatsEnum.PCMU, _currentDir + "/" + AUDIO_FILE_PCMU } } }, null); } } else { Log.LogWarning("There is no active call to put on hold."); } } else if (keyProps.KeyChar == 'H') { if (userAgent.IsCallActive) { Log.LogInformation("Hanging up call."); userAgent.Hangup(); } } else if (keyProps.KeyChar == 't') { // Initiate a blind transfer to the remote call party. if (userAgent.IsCallActive) { var transferURI = SIPURI.ParseSIPURI(TRANSFER_DESTINATION_SIP_URI); bool result = await userAgent.BlindTransfer(transferURI, TimeSpan.FromSeconds(TRANSFER_TIMEOUT_SECONDS), exitCts.Token); if (result) { // If the transfer was accepted the original call will already have been hungup. // Wait a second for the transfer NOTIFY request to arrive. await Task.Delay(1000); exitCts.Cancel(); } else { Log.LogWarning($"Transfer to {TRANSFER_DESTINATION_SIP_URI} failed."); } } else { Log.LogWarning("There is no active call to transfer."); } } else if (keyProps.KeyChar == 'q') { // Quit application. exitCts.Cancel(); } } } catch (Exception excp) { SIPSorcery.Sys.Log.Logger.LogError($"Exception Key Press listener. {excp.Message}."); } }); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); #region Cleanup. Log.LogInformation("Exiting..."); rtpAVSession?.Close("app exit"); if (userAgent != null) { if (userAgent.IsCallActive) { Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}."); userAgent.Hangup(); } // Give the BYE or CANCEL request time to be transmitted. Log.LogInformation("Waiting 1s for call to clean up..."); Task.Delay(1000).Wait(); } SIPSorcery.Net.DNSManager.Stop(); if (sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } #endregion }
static async Task Main() { Console.WriteLine("SIPSorcery Getting Started Demo"); AddConsoleLogger(); _waveFile = new WaveFileWriter("output.mp3", _waveFormat); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); userAgent.ClientCallFailed += (uac, err, resp) => { Console.WriteLine($"Call failed {err}"); _waveFile?.Close(); }; userAgent.OnCallHungup += (dialog) => _waveFile?.Close(); var rtpSession = new RtpAVSession( new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice, AudioCodecs = new List <SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU, SDPMediaFormatsEnum.PCMA } }, null); rtpSession.OnRtpPacketReceived += OnRtpPacketReceived; // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } else { Console.WriteLine("Cancelling call"); userAgent.Cancel(); } }; // Place the call and wait for the result. bool callResult = await userAgent.Call(DESTINATION, null, null, rtpSession); Console.WriteLine($"Call result {((callResult) ? "success" : "failure")}."); Console.WriteLine("press any key to exit..."); Console.Read(); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); userAgent.Hangup(); } // Clean up. sipTransport.Shutdown(); }
/// <summary> /// Process user key presses. /// </summary> /// <param name="exit">The cancellation token to set if the user requests to quit the application.</param> private static void OnKeyPress(CancellationTokenSource exitCts) { try { while (!exitCts.IsCancellationRequested) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { SIPUserAgent ua = null; string dst = null; if (_transfereeCall == null) { dst = TRANSFEREE_DST; _transfereeCall = new SIPUserAgent(_sipTransport, null); ua = _transfereeCall; } else if (_targetCall == null) { dst = TARGET_DST; _targetCall = new SIPUserAgent(_sipTransport, null); ua = _targetCall; } if (ua == null) { Log.LogWarning("Cannot place a new call, both the transferee and target user agents are busy."); } else { // Place an outgoing call. ua.ClientCallTrying += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallRinging += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}."); ua.ClientCallFailed += (uac, err, resp) => Log.LogWarning($"{uac.CallDescriptor.To} Failed: {err}, Status code: {resp?.StatusCode}"); ua.ClientCallAnswered += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); ua.OnDtmfTone += (key, duration) => Log.LogInformation($"Received DTMF tone {key}."); //ua.OnRtpEvent += (evt, hdr) => Log.LogDebug($"transferee rtp event {evt.EventID}, ssrc {hdr.SyncSource}, duration {evt.Duration}, end of event {evt.EndOfEvent}, timestamp {hdr.Timestamp}, marker {hdr.MarkerBit}."); ua.OnCallHungup += (dialog) => Log.LogDebug("Call hungup by remote party."); Task.Run(async() => { var rtpSession = CreateRtpSession(); var callResult = await ua.Call(dst, null, null, rtpSession); if (!callResult) { Log.LogWarning($"Call to {dst} failed."); } else { Log.LogInformation($"Call to {dst} was successful."); } }); } } else if (keyProps.KeyChar == 'h') { if (_transfereeCall != null) { Log.LogDebug("Hanging up transferee call."); _transfereeCall.Hangup(); } if (_targetCall != null) { Log.LogDebug("Hanging up target call."); _targetCall.Hangup(); } _transfereeCall = null; _targetCall = null; } else if (keyProps.KeyChar == 't') { if (_transfereeCall == null) { Log.LogWarning("The call to the transferee is not established."); } else if (_targetCall == null) { Log.LogWarning("The call to the target is not established."); } else { Task.Run(async() => { Log.LogInformation("Initiating transfer to the transferee..."); bool transferResult = await _transfereeCall.AttendedTransfer(_targetCall.Dialogue, TimeSpan.FromSeconds(2), exitCts.Token); Log.LogDebug($"Transfer result {transferResult}."); await Task.Delay(2000); Log.LogDebug($"Transferee call status {_transfereeCall?.IsCallActive}."); Log.LogDebug($"Target call status {_targetCall?.IsCallActive}."); }); } } else if (keyProps.KeyChar == 'a') { Log.LogDebug($"Yes I am alive!"); } else if (keyProps.KeyChar == 'q') { // Quit application. Log.LogInformation("Quitting"); exitCts.Cancel(); break; } } } catch (Exception excp) { Log.LogError($"Exception OnKeyPress. {excp.Message}."); } }
public async Task HandleInvalidSdpPortOnPlaceCallUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); // This transport will act as the call receiver. It allows the test to provide a // tailored response to an incoming call. SIPTransport calleeTransport = new SIPTransport(); // This transport will be used by the SIPUserAgent being tested to place the call. SIPTransport callerTransport = new SIPTransport(); RTPSession rtpSession = new RTPSession(false, false, false); try { calleeTransport.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); calleeTransport.SIPTransportRequestReceived += async(lep, rep, req) => { if (req.Method != SIPMethodsEnum.INVITE) { SIPResponse notAllowedResponse = SIPResponse.GetResponse(req, SIPResponseStatusCodesEnum.MethodNotAllowed, null); await calleeTransport.SendResponseAsync(notAllowedResponse); } else { UASInviteTransaction uasTransaction = new UASInviteTransaction(calleeTransport, req, null); var uas = new SIPServerUserAgent(calleeTransport, null, null, null, SIPCallDirection.In, null, null, null, uasTransaction); uas.Progress(SIPResponseStatusCodesEnum.Trying, null, null, null, null); uas.Progress(SIPResponseStatusCodesEnum.Ringing, null, null, null, null); var answerSdp = @" v=0 o=- 1838015445 0 IN IP4 127.0.0.1 s=- c=IN IP4 127.0.0.1 t=0 0 m=audio 79762 RTP/AVP 0 a=rtpmap:0 PCMU/8000 a=sendrecv"; uas.Answer(SDP.SDP_MIME_CONTENTTYPE, answerSdp, null, SIPDialogueTransferModesEnum.NotAllowed); } }; SIPUserAgent userAgent = new SIPUserAgent(callerTransport, null); MediaStreamTrack audioTrack = new MediaStreamTrack(SDPMediaTypesEnum.audio, false, new List <SDPMediaFormat> { new SDPMediaFormat(SDPMediaFormatsEnum.PCMU) }); rtpSession.addTrack(audioTrack); SIPURI dstUri = new SIPURI(SIPSchemesEnum.sip, calleeTransport.GetSIPChannels().First().ListeningSIPEndPoint); var result = await userAgent.Call(dstUri.ToString(), null, null, rtpSession); Assert.False(result); } finally { rtpSession?.Close("normal"); callerTransport?.Shutdown(); calleeTransport?.Shutdown(); } }
public async Task AttendedTransfereeUnitTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); // User agents A and B can use the same transport as they don't auto-answer incoming calls. SIPTransport sipTransportCaller = new SIPTransport(); sipTransportCaller.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); var userAgentA = new SIPUserAgent(sipTransportCaller, null); var userAgentB = new SIPUserAgent(sipTransportCaller, null); SIPTransport sipTransportC = new SIPTransport(); sipTransportC.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); var userAgentC = new SIPUserAgent(sipTransportC, null); SIPTransport sipTransportD = new SIPTransport(); sipTransportD.AddSIPChannel(new SIPUDPChannel(IPAddress.Loopback, 0)); var userAgentD = new SIPUserAgent(sipTransportD, null); logger.LogDebug($"sip transport for UA's A and B listening on: {sipTransportCaller.GetSIPChannels()[0].ListeningSIPEndPoint}."); logger.LogDebug($"sip transport for UA C listening on: {sipTransportC.GetSIPChannels()[0].ListeningSIPEndPoint}."); logger.LogDebug($"sip transport for UA D listening on: {sipTransportD.GetSIPChannels()[0].ListeningSIPEndPoint}."); // Set up auto-answer for UA's C and D: foreach (var userAgent in new List <SIPUserAgent> { userAgentC, userAgentD }) { userAgent.ServerCallCancelled += (uas) => logger.LogDebug("Incoming call cancelled by remote party."); userAgent.OnCallHungup += (dialog) => logger.LogDebug("Call hungup by remote party."); userAgent.OnIncomingCall += async(ua, req) => { var uas = ua.AcceptCall(req); bool answerResult = await ua.Answer(uas, CreateMediaSession()); logger.LogDebug($"Answer incoming call result {answerResult}."); }; } // Place the two calls from A to C and B to D. var dstUriC = sipTransportC.GetSIPChannels()[0].GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Loopback, 0))); logger.LogDebug($"UA-A attempting call UA-C on {dstUriC}."); var callResultAtoC = await userAgentA.Call(dstUriC.ToString(), null, null, CreateMediaSession()); logger.LogDebug($"Client agent answer result for A to C {callResultAtoC}."); Assert.True(callResultAtoC); var dstUriD = sipTransportD.GetSIPChannels()[0].GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(IPAddress.Loopback, 0))); logger.LogDebug($"UA-B attempting call UA-D on {dstUriD}."); var callResultBtoD = await userAgentB.Call(dstUriD.ToString(), null, null, CreateMediaSession()); logger.LogDebug($"Client agent answer result for B to D {callResultBtoD}."); Assert.True(callResultBtoD); Assert.True(userAgentA.IsCallActive); Assert.True(userAgentB.IsCallActive); Assert.True(userAgentC.IsCallActive); Assert.True(userAgentD.IsCallActive); // Initiate attended transfer. A sends REFER request to C such that: // - A sends a REFER request to C, // - The REFER request Refer-To header tells C who to call and what to put in its INVITE request Replaces header, // - The INVITE from C to D tells D this new call from C replaces its call with B, // - When D answers it hangs up its call with B, // - When C gets the Ok response from C it hangs up its call with A. CancellationTokenSource cts = new CancellationTokenSource(); bool transferResult = await userAgentA.AttendedTransfer(userAgentB.Dialogue, TimeSpan.FromSeconds(2), cts.Token); // This means the REFER request was accepted but the transfer still needs to be actioned. Assert.True(transferResult); // Give the transfer time to be processed. await Task.Delay(2000); Assert.False(userAgentA.IsCallActive); Assert.False(userAgentB.IsCallActive); Assert.True(userAgentC.IsCallActive); Assert.True(userAgentD.IsCallActive); sipTransportCaller.Shutdown(); sipTransportC.Shutdown(); sipTransportD.Shutdown(); }
static void Main() { Console.WriteLine("SIPSorcery Call Hold and Blind Transfer example."); Console.WriteLine("Press 'c' to initiate a call to the default destination."); Console.WriteLine("Press 'h' to place an established call on and off hold."); Console.WriteLine("Press 'H' to hangup an established call."); Console.WriteLine("Press 't' to request a blind transfer on an established call."); Console.WriteLine("Press 'q' or ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. Log = AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); Console.WriteLine($"Listening for incoming calls on: {sipTransport.GetSIPChannels().First().ListeningEndPoint}."); EnableTraceLogs(sipTransport); var winAudio = new WindowsAudioEndPoint(new AudioEncoder()); winAudio.RestrictCodecs(new List <AudioCodecsEnum> { AudioCodecsEnum.PCMU }); // Create a client/server user agent to place a call to a remote SIP server along with event handlers for the different stages of the call. var userAgent = new SIPUserAgent(sipTransport, null, true); userAgent.RemotePutOnHold += () => Log.LogInformation("Remote call party has placed us on hold."); userAgent.RemoteTookOffHold += () => Log.LogInformation("Remote call party took us off hold."); userAgent.OnIncomingCall += async(ua, req) => { Log.LogInformation($"Incoming call from {req.Header.From.FriendlyDescription()} at {req.RemoteSIPEndPoint}."); var uas = userAgent.AcceptCall(req); if (userAgent?.IsCallActive == true) { // If we are already on a call return a busy response. Log.LogWarning($"Busy response returned for incoming call request."); uas.Reject(SIPResponseStatusCodesEnum.BusyHere, null); } else { var voipSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipSession.AcceptRtpFromAny = true; var answerResult = await userAgent.Answer(uas, voipSession); } }; // At this point the call has been initiated and everything will be handled in an event handler. Task.Run(async() => { try { while (!exitCts.Token.WaitHandle.WaitOne(0)) { var keyProps = Console.ReadKey(); if (keyProps.KeyChar == 'c') { if (!userAgent.IsCallActive) { var voipSession = new VoIPMediaSession(winAudio.ToMediaEndPoints()); voipSession.AcceptRtpFromAny = true; bool callResult = await userAgent.Call(DEFAULT_DESTINATION_SIP_URI, SIP_USERNAME, SIP_PASSWORD, voipSession); Log.LogInformation($"Call attempt {((callResult) ? "successfull" : "failed")}."); } else { Log.LogWarning("There is already an active call."); } } else if (keyProps.KeyChar == 'h') { // Place call on/off hold. if (userAgent.IsCallActive) { if (userAgent.IsOnLocalHold) { Log.LogInformation("Taking the remote call party off hold."); (userAgent.MediaSession as VoIPMediaSession).TakeOffHold(); userAgent.TakeOffHold(); } else { Log.LogInformation("Placing the remote call party on hold."); await(userAgent.MediaSession as VoIPMediaSession).PutOnHold(); userAgent.PutOnHold(); } } else { Log.LogWarning("There is no active call to put on hold."); } } else if (keyProps.KeyChar == 'H') { if (userAgent.IsCallActive) { Log.LogInformation("Hanging up call."); userAgent.Hangup(); } } else if (keyProps.KeyChar == 't') { // Initiate a blind transfer to the remote call party. if (userAgent.IsCallActive) { var transferURI = SIPURI.ParseSIPURI(TRANSFER_DESTINATION_SIP_URI); bool result = await userAgent.BlindTransfer(transferURI, TimeSpan.FromSeconds(TRANSFER_TIMEOUT_SECONDS), exitCts.Token); if (result) { // If the transfer was accepted the original call will already have been hungup. // Wait a second for the transfer NOTIFY request to arrive. await Task.Delay(1000); exitCts.Cancel(); } else { Log.LogWarning($"Transfer to {TRANSFER_DESTINATION_SIP_URI} failed."); } } else { Log.LogWarning("There is no active call to transfer."); } } else if (keyProps.KeyChar == 'q') { // Quit application. exitCts.Cancel(); } } } catch (Exception excp) { Log.LogError($"Exception Key Press listener. {excp.Message}."); } }); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); #region Cleanup. Log.LogInformation("Exiting..."); if (userAgent != null) { if (userAgent.IsCallActive) { Log.LogInformation($"Hanging up call to {userAgent?.CallDescriptor?.To}."); userAgent.Hangup(); } // Give the BYE or CANCEL request time to be transmitted. Log.LogInformation("Waiting 1s for call to clean up..."); Task.Delay(1000).Wait(); } if (sipTransport != null) { Log.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } #endregion }
static async Task Main() { Console.WriteLine("SIPSorcery Send DTMF Tones example."); Console.WriteLine("Press ctrl-c to exit."); // Plumbing code to facilitate a graceful exit. CancellationTokenSource rtpCts = new CancellationTokenSource(); // Cancellation token to stop the RTP stream. AddConsoleLogger(); var sipTransport = new SIPTransport(); var userAgent = new SIPUserAgent(sipTransport, null); var rtpSession = new RtpAVSession(new AudioOptions { AudioSource = AudioSourcesEnum.CaptureDevice }, null); // Place the call and wait for the result. bool callResult = await userAgent.Call(DEFAULT_DESTINATION_SIP_URI, null, null, rtpSession); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; rtpCts.Cancel(); }; if (callResult) { Console.WriteLine("Call attempt successful."); // Give the call some time to answer. await Task.Delay(1000); // Send the DTMF tones. await userAgent.SendDtmf(0x05); await Task.Delay(2000); await userAgent.SendDtmf(0x09); await Task.Delay(2000); await userAgent.SendDtmf(0x02); await Task.Delay(2000); if (userAgent.IsCallActive) { Console.WriteLine("Hanging up."); rtpCts.Cancel(); userAgent.Hangup(); } } else { Console.WriteLine("Call attempt failed."); } Log.LogInformation("Exiting..."); // Clean up. sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
static async Task Main() { Console.WriteLine("SIPSorcery Play Sounds Demo"); AddConsoleLogger(); CancellationTokenSource exitCts = new CancellationTokenSource(); var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); var userAgent = new SIPUserAgent(sipTransport, OUTBOUND_PROXY); userAgent.ClientCallFailed += (uac, error, sipResponse) => Console.WriteLine($"Call failed {error}."); userAgent.ClientCallFailed += (uac, error, sipResponse) => exitCts.Cancel(); userAgent.OnCallHungup += (dialog) => exitCts.Cancel(); var windowsAudio = new WindowsAudioEndPoint(new AudioEncoder()); //windowsAudio.RestrictFormats(format => format.Codec == AudioCodecsEnum.PCMU); var voipMediaSession = new VoIPMediaSession(windowsAudio.ToMediaEndPoints()); voipMediaSession.AcceptRtpFromAny = true; //voipMediaSession.AudioExtrasSource.AudioSamplePeriodMilliseconds = 20; //voipMediaSession.AudioLocalTrack.Capabilities.Clear(); //voipMediaSession.AudioLocalTrack.Capabilities.Add( // new SDPAudioVideoMediaFormat(new AudioFormat(AudioCodecsEnum.L16, 118, 8000))); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; if (userAgent != null) { if (userAgent.IsCalling || userAgent.IsRinging) { Console.WriteLine("Cancelling in progress call."); userAgent.Cancel(); } else if (userAgent.IsCallActive) { Console.WriteLine("Hanging up established call."); userAgent.Hangup(); } } ; exitCts.Cancel(); }; // Place the call and wait for the result. var callTask = userAgent.Call(DESTINATION, null, null, voipMediaSession); Console.WriteLine("press ctrl-c to exit..."); bool callResult = await callTask; if (callResult) { Console.WriteLine($"Call to {DESTINATION} succeeded."); await windowsAudio.PauseAudio(); try { await voipMediaSession.AudioExtrasSource.StartAudio(); //Console.WriteLine("Sending welcome message from 8KHz sample."); await voipMediaSession.AudioExtrasSource.SendAudioFromStream(new FileStream(WELCOME_8K, FileMode.Open), AudioSamplingRatesEnum.Rate8KHz); await Task.Delay(200, exitCts.Token); Console.WriteLine("Sending sine wave."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.SineWave); await Task.Delay(5000, exitCts.Token); Console.WriteLine("Sending white noise signal."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.WhiteNoise); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Sending pink noise signal."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.PinkNoise); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Sending silence."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Silence); await Task.Delay(2000, exitCts.Token); Console.WriteLine("Playing music."); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.Music); await Task.Delay(5000, exitCts.Token); Console.WriteLine("Sending goodbye message from 16KHz sample."); await voipMediaSession.AudioExtrasSource.SendAudioFromStream(new FileStream(GOODBYE_16K, FileMode.Open), AudioSamplingRatesEnum.Rate16KHz); voipMediaSession.AudioExtrasSource.SetSource(AudioSourcesEnum.None); await voipMediaSession.AudioExtrasSource.PauseAudio(); await Task.Delay(200, exitCts.Token); } catch (System.Threading.Tasks.TaskCanceledException) { } // Switch to the external microphone input source. await windowsAudio.ResumeAudio(); exitCts.Token.WaitHandle.WaitOne(); } else { Console.WriteLine($"Call to {DESTINATION} failed."); } Console.WriteLine("Exiting..."); if (userAgent?.IsHangingUp == true) { Console.WriteLine("Waiting 1s for the call hangup or cancel to complete..."); await Task.Delay(1000); } // Clean up. sipTransport.Shutdown(); }