我正在使用 SIPSorcery v6.0.12 在 MAUI 中开发 VOIP 应用程序。
我在上述情况下处于以下状态。
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
}
我在以下两种情况下失败了。