コード例 #1
0
ファイル: SIPUserAgent.cs プロジェクト: cfasol/sipsorcery
 /// <summary>
 /// Event handler for RTP events from the remote call party. Fires
 /// when the event is completed.
 /// </summary>
 /// <param name="rtpEvent">The received RTP event.</param>
 private void OnRemoteRtpEvent(RTPEvent rtpEvent)
 {
     if (rtpEvent.EndOfEvent)
     {
         OnDtmfTone?.Invoke(rtpEvent.EventID, rtpEvent.Duration);
     }
 }
コード例 #2
0
ファイル: SIPUserAgent.cs プロジェクト: zhouzu/sipsorcery
        /// <summary>
        /// Event handler for RTP events from the remote call party. Fires
        /// when the event is completed.
        /// </summary>
        /// <param name="rtpEvent">The received RTP event.</param>
        /// <param name="rtpHeader">THe RTP header on the packet that the event was received in.</param>
        private void OnRemoteRtpEvent(RTPEvent rtpEvent, RTPHeader rtpHeader)
        {
            OnRtpEvent?.Invoke(rtpEvent, rtpHeader);

            if (rtpEvent.EndOfEvent)
            {
                OnDtmfTone?.Invoke(rtpEvent.EventID, rtpEvent.Duration);
            }
        }
コード例 #3
0
 /// <summary>
 /// Event handler for RTP events from the remote call party. Fires
 /// when the event is completed.
 /// </summary>
 /// <param name="rtpEvent">The received RTP event.</param>
 private void OnRemoteRtpEvent(RTPEvent rtpEvent)
 {
     if (lastRtpEventEndTimeStamp != rtpEvent.Source.Header.Timestamp &&
         rtpEvent.EndOfEvent)
     {
         lastRtpEventEndTimeStamp = rtpEvent.Source.Header.Timestamp;
         OnDtmfTone?.Invoke(rtpEvent.EventID, rtpEvent.Duration);
     }
 }
コード例 #4
0
 /// <summary>
 /// Event handler for RTP events from the remote call party.
 /// </summary>
 /// <param name="rtpEvent">The received RTP event.</param>
 private void OnRemoteRtpEvent(RTPEvent rtpEvent)
 {
     if (rtpEvent.EndOfEvent)
     {
         remoteDtmfDuration = 0;
     }
     else if (remoteDtmfDuration == 0)
     {
         remoteDtmfDuration = rtpEvent.Duration;
         DtmfCompleted?.Invoke(rtpEvent.EventID);
     }
 }
コード例 #5
0
        public Task SendDtmf(byte key, CancellationToken cancellationToken = default)
        {
            var dtmfEvent = new RTPEvent(key, false, RTPEvent.DEFAULT_VOLUME, DTMF_EVENT_DURATION, DTMF_EVENT_PAYLOAD_ID);

            return(SendDtmfEvent(dtmfEvent, cancellationToken));
        }
コード例 #6
0
        static void Main()
        {
            Console.WriteLine("SIPSorcery client user agent 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.
            bool isCallHungup  = false;
            bool hasCallFailed = false;

            AddConsoleLogger();

            SIPURI callUri = SIPURI.ParseSIPURI(DEFAULT_DESTINATION_SIP_URI);

            Log.LogInformation($"Call destination {callUri}.");

            // Set up a default SIP transport.
            var sipTransport = new SIPTransport();

            sipTransport.AddSIPChannel(new SIPUDPChannel(new IPEndPoint(IPAddress.Any, 0)));

            // Un/comment this line to see/hide each SIP message sent and received.
            EnableTraceLogs(sipTransport);

            // Note this relies on the callURI host being an IP address. If it's a hostname a DNS lookup is required.
            IPAddress localIPAddress = NetServices.GetLocalAddressForRemote(callUri.ToSIPEndPoint().Address);

            // Initialise an RTP session to receive the RTP packets from the remote SIP server.
            var rtpSession = new RTPSession((int)SDPMediaFormatsEnum.PCMU, null, null, true, localIPAddress.AddressFamily);
            var offerSDP   = rtpSession.GetSDP(localIPAddress);

            // Create a client user agent to place a call to a remote SIP server along with event handlers for the different stages of the call.
            var uac = new SIPClientUserAgent(sipTransport);

            uac.CallTrying += (uac, resp) =>
            {
                Log.LogInformation($"{uac.CallDescriptor.To} Trying: {resp.StatusCode} {resp.ReasonPhrase}.");
            };
            uac.CallRinging += (uac, resp) => Log.LogInformation($"{uac.CallDescriptor.To} Ringing: {resp.StatusCode} {resp.ReasonPhrase}.");
            uac.CallFailed  += (uac, err) =>
            {
                Log.LogWarning($"{uac.CallDescriptor.To} Failed: {err}");
                hasCallFailed = true;
            };
            uac.CallAnswered += (uac, resp) =>
            {
                if (resp.Status == SIPResponseStatusCodesEnum.Ok)
                {
                    Log.LogInformation($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}.");
                    rtpSession.DestinationEndPoint = SDP.GetSDPRTPEndPoint(resp.Body);
                    Log.LogDebug($"Remote RTP socket {rtpSession.DestinationEndPoint}.");
                }
                else
                {
                    Log.LogWarning($"{uac.CallDescriptor.To} Answered: {resp.StatusCode} {resp.ReasonPhrase}.");
                }
            };

            // The only incoming request that needs to be explicitly handled for this example is if the remote end hangs up the call.
            sipTransport.SIPTransportRequestReceived += async(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) =>
            {
                if (sipRequest.Method == SIPMethodsEnum.BYE)
                {
                    SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null);
                    await sipTransport.SendResponseAsync(okResponse);

                    if (uac.IsUACAnswered)
                    {
                        Log.LogInformation("Call was hungup by remote server.");
                        isCallHungup = true;
                        rtpCts.Cancel();
                    }
                }
            };

            // Wire up the RTP receive session to the default speaker.
            var(audioOutEvent, audioOutProvider) = GetAudioOutputDevice();
            rtpSession.OnReceivedSampleReady    += (sample) =>
            {
                for (int index = 0; index < sample.Length; index++)
                {
                    short  pcm       = NAudio.Codecs.MuLawDecoder.MuLawToLinearSample(sample[index]);
                    byte[] pcmSample = new byte[] { (byte)(pcm & 0xFF), (byte)(pcm >> 8) };
                    audioOutProvider.AddSamples(pcmSample, 0, 2);
                }
            };

            // Send audio packets (in this case silence) to the callee.
            Task.Run(() => SendSilence(rtpSession, rtpCts));

            // Start the thread that places the call.
            SIPCallDescriptor callDescriptor = new SIPCallDescriptor(
                SIPConstants.SIP_DEFAULT_USERNAME,
                null,
                callUri.ToString(),
                SIPConstants.SIP_DEFAULT_FROMURI,
                null, null, null, null,
                SIPCallDirection.Out,
                SDP.SDP_MIME_CONTENTTYPE,
                offerSDP.ToString(),
                null);

            uac.Call(callDescriptor);

            // Ctrl-c will gracefully exit the call at any point.
            Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
            {
                e.Cancel = true;
                rtpCts.Cancel();
            };

            // Give the call some time to answer.
            Task.Delay(3000).Wait();

            // Send some DTMF key presses via RTP events.
            var dtmf5 = new RTPEvent(0x05, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf5, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).Wait();

            var dtmf9 = new RTPEvent(0x09, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf9, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).Wait();

            var dtmf2 = new RTPEvent(0x02, false, RTPEvent.DEFAULT_VOLUME, 1200, RTPSession.DTMF_EVENT_PAYLOAD_ID);

            rtpSession.SendDtmfEvent(dtmf2, rtpCts.Token).Wait();
            Task.Delay(2000, rtpCts.Token).ContinueWith((task) => { }).Wait(); // Don't care about the exception if the cancellation token is set.

            Log.LogInformation("Exiting...");

            rtpCts.Cancel();
            audioOutEvent?.Stop();
            rtpSession.CloseSession(null);

            if (!isCallHungup && uac != null)
            {
                if (uac.IsUACAnswered)
                {
                    Log.LogInformation($"Hanging up call to {uac.CallDescriptor.To}.");
                    uac.Hangup();
                }
                else if (!hasCallFailed)
                {
                    Log.LogInformation($"Cancelling call to {uac.CallDescriptor.To}.");
                    uac.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();
            }
        }