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 _sendPttRequestTo = new HashSet(); #endregion #region Constructor public ExceraForSafeDispatch(string repeaterIP, int repeaterSipPort, int localSipPort, string userName, IEnumerable 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 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 DialogClosed; public event EventHandler DialogCreated; public event EventHandler ErrorOnCreatingDialog; public event EventHandler InviteReceived; public event EventHandler RegistrationStateChanged; public event EventHandler SdCanSendVoice; public event EventHandler SdCannotSendVoice; public event EventHandler SdReceivesCallInit; public event EventHandler SdReceivesStopPTT; public event EventHandler SmsReceived; public event EventHandler VoiceReceived; #endregion #region Excera specific events public event EventHandler 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 groupSipIdsToRegister) { Task.Factory.StartNew((stateObj) => { IEnumerable groupIds = (IEnumerable)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 } }