public void RegisterStartWithCustomHeaderTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPTransport transport = new SIPTransport(); MockSIPChannel channel = new MockSIPChannel(new IPEndPoint(IPAddress.Any, 0)); transport.AddSIPChannel(channel); SIPRegistrationUserAgent userAgent = new SIPRegistrationUserAgent( transport, null, new SIPURI("alice", "192.168.11.50", null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), "alice", "password123", null, "192.168.11.50", new SIPURI(SIPSchemesEnum.sip, IPAddress.Any, 0), 120, null, new[] { "My-Header: value" }); userAgent.Start(); channel.SIPMessageSent.WaitOne(5000); Assert.Contains("My-Header: value", channel.LastSIPMessageSent); userAgent.Stop(); }
/// <summary> /// An asynchronous task that attempts to initiate a registration. /// </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 Task <bool> InitiateRegisterTaskAsync(SIPTransport sipTransport, SIPURI dst) { var ua = new SIPRegistrationUserAgent(sipTransport, "user", "password", dst.Host, 120); try { bool result = false; ManualResetEvent mre = new ManualResetEvent(false); ua.RegistrationFailed += (uri, err) => { result = false; mre.Set(); }; ua.RegistrationTemporaryFailure += (uri, err) => { result = false; mre.Set(); }; ua.RegistrationSuccessful += (uri) => { result = true; mre.Set(); }; ua.Start(); mre.WaitOne(TimeSpan.FromSeconds(2000)); ua.Stop(); return(Task.FromResult(result)); } catch (Exception excp) { logger.LogError($"Exception InitiateRegisterTaskAsync. {excp.Message}"); ua.Stop(); return(Task.FromResult(false)); } }
static void Main() { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); EnableTraceLogs(sipTransport); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent(sipTransport, USERNAME, PASSWORD, DOMAIN, EXPIRY); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => Log.LogError($"{uri.ToString()}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => Log.LogWarning($"{uri.ToString()}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => Log.LogError($"{uri.ToString()} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => Log.LogInformation($"{uri.ToString()} registration succeeded."); // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); ManualResetEvent exitMRE = new ManualResetEvent(false); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); exitMRE.Set(); }; exitMRE.WaitOne(); regUserAgent.Stop(); sipTransport.Shutdown(); SIPSorcery.Net.DNSManager.Stop(); }
public void RegisterWithAdjustedRegisterHeaderTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); SIPTransport transport = new SIPTransport(); MockSIPChannel channel = new MockSIPChannel(new System.Net.IPEndPoint(IPAddress.Any, 0)); transport.AddSIPChannel(channel); SIPRegistrationUserAgent userAgent = new SIPRegistrationUserAgent( transport, null, new SIPURI("alice", "192.168.11.50", null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), "alice", "password123", null, "192.168.11.50", new SIPURI(SIPSchemesEnum.sip, IPAddress.Any, 0), 120, null, new[] { "My-Header: value" }); SIPContactHeader testHeader = new SIPContactHeader("Contact Name", new SIPURI("User", "Host", "Param=Value")); userAgent.AdjustRegister = register => { register.Header.Contact = new List <SIPContactHeader> { testHeader }; return(register); }; userAgent.Start(); channel.SIPMessageSent.WaitOne(5000); Assert.Contains(testHeader.ToString(), channel.LastSIPMessageSent); userAgent.Stop(); }
static void Main() { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); var sipChannel = new SIPUDPChannel(IPAddress.Any, 0); sipTransport.AddSIPChannel(sipChannel); EnableTraceLogs(sipTransport); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent( sipTransport, "softphonesample", "password", "sipsorcery.com", 120); int successCounter = 0; ManualResetEvent taskCompleteMre = new ManualResetEvent(false); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => SIPSorcery.Sys.Log.Logger.LogWarning($"{uri.ToString()}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => { SIPSorcery.Sys.Log.Logger.LogInformation($"{uri.ToString()} registration succeeded."); Interlocked.Increment(ref successCounter); SIPSorcery.Sys.Log.Logger.LogInformation($"Successful registrations {successCounter} of {SUCCESS_REGISTRATION_COUNT}."); if (successCounter == SUCCESS_REGISTRATION_COUNT) { taskCompleteMre.Set(); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); taskCompleteMre.Set(); }; // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); taskCompleteMre.WaitOne(); regUserAgent.Stop(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } SIPSorcery.Net.DNSManager.Stop(); }
private const int SUCCESS_REGISTRATION_COUNT = 3; // Number of successful registrations to attempt before exiting process. static void Main(string[] args) { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); // Logging configuration. Can be ommitted if internal SIPSorcery debug and warning messages are not required. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .Enrich.FromLogContext() .MinimumLevel.Is(Serilog.Events.LogEventLevel.Debug) .WriteTo.Console() .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); SIPSorcery.Sys.Log.LoggerFactory = loggerFactory; // Set up a default SIP transport. var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine()); int port = FreePort.FindNextAvailableUDPPort(SIPConstants.DEFAULT_SIP_PORT); var sipChannel = new SIPUDPChannel(new IPEndPoint(LocalIPConfig.GetDefaultIPv4Address(), port)); sipTransport.AddSIPChannel(sipChannel); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent( sipTransport, "softphonesample", "password", "sipsorcery.com", 120); int successCounter = 0; ManualResetEvent taskCompleteMre = new ManualResetEvent(false); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => SIPSorcery.Sys.Log.Logger.LogWarning($"{uri.ToString()}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => SIPSorcery.Sys.Log.Logger.LogError($"{uri.ToString()} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => { SIPSorcery.Sys.Log.Logger.LogInformation($"{uri.ToString()} registration succeeded."); Interlocked.Increment(ref successCounter); SIPSorcery.Sys.Log.Logger.LogInformation($"Successful registrations {successCounter} of {SUCCESS_REGISTRATION_COUNT}."); if (successCounter == SUCCESS_REGISTRATION_COUNT) { taskCompleteMre.Set(); } }; Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); taskCompleteMre.Set(); }; // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); taskCompleteMre.WaitOne(); regUserAgent.Stop(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } SIPSorcery.Net.DNSManager.Stop(); }
/// <summary> /// An asynchronous task that attempts to initiate a registration. /// </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 Task <bool> InitiateRegisterTaskAsync(SIPTransport sipTransport, SIPURI dst) { if (dst.User == null) { dst.User = "******"; } var ua = new SIPRegistrationUserAgent( sipTransport, dst.User, "password", dst.ToString(), 120); //var ua = new SIPRegistrationUserAgent( // sipTransport, // null, // dst, // dst.User, // "password", // null, // dst.ToString(), // new SIPURI(dst.Scheme, IPAddress.Any, 0), // 120, // null); try { bool result = false; ManualResetEvent mre = new ManualResetEvent(false); ua.RegistrationFailed += (uri, err) => { result = false; mre.Set(); }; ua.RegistrationTemporaryFailure += (uri, err) => { result = false; mre.Set(); }; ua.RegistrationSuccessful += (uri) => { result = true; mre.Set(); }; ua.Start(); mre.WaitOne(TimeSpan.FromSeconds(2000)); ua.Stop(false); return(Task.FromResult(result)); } catch (Exception excp) { logger.LogError($"Exception InitiateRegisterTaskAsync. {excp.Message}"); ua.Stop(); return(Task.FromResult(false)); } }
static void Main(string[] args) { Console.WriteLine("SIPSorcery registration user agent example."); Console.WriteLine("Press ctrl-c to exit."); Log = AddConsoleLogger(LogEventLevel.Verbose); string server = DEFAULT_SERVER; string username = DEFAULT_USERNAME; string password = DEFAULT_PASSWORD; int expiry = DEFAULT_EXPIRY; int posn = 0; while (posn < args?.Length && posn <= 3) { switch (posn) { case 0: server = args[posn++].Trim(); break; case 1: username = args[posn++].Trim(); break; case 2: password = args[posn++].Trim(); break; case 3: int.TryParse(args[posn++], out expiry); break; } } Console.WriteLine("Attempting registration with:"); Console.WriteLine($" server: {server}"); Console.WriteLine($" username: {username}"); Console.WriteLine($" expiry: {expiry}"); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.EnableTraceLogs(); // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent(sipTransport, username, password, server, expiry); // Event handlers for the different stages of the registration. regUserAgent.RegistrationFailed += (uri, err) => Log.LogWarning($"{uri}: {err}"); regUserAgent.RegistrationTemporaryFailure += (uri, msg) => Log.LogWarning($"{uri}: {msg}"); regUserAgent.RegistrationRemoved += (uri) => Log.LogWarning($"{uri} registration failed."); regUserAgent.RegistrationSuccessful += (uri) => Log.LogInformation($"{uri} registration succeeded."); // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); ManualResetEvent exitMRE = new ManualResetEvent(false); Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs e) => { e.Cancel = true; Log.LogInformation("Exiting..."); exitMRE.Set(); }; exitMRE.WaitOne(); regUserAgent.Stop(); // Allow for unregister request to be sent (REGISTER with 0 expiry) Task.Delay(1500).Wait(); 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; Utils.AddConsoleLogger(); // Set up a default SIP transport. var sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_LISTEN_PORT))); //EnableTraceLogs(sipTransport); // Get the default speaker. var(audioOutEvent, audioOutProvider) = Utils.GetAudioOutputDevice(); WaveInEvent waveInEvent = Utils.GetAudioInputDevice(); RTPMediaSession RtpMediaSession = null; // Create a client user agent to maintain a periodic registration with a SIP server. var regUserAgent = new SIPRegistrationUserAgent( sipTransport, "1772", "aaa10800bd32115d86e548b8dfb21816", "10.84.0.250", 120); ManualResetEvent taskCompleteMre = new ManualResetEvent(false); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; SIPSorcery.Sys.Log.Logger.LogInformation("Exiting..."); taskCompleteMre.Set(); }; // Start the thread to perform the initial registration and then periodically resend it. regUserAgent.Start(); // 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}."); Utils.PlayRemoteMedia(RtpMediaSession, audioOutProvider); } else { Log.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}."); hasCallFailed = true; exitCts.Cancel(); } }; userAgent.OnCallHungup += () => { Log.LogInformation($"Call hungup by remote party."); exitCts.Cancel(); }; userAgent.ServerCallCancelled += (uas) => Log.LogInformation("Incoming call cancelled by caller."); 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); RtpMediaSession = new RTPMediaSession(SDPMediaTypesEnum.audio, (int)SDPMediaFormatsEnum.PCMU, AddressFamily.InterNetwork); RtpMediaSession.RemotePutOnHold += () => Log.LogInformation("Remote call party has placed us on hold."); RtpMediaSession.RemoteTookOffHold += () => Log.LogInformation("Remote call party took us off hold."); await userAgent.Answer(incomingCall, RtpMediaSession); Utils.PlayRemoteMedia(RtpMediaSession, audioOutProvider); waveInEvent.StartRecording(); 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); } }; // Wire up the RTP send session to the audio output device. uint rtpSendTimestamp = 0; waveInEvent.DataAvailable += (object sender, WaveInEventArgs args) => { byte[] sample = new byte[args.Buffer.Length / 2]; int sampleIndex = 0; for (int index = 0; index < args.BytesRecorded; index += 2) { var ulawByte = NAudio.Codecs.MuLawEncoder.LinearToMuLawSample(BitConverter.ToInt16(args.Buffer, index)); sample[sampleIndex++] = ulawByte; } if (RtpMediaSession != null) { RtpMediaSession.SendAudioFrame(rtpSendTimestamp, sample); rtpSendTimestamp += (uint)(8000 / waveInEvent.BufferMilliseconds); } }; // 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) { RtpMediaSession = new RTPMediaSession(SDPMediaTypesEnum.audio, (int)SDPMediaFormatsEnum.PCMU, AddressFamily.InterNetwork); RtpMediaSession.RemotePutOnHold += () => Log.LogInformation("Remote call party has placed us on hold."); RtpMediaSession.RemoteTookOffHold += () => Log.LogInformation("Remote call party took us off hold."); var callDescriptor = Utils.GetCallDescriptor(DEFAULT_DESTINATION_SIP_URI); await userAgent.InitiateCall(callDescriptor, RtpMediaSession); } else { Log.LogWarning("There is already an active call."); } } else if (keyProps.KeyChar == 'h') { // Place call on/off hold. if (userAgent.IsCallActive) { if (RtpMediaSession.LocalOnHold) { Log.LogInformation("Taking the remote call party off hold."); RtpMediaSession.TakeOffHold(); } else { Log.LogInformation("Placing the remote call party on hold."); RtpMediaSession.PutOnHold(); } } else { Log.LogWarning("There is no active call to put on hold."); } } else if (keyProps.KeyChar == 't') { 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}."); } }); // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; taskCompleteMre.WaitOne(); regUserAgent.Stop(); if (sipTransport != null) { SIPSorcery.Sys.Log.Logger.LogInformation("Shutting down SIP transport..."); sipTransport.Shutdown(); } SIPSorcery.Net.DNSManager.Stop(); }