在 SIPSorcery C# 中无法检测到呼叫已被用户挂断/取消

问题描述 投票:0回答:0

我正在使用 SIPSorcery v6.0.12 在 MAUI 中开发 VOIP 应用程序。

我在上述情况下处于以下状态。

  1. 用户1呼叫用户2,用户2不接电话并拒绝:成功
  2. 用户1呼叫用户2,用户2不接听电话,用户1取消呼叫:成功
  3. user1 呼叫 user2,user2 accept call and declined it : Failed
  4. 用户1呼叫用户2,用户2接受呼叫,用户1取消呼叫:失败

call-dialer.xaml.cs(用户1拨打电话)

using SIPSorcery.Media;
using SIPSorcery.SIP.App;
using SIPSorceryMedia.Windows;
using sipsorcery.desktop.preferences_utilities;
using Serilog;
using SIPSorcery.SIP;
using System.Net;

namespace sipsorcery.desktop;

public partial class call_dialer : ContentPage
{
    private string gblStrDomain = "@server.com";
    private string gblStrCloudDestinationAddress = "[email protected]";
    private string gblStrExtentionNumber = "", gblStrExtentionPassword = "";

    SIPUserAgent objSIPUserAgent = null;
    SIPRequest objSIPRequest = null;
    SIPServerUserAgent objSIPServerUserAgent = null;
    SIPTransport objSIPTransport = null;

    ILogger objLogger = Log.ForContext<call_dialer>();

    public call_dialer()
    {
        InitializeComponent();
        //GLOBAL VARIABLES SET HERE
    }

    #region EVENTS
    /// <summary>
    /// THIS EVENT IS CALLED ON CLICK OF 'PLACE CALL' BUTTON
    /// </summary>
    /// <param name="objSender"></param>
    /// <param name="objEventArgs"></param>
    private async void btnCall_Clicked(object objSender, EventArgs objEventArgs)
    {
        try
        {
            string strDialledNumber = !string.IsNullOrEmpty(entryCallNumber.Text) ? entryCallNumber.Text : "";
            if (!string.IsNullOrEmpty(strDialledNumber))
            {
                if (gblStrExtentionNumber == strDialledNumber)
                {
                    objLogger.Information($"Couldn't place call on {strDialledNumber}.");
                    await DisplayAlert("Warning", $"Couldn't place call on {strDialledNumber}.", "OK");
                }
                else
                {
                    //PLACE THE CALL AND WAIT FOR THE RESULT
                    objSIPUserAgent = new SIPUserAgent();
                    WindowsAudioEndPoint objWindowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder());
                    VoIPMediaSession objVoIPMediaSession = new VoIPMediaSession(objWindowsAudioEndPoint.ToMediaEndPoints());
                    objVoIPMediaSession.AcceptRtpFromAny = true;

                    objLogger.Information($"SIPUserAgent,WindowsAudioEndPoint,VoIPMediaSession instance created to place a call");

                    #region CALLING EVENTS
                    objSIPUserAgent.ClientCallRinging += async (isip_client_user_agent, sip_response) =>
                    {
                        objLogger.Information($"Client call is ringing");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridRinging");
                        });
                    };
                    objSIPUserAgent.ClientCallTrying += async (isip_client_user_agent, sip_response) =>
                    {
                        objLogger.Information($"Trying to connect call");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridRinging");
                        });
                    };
                    objSIPUserAgent.ClientCallAnswered += async (isip_client_user_agent, sip_response) =>
                    {
                        objLogger.Information($"Call is accepted by client machine");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridCalling");
                        });
                    };
                    objSIPUserAgent.ClientCallFailed += async (isip_client_user_agent, error_response, sip_response) =>
                    {
                        objLogger.Information($"Client call is failed");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridCallDialer");
                        });
                    };
                    objSIPUserAgent.ServerCallCancelled += async (isip_client_user_agent) =>
                    {
                        objLogger.Information($"Server canclled call");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridCallDialer");
                        });
                    };
                    objSIPUserAgent.ServerCallRingTimeout += async (isip_client_user_agent) =>
                    {
                        objLogger.Information($"Ringing timeout");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridCallDialer");
                        });
                    };
                    objSIPUserAgent.OnCallHungup += async (sip_dialogue) =>
                    {
                        objLogger.Information($"Call is hanging up");
                        Device.InvokeOnMainThreadAsync(() =>
                        {
                            ShowGrid("gridCallDialer");
                        });
                    };
                    #endregion

                    string strDestinationAddress = strDialledNumber + gblStrDomain;

                    bool blnCallResult = await objSIPUserAgent.Call(strDestinationAddress, gblStrExtentionNumber, gblStrExtentionPassword, objVoIPMediaSession);
                }
            }
        }
        catch
        {
        }
    }

    /// <summary>
    /// WHEN USER1 PLACES CALL, 'CANCEL' CALL BUTTON WILL BE SHOWN TO HIM & THIS EVENT IS CALLED ON CLICK OF THAT BUTTON
    /// </summary>
    /// <param name="objSender"></param>
    /// <param name="objEventArgs"></param>
    private async void btnCancelCall_Clicked(object objSender, EventArgs objEventArgs)
    {
        try
        {
            objLogger.Information($"Sender clicked decline");
            if (objSIPUserAgent != null)
            {
                objSIPUserAgent.Hangup();
                objLogger.Information($"objSIPUserAgent.Hangup() method is called from server machine");

                objSIPUserAgent.Cancel();
                objLogger.Information($"objSIPUserAgent.Cancel() method is called from server machine");

                objSIPUserAgent.Dispose();
                objLogger.Information($"objSIPUserAgent.Dispose() method is called from server machine");
            }
            App.Current.MainPage = new call_dialer();
        }
        catch
        {
            App.Current.MainPage = new call_dialer();
        }
    }

    /// <summary>
    /// THIS METHOD IS CALLED WHEN WINDOW IS LOADED/APPEARED
    /// </summary>
    protected override async void OnAppearing()
    {
        base.OnAppearing();
        await Task.Delay(500);
        await Task.Run(() =>
        {
            Device.InvokeOnMainThreadAsync(() =>
            {
                entryCallNumber.Focus();
            });
        });
    }
    #endregion
}

App.xaml.cs(来电事件在这个文件中为user2处理)

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        SIPTransport objSIPTransport = new SIPTransport();

        objSIPTransport.AddSIPChannel(new SIPTCPChannel(new IPEndPoint(IPAddress.Any, 5060)));

        SIPUserAgent objSIPUserAgent = new SIPUserAgent(objSIPTransport, null, true);

        objSIPUserAgent.OnIncomingCall += async (useragent, siprequest) =>
        {
            Device.InvokeOnMainThreadAsync(() =>
            {
                MainPage = new incoming_call_notification(siprequest, useragent, objSIPTransport);
            });
        };

        if (new preferences_management().ValidUser(objSIPTransport))
        {
            MainPage = new call_dialer();
        }
        else
        {
            MainPage = new user_login();
        }
    }
}

incoming-call-notification.xaml.cs(当为user2处理来电事件时,他将获得“接受”和“拒绝”按钮)

using SIPSorcery.Media;
using SIPSorcery.SIP;
using SIPSorcery.SIP.App;
using SIPSorceryMedia.Windows;
using Serilog;

namespace sipsorcery.desktop;

public partial class incoming_call_notification : ContentPage
{
    SIPRequest objSIPRequest = null;
    SIPUserAgent objSIPUserAgent = null;
    SIPServerUserAgent objSIPServerUserAgent = null;
    SIPTransport objSIPTransport = null;

    public incoming_call_notification(SIPRequest _objSIPRequest, SIPUserAgent _objSIPUserAgent, SIPTransport _objSIPTransport)
    {
        InitializeComponent();
        objSIPRequest = _objSIPRequest;
        objSIPUserAgent = _objSIPUserAgent;
        objSIPTransport = _objSIPTransport;
    }

    #region METHODS
    /// <summary>
    /// THIS METHOD IS USED TO START TIMER WHEN CALL IS CONNECTED
    /// </summary>
    private void StartCallingTimer()
    {
        DateTime objCurrentDateTime = DateTime.Now;
        IDispatcherTimer _objIDispatcherTimer;
        _objIDispatcherTimer = Dispatcher.CreateTimer();
        _objIDispatcherTimer.Interval = TimeSpan.FromMilliseconds(1000);
        _objIDispatcherTimer.Tick += (start, end) =>
        {
            lblCallTime.Text = string.Format("{0:00}:{1:00}:{2:00}", (DateTime.Now - objCurrentDateTime).Hours, (DateTime.Now - objCurrentDateTime).Minutes, (DateTime.Now - objCurrentDateTime).Seconds);
        };
        _objIDispatcherTimer.Start();
    }

    /// <summary>
    /// THIS METHOD IS USED TO SHOW GRID BY NAME
    /// </summary>
    /// <param name="strGridName"></param>
    private void ShowGrid(string strGridName)
    {
        try
        {
            if (!string.IsNullOrEmpty(strGridName))
            {
                if (strGridName == "gridIncomingCall")
                {
                    gridIncomingCall.IsVisible = true;
                    gridCallAccepted.IsVisible = false;
                }
                else if (strGridName == "gridCallAccepted")
                {
                    gridCallAccepted.IsVisible = true;
                    gridIncomingCall.IsVisible = false;
                    StartCallingTimer();
                }
            }
        }
        catch
        {
        }
    }
    #endregion

    #region EVENTS
    /// <summary>
    /// THE USER2 WILL GET ACCEPT & REJECT BUTTON WHEN CALL IS INCOMING. BY CLICKING ON ACCEPT BUTTON, THIS EVENT IS CALLED
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void btnAccept_Clicked(object sender, EventArgs e)
    {
        try
        {
            if (objSIPRequest != null && objSIPUserAgent != null)
            {
                objSIPServerUserAgent = objSIPUserAgent.AcceptCall(objSIPRequest);
                WindowsAudioEndPoint objWindowsAudioEndPoint = new WindowsAudioEndPoint(new AudioEncoder());
                VoIPMediaSession objVoIPMediaSession = new VoIPMediaSession(objWindowsAudioEndPoint.ToMediaEndPoints());
                objVoIPMediaSession.AcceptRtpFromAny = true;

                objSIPUserAgent.ClientCallRinging += async (isip_client_user_agent, sip_response) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        ShowGrid("gridIncomingCall");
                    });
                };
                objSIPUserAgent.ClientCallTrying += async (isip_client_user_agent, sip_response) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        ShowGrid("gridIncomingCall");
                    });
                };
                objSIPUserAgent.ClientCallAnswered += async (isip_client_user_agent, sip_response) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        ShowGrid("gridCallAccepted");
                    });
                };
                objSIPUserAgent.ClientCallFailed += async (isip_client_user_agent, error_response, sip_response) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        App.Current.MainPage = new call_dialer();
                    });
                };
                objSIPUserAgent.ServerCallCancelled += async (isip_client_user_agent) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        App.Current.MainPage = new call_dialer();
                    });
                };
                objSIPUserAgent.ServerCallRingTimeout += async (isip_client_user_agent) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        App.Current.MainPage = new call_dialer();
                    });
                };
                objSIPUserAgent.OnCallHungup += async (sip_dialogue) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        App.Current.MainPage = new call_dialer();
                    });
                };
                objSIPServerUserAgent.CallCancelled += async (isip_client_user_agent) =>
                {
                    Device.InvokeOnMainThreadAsync(() =>
                    {
                        App.Current.MainPage = new call_dialer();
                    });
                };

                await objSIPUserAgent.Answer(objSIPServerUserAgent, objVoIPMediaSession);

                ShowGrid("gridCallAccepted");
            }
        }
        catch
        {
        }
    }

    /// <summary>
    /// THE USER2 WILL GET ACCEPT & REJECT BUTTON WHEN CALL IS INCOMING. BY CLICKING ON REJECT BUTTON, THIS EVENT IS CALLED
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnDecline_Clicked(object sender, EventArgs e)
    {
        try
        {
            if (objSIPServerUserAgent == null)
            {
                objSIPServerUserAgent = objSIPUserAgent.AcceptCall(objSIPRequest);
            }
            objSIPServerUserAgent.Reject(SIPResponseStatusCodesEnum.Decline, null);
            
            #region ALSO USED BELOW TWO CODE SNIPPETS BUT DIDN'T WORKED
            //if (objSIPTransport != null)
            //{
            //    SIPClientUserAgent objClientUserAgent = new SIPClientUserAgent(objSIPTransport);
            //    objClientUserAgent.Hangup();
            //    objClientUserAgent.Cancel();
            //}
            //if(objSIPUserAgent != null)
            //{
            //  objSIPUserAgent.Hangup();
            //    objSIPUserAgent.Cancel();
            //  objSIPUserAgent.Dispose();
            //}
            #endregion
            
            App.Current.MainPage = new call_dialer();
        }
        catch
        {
            App.Current.MainPage = new call_dialer();
        }
    }
    #endregion
}

我在以下两种情况下失败了。

  1. 当user1呼叫user2时,user2接听电话,user1挂断电话。 在这种情况下,用户 2 无法检测到用户 1 挂断电话的任何事件或确认。
  2. 当user1呼叫user2时,user2接听电话,user2挂断电话。 在这种情况下,用户 1 无法检测到用户 2 挂断电话的任何事件或确认。
c# .net asterisk sip sip-server
© www.soinside.com 2019 - 2024. All rights reserved.