Example #1
0
        /// <summary>
        /// Starts a registration agent for each of the supplied SIP accounts.
        /// </summary>
        /// <param name="sipTransport">The SIP transport to use for the registrations.</param>
        /// <param name="sipAccounts">The list of SIP accounts to create a registration for.</param>
        private static void StartRegistrations(SIPTransport sipTransport, List <SIPRegisterAccount> sipAccounts)
        {
            foreach (var sipAccount in sipAccounts)
            {
                var regUserAgent = new SIPRegistrationUserAgent(sipTransport, sipAccount.Username, sipAccount.Password, sipAccount.Domain, sipAccount.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();

                _registrations.TryAdd($"{sipAccount.Username}@{sipAccount.Domain}", regUserAgent);
            }
        }
Example #2
0
        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;

            // If your default DNS server supports SRV records there is no need to set a specific DNS server.
            DNSManager.SetDNSServers(new List <IPEndPoint> {
                IPEndPoint.Parse("8.8.8.8:53")
            });

            // 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");

            // 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.");

            // Start the thread to perform the initial registration and then periodically resend it.
            regUserAgent.Start();
        }
        public void Init()
        {
            var port = FreePort.FindNextAvailableUDPPort(15090);

            transport       = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine());
            publicIPAddress = STUNClient.GetPublicIPAddress("stun.ekiga.net");
            localIPEndPoint = IpAddressLookup.QueryRoutingInterface(asterisk, port);

            var endpoint = new IPEndPoint(localIPEndPoint.Address, port);
            var channel  = new SIPUDPChannel(endpoint);

            //channel.SIPMessageReceived += (SIPChannel sipChannel, SIPEndPoint remoteEndPoint, byte[] buffer) => { logger.Debug("Channel SIP message received " + channel.SIPChannelEndPoint + "<-" + remoteEndPoint); };

            transport.AddSIPChannel(channel);

            for (var i = 0; i < numbers.Length; i++)
            {
                var number       = numbers[i];
                var password     = passwords[i];
                var registration = new SIPRegistrationUserAgent(
                    transport,
                    null,
                    new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port),
                    new SIPURI(number, asterisk, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp),
                    number,
                    password,
                    null,
                    asterisk,
                    new SIPURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.udp, publicIPAddress, port)),
                    180,
                    null,
                    null,
                    (e) => { logger.Debug(e.Message); }
                    );

                logger.Debug($"{prefix} Registration attempt for {number}@{endpoint.Address}:{endpoint.Port}");

                registration.RegistrationSuccessful += Registration_RegistrationSuccessful;
                registration.RegistrationFailed     += Registration_RegistrationFailed;
                registration.Start();

                registrations.Add(registration);
            }
        }
Example #4
0
        private async Task Initialize()
        {
            await _sipTransportManager.InitialiseSIP();

            for (int i = 0; i < SIP_CLIENT_COUNT; i++)
            {
                var mediaSessionFactory = new RTPMediaSessionManager(_mediaManager, _musicOnHold);
                var sipClient           = new SIPClient(_sipTransportManager.SIPTransport, mediaSessionFactory);

                sipClient.CallAnswer        += SIPCallAnswered;
                sipClient.CallEnded         += ResetToCallStartState;
                sipClient.StatusMessage     += (client, message) => { SetStatusText(m_signallingStatus, message); };
                sipClient.RemotePutOnHold   += RemotePutOnHold;
                sipClient.RemoteTookOffHold += RemoteTookOffHold;

                _sipClients.Add(sipClient);
            }

            string listeningEndPoints = null;

            foreach (var sipChannel in _sipTransportManager.SIPTransport.GetSIPChannels())
            {
                SIPEndPoint sipChannelEP = sipChannel.ListeningSIPEndPoint.CopyOf();
                sipChannelEP.ChannelID = null;
                listeningEndPoints    += (listeningEndPoints == null) ? sipChannelEP.ToString() : $", {sipChannelEP}";
            }

            listeningEndPoint.Content = $"Listening on: {listeningEndPoints}";

            _sipRegistrationClient = new SIPRegistrationUserAgent(
                _sipTransportManager.SIPTransport,
                null,
                new SIPURI(m_sipUsername, m_sipServer, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp),
                m_sipUsername,
                m_sipPassword,
                null,
                m_sipServer,
                new SIPURI(m_sipUsername, IPAddress.Any.ToString(), null),
                180,
                (message) => { logger.LogDebug(message.ToString()); });

            _sipRegistrationClient.Start();
        }
Example #5
0
        private SIPRegistrationUserAgent _sipRegistrationClient;   // Can be used to register with an external SIP provider if incoming calls are required.

        public SoftPhone()
        {
            InitializeComponent();

            // Do some UI initialisation.
            m_uasGrid.Visibility      = Visibility.Collapsed;
            m_cancelButton.Visibility = Visibility.Collapsed;
            m_byeButton.Visibility    = Visibility.Collapsed;

            // Set up the SIP client. It can receive calls and initiate outgoing calls.
            _sipClient = new SIPClient();
            _sipClient.IncomingCall  += SIPCallIncoming;
            _sipClient.CallAnswer    += SIPCallAnswered;
            _sipClient.CallEnded     += ResetToCallStartState;
            _sipClient.StatusMessage += (message) => { SetStatusText(m_signallingStatus, message); };

            // Set up the Gingle client.
            _gingleClient                = new GingleClient();
            _gingleClient.CallEnded     += ResetToCallStartState;
            _gingleClient.StatusMessage += (message) => { SetStatusText(m_signallingStatus, message); };

            // Lookup and periodically check the public IP address of the host machine.
            _stunClient = new SoftphoneSTUNClient();

            // Comment this out if you don't want the app to register with your SIP server.
            _sipRegistrationClient = new SIPRegistrationUserAgent(
                _sipClient.SIPClientTransport,
                null,
                null,
                new SIPURI(m_sipUsername, m_sipServer, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp),
                m_sipUsername,
                m_sipPassword,
                null,
                m_sipServer,
                new SIPURI(m_sipUsername, _sipClient.SIPClientTransport.GetDefaultSIPEndPoint().GetIPEndPoint().ToString(), null),
                180,
                null,
                null,
                (message) => { logger.Debug(message); });
            _sipRegistrationClient.Start();

            //videoElement.NewVideoSample += new EventHandler<WPFMediaKit.DirectShow.MediaPlayers.VideoSampleArgs>(videoElement_NewVideoSample);
        }
Example #6
0
        private async void Initialise()
        {
            await _sipClient.InitialiseSIP();

            _sipRegistrationClient = new SIPRegistrationUserAgent(
                _sipClient.SIPClientTransport,
                null,
                null,
                new SIPURI(m_sipUsername, m_sipServer, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp),
                m_sipUsername,
                m_sipPassword,
                null,
                m_sipServer,
                new SIPURI(m_sipUsername, _sipClient.SIPClientTransport.GetDefaultSIPEndPoint().GetIPEndPoint().ToString(), null),
                180,
                null,
                null,
                (message) => { logger.Debug(message); });
            _sipRegistrationClient.Start();
        }
Example #7
0
        /// <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));
            }
        }
Example #8
0
        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();
        }
Example #10
0
        /// <summary>
        /// Initialises the SIP clients and transport.
        /// </summary>
        private async Task Initialize()
        {
            await _sipTransportManager.InitialiseSIP();

            for (int i = 0; i < SIP_CLIENT_COUNT; i++)
            {
                var sipClient = new SIPClient(_sipTransportManager.SIPTransport);

                sipClient.CallAnswer        += SIPCallAnswered;
                sipClient.CallEnded         += ResetToCallStartState;
                sipClient.StatusMessage     += (client, message) => { SetStatusText(m_signallingStatus, message); };
                sipClient.RemotePutOnHold   += RemotePutOnHold;
                sipClient.RemoteTookOffHold += RemoteTookOffHold;

                _sipClients.Add(sipClient);
            }

            string listeningEndPoints = null;

            foreach (var sipChannel in _sipTransportManager.SIPTransport.GetSIPChannels())
            {
                SIPEndPoint sipChannelEP = sipChannel.ListeningSIPEndPoint.CopyOf();
                sipChannelEP.ChannelID = null;
                listeningEndPoints    += (listeningEndPoints == null) ? sipChannelEP.ToString() : $", {sipChannelEP}";
            }

            listeningEndPoint.Content = $"Listening on: {listeningEndPoints}";

            _sipRegistrationClient = new SIPRegistrationUserAgent(
                _sipTransportManager.SIPTransport,
                m_sipUsername,
                m_sipPassword,
                m_sipServer,
                REGISTRATION_EXPIRY);

            _sipRegistrationClient.Start();
        }
Example #11
0
        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();
        }
Example #12
0
        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();
        }
Example #13
0
        /// <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));
            }
        }
Example #14
0
        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();
        }
Example #15
0
File: Program.cs Project: spFly/sip
        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();
        }