300 lines
11 KiB
C#
300 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SipComponent;
|
|
using System.Threading;
|
|
|
|
namespace Dispatcher.Sip
|
|
{
|
|
class ExceraForSafeDispatch : ISipComponent, IDisposable
|
|
{
|
|
|
|
#region Fields
|
|
|
|
private SipClientClassExcera _sipClass = null;
|
|
private HashSet<string> _sendPttRequestTo = new HashSet<string>();
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
public ExceraForSafeDispatch(string repeaterIP, int repeaterSipPort, int localSipPort,
|
|
string userName, IEnumerable<int> groupSipIdsToRegister, int registrationInterval, int bufferMiliseconds, int requestTimeout, string localIPAddress = null)
|
|
{
|
|
_sipClass = new SipClientClassExcera(repeaterIP, repeaterSipPort, localSipPort, userName, registrationInterval,
|
|
bufferMiliseconds, requestTimeout, localIPAddress);
|
|
AddSipEventHandlers();
|
|
RegisterToGroups(groupSipIdsToRegister);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ISipComponent Methods
|
|
|
|
public void AcceptInvite(string callingSipID)
|
|
{
|
|
_sipClass.AcceptInvite(callingSipID);
|
|
}
|
|
|
|
public void Decline(string idToDeclineCall)
|
|
{
|
|
_sipClass.Decline(idToDeclineCall);
|
|
}
|
|
|
|
public void SendAudio(string idToSendVoice, byte[] audioBuffer, int bufferLength, AudioFormat format)
|
|
{
|
|
_sipClass.SendAudio(idToSendVoice, audioBuffer, bufferLength, format);
|
|
}
|
|
|
|
public void SendCallRequest(string sipId, bool groupCall)
|
|
{
|
|
if (_sipClass.InDialogWith(sipId))
|
|
{
|
|
// Send Ptt request
|
|
_sipClass.RequestPTT(sipId);
|
|
}
|
|
else
|
|
{
|
|
// Send Invite, then remember to send Ptt request after the dialog is created
|
|
|
|
// Add to hashSet
|
|
_sendPttRequestTo.Add(sipId);
|
|
|
|
// SendInvite
|
|
if (groupCall)
|
|
_sipClass.InviteGroup(sipId);
|
|
else
|
|
_sipClass.Invite(sipId);
|
|
}
|
|
}
|
|
|
|
public void StopPTT(string sipId)
|
|
{
|
|
_sipClass.EndPTT(sipId);
|
|
}
|
|
|
|
public async Task<bool> SendSmsAsync(string idToSendSMS, string text)
|
|
{
|
|
return await _sipClass.SendSmsAsync(idToSendSMS, text);
|
|
}
|
|
|
|
public void Stop(bool async)
|
|
{
|
|
RemoveSipEventHandlers();
|
|
_sipClass.Stop(async);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ISipComponent Events
|
|
|
|
public event EventHandler<SipDialogClosedEventArgs> DialogClosed;
|
|
public event EventHandler<SipDialogCreatedEventArgs> DialogCreated;
|
|
public event EventHandler<ErrorEventArgs> ErrorOnCreatingDialog;
|
|
public event EventHandler<InviteReceivedArgs> InviteReceived;
|
|
public event EventHandler<RegistrationStateChangedEventArgs> RegistrationStateChanged;
|
|
public event EventHandler<SdCanSendVoiceEventArgs> SdCanSendVoice;
|
|
public event EventHandler<SdCannotSendVoiceEventArgs> SdCannotSendVoice;
|
|
public event EventHandler<SdReceivedCallStatusEventArgs> SdReceivesCallInit;
|
|
public event EventHandler<SdReceivedCallStatusEventArgs> SdReceivesStopPTT;
|
|
public event EventHandler<SmsReceivedEventsArgs> SmsReceived;
|
|
public event EventHandler<SipVoiceReceivedEventArgs> VoiceReceived;
|
|
|
|
#endregion
|
|
|
|
#region Excera specific events
|
|
|
|
public event EventHandler<SipEventArgs> ExceraEmergencyReceived;
|
|
|
|
#endregion
|
|
|
|
#region IDisposable Implementation
|
|
|
|
public void Dispose()
|
|
{
|
|
Stop(false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SipClientClassExcera Event Handlers
|
|
|
|
private void _sipClass_ErrorOnCreatingDialog(object sender, ErrorEventArgs e)
|
|
{
|
|
bool inviteSentByMe = _sipClass.UserName == e.FromID;
|
|
if (inviteSentByMe)
|
|
if (_sendPttRequestTo.Contains(e.ToID))
|
|
_sendPttRequestTo.Remove(e.ToID);
|
|
ErrorOnCreatingDialog?.Invoke(this, e);
|
|
}
|
|
|
|
private void _sipClass_DialogClosed(object sender, DialogClosedEventArgs e)
|
|
{
|
|
SipDialogClosedEventArgs ev = new SipDialogClosedEventArgs(
|
|
int.Parse(e.SipIDinDialogWith),
|
|
int.Parse(e.SipIDwhoClosed),
|
|
e.WasGroupCall ? e.SipIDinDialogWith : null);
|
|
DialogClosed?.Invoke(this, ev);
|
|
}
|
|
|
|
private void _sipClass_VoiceReceived(object sender, AudioEventArgs e)
|
|
{
|
|
SipVoiceReceivedEventArgs ev = new SipVoiceReceivedEventArgs(
|
|
e.CallSourceID,
|
|
e.Buffer,
|
|
e.SipIdInDialogWith != e.CallSourceID ? e.SipIdInDialogWith.ToString() : null);
|
|
VoiceReceived?.Invoke(this, ev);
|
|
}
|
|
|
|
private void _sipClass_DialogCreated(object sender, DialogCreatedEventArgs e)
|
|
{
|
|
int sipIdWhoSentInvite = int.Parse(e.FromID);
|
|
int sipIdWhoReceivedInvite = int.Parse(e.ToID);
|
|
bool inviteSentByMe = _sipClass.UserName == e.FromID;
|
|
|
|
int? groupCallSipId = null;
|
|
|
|
if (e.IsGroupCall)
|
|
{
|
|
groupCallSipId = inviteSentByMe ? sipIdWhoReceivedInvite : sipIdWhoSentInvite;
|
|
}
|
|
|
|
SipDialogCreatedEventArgs ev = new SipDialogCreatedEventArgs(
|
|
sipIdWhoSentInvite,
|
|
sipIdWhoReceivedInvite,
|
|
groupCallSipId);
|
|
|
|
// Fire dialog created event
|
|
DialogCreated?.Invoke(this, ev);
|
|
|
|
// Send Ptt request if necessary
|
|
if (inviteSentByMe)
|
|
if (_sendPttRequestTo.Contains(e.ToID))
|
|
{
|
|
_sipClass.RequestPTT(e.ToID);
|
|
_sendPttRequestTo.Remove(e.ToID);
|
|
}
|
|
}
|
|
|
|
private void _sipClass_SipSmsReceived(object sender, SmsReceivedEventsArgs e)
|
|
{
|
|
SmsReceived?.Invoke(this, e);
|
|
}
|
|
|
|
private void _sipClass_RegistrationStateChanged(object sender, RegistrationStateChangedEventArgs e)
|
|
{
|
|
RegistrationStateChanged?.Invoke(this, e);
|
|
}
|
|
|
|
private void _sipClass_InviteReceived(object sender, InviteReceivedArgs e)
|
|
{
|
|
InviteReceived?.Invoke(this, e);
|
|
}
|
|
|
|
private void _sipClass_PTTStartReceived(object sender, RtpEventArgs e)
|
|
{
|
|
int? groupSipId = null;
|
|
if (e.SipIDsendingRTP != e.SipIDinDialogWith)
|
|
groupSipId = int.Parse(e.SipIDinDialogWith);
|
|
SdReceivedCallStatusEventArgs ev = new SdReceivedCallStatusEventArgs(
|
|
int.Parse(e.SipIDsendingRTP), groupSipId);
|
|
SdReceivesCallInit?.Invoke(this, ev);
|
|
}
|
|
|
|
private void _sipClass_PTTrequestGranted(object sender, SipInfoEventArgs e)
|
|
{
|
|
SdCanSendVoiceEventArgs ev = new SdCanSendVoiceEventArgs(
|
|
int.Parse(e.SipIDinDialogWith), e.IsGroup);
|
|
SdCanSendVoice?.Invoke(this, ev);
|
|
}
|
|
|
|
private void _sipClass_PTTrequestFailed(object sender, SipEventArgs e)
|
|
{
|
|
SdCannotSendVoice?.Invoke(this, new SdCannotSendVoiceEventArgs(
|
|
int.Parse(e.SipIDinDialogWith), "No response to ptt request"));
|
|
}
|
|
|
|
private void _sipClass_PTTrequestDenied(object sender, SipEventArgs e)
|
|
{
|
|
SdCannotSendVoice?.Invoke(this, new SdCannotSendVoiceEventArgs(
|
|
int.Parse(e.SipIDinDialogWith), "Ptt request was denied"));
|
|
}
|
|
|
|
private void _sipClass_PTTEndReceived(object sender, RtpEventArgs e)
|
|
{
|
|
int? groupSipId = null;
|
|
if (e.SipIDinDialogWith != e.SipIDsendingRTP)
|
|
groupSipId = int.Parse(e.SipIDinDialogWith);
|
|
|
|
SdReceivedCallStatusEventArgs ev = new SdReceivedCallStatusEventArgs(
|
|
int.Parse(e.SipIDsendingRTP), groupSipId);
|
|
SdReceivesStopPTT?.Invoke(this, ev);
|
|
}
|
|
|
|
|
|
private void _sipClass_EmergencyReceived(object sender, SipEventArgs e)
|
|
{
|
|
ExceraEmergencyReceived?.Invoke(this, e);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Helper Methods
|
|
|
|
private void AddSipEventHandlers()
|
|
{
|
|
_sipClass.InviteReceived += _sipClass_InviteReceived;
|
|
_sipClass.RegistrationStateChanged += _sipClass_RegistrationStateChanged;
|
|
_sipClass.SmsReceived += _sipClass_SipSmsReceived;
|
|
_sipClass.DialogCreated += _sipClass_DialogCreated;
|
|
_sipClass.VoiceReceived += _sipClass_VoiceReceived;
|
|
_sipClass.DialogClosed += _sipClass_DialogClosed;
|
|
_sipClass.ErrorOnCreatingDialog += _sipClass_ErrorOnCreatingDialog;
|
|
_sipClass.PTTStartReceived += _sipClass_PTTStartReceived;
|
|
_sipClass.PTTrequestGranted += _sipClass_PTTrequestGranted;
|
|
_sipClass.PTTrequestDenied += _sipClass_PTTrequestDenied;
|
|
_sipClass.PTTrequestFailed += _sipClass_PTTrequestFailed;
|
|
_sipClass.PTTEndReceived += _sipClass_PTTEndReceived;
|
|
_sipClass.EmergencyReceived += _sipClass_EmergencyReceived;
|
|
}
|
|
|
|
|
|
private void RemoveSipEventHandlers()
|
|
{
|
|
_sipClass.InviteReceived -= _sipClass_InviteReceived;
|
|
_sipClass.RegistrationStateChanged -= _sipClass_RegistrationStateChanged;
|
|
_sipClass.SmsReceived -= _sipClass_SipSmsReceived;
|
|
_sipClass.DialogCreated -= _sipClass_DialogCreated;
|
|
_sipClass.VoiceReceived -= _sipClass_VoiceReceived;
|
|
_sipClass.DialogClosed -= _sipClass_DialogClosed;
|
|
_sipClass.ErrorOnCreatingDialog -= _sipClass_ErrorOnCreatingDialog;
|
|
_sipClass.PTTStartReceived -= _sipClass_PTTStartReceived;
|
|
_sipClass.PTTrequestGranted -= _sipClass_PTTrequestGranted;
|
|
_sipClass.PTTrequestDenied -= _sipClass_PTTrequestDenied;
|
|
_sipClass.PTTrequestFailed -= _sipClass_PTTrequestFailed;
|
|
_sipClass.PTTEndReceived -= _sipClass_PTTEndReceived;
|
|
_sipClass.EmergencyReceived -= _sipClass_EmergencyReceived;
|
|
}
|
|
|
|
private void RegisterToGroups(IEnumerable<int> groupSipIdsToRegister)
|
|
{
|
|
Task.Factory.StartNew((stateObj) =>
|
|
{
|
|
IEnumerable<int> groupIds = (IEnumerable<int>)stateObj;
|
|
// Register to groups
|
|
foreach (int sipGroupId in groupIds)
|
|
{
|
|
_sipClass.RegisterToGroup(sipGroupId.ToString());
|
|
Thread.Sleep(20);
|
|
}
|
|
// Register to the all call group (16777215)
|
|
_sipClass.RegisterToGroup("16777215");
|
|
}, groupSipIdsToRegister);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|