Example #1
0
        public SIPNonInviteTransaction CreateNonInviteTransaction(SIPRequest sipRequest, SIPEndPoint dstEndPoint, SIPEndPoint localSIPEndPoint, SIPEndPoint outboundProxy)
        {
            try
            {
                if (localSIPEndPoint == null)
                {
                    localSIPEndPoint = GetDefaultSIPEndPoint();
                }

                CheckTransactionEngineExists();
                SIPNonInviteTransaction nonInviteTransaction = new SIPNonInviteTransaction(this, sipRequest, dstEndPoint, localSIPEndPoint, outboundProxy);
                m_transactionEngine.AddTransaction(nonInviteTransaction);
                return nonInviteTransaction;
            }
            catch (Exception excp)
            {
                logger.Error("Exception CreateNonInviteTransaction. " + excp.Message);
                throw;
            }
        }
        private bool AuthenticateReferRequest(SIPNonInviteTransaction referTransaction, string sipUsername, string sipDomain)
        {
            SIPRequest referRequest = referTransaction.TransactionRequest;

            try
            {
                if (SIPAuthenticateRequest_External == null)
                {
                    // No point trying to authenticate if we haven't been given an authentication delegate.
                    logger.Warn("Missing SIP request authentication delegate in SIPDialogueManager AuthenticateReferRequest.");
                    SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                    referTransaction.SendFinalResponse(errorResponse);
                }
                else if (GetSIPAccount_External == null)
                {
                    // No point trying to authenticate if we haven't been given a  delegate to load the SIP account.
                    logger.Warn("Missing get SIP account delegate in SIPDialogueManager AuthenticateReferRequest.");
                    SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                    referTransaction.SendFinalResponse(errorResponse);
                }
                else
                {
                    SIPAccount sipAccount = GetSIPAccount_External(s => s.SIPUsername == sipUsername && s.SIPDomain == sipDomain);

                    if (sipAccount == null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Rejecting authentication required call for " + sipUsername + "@" + sipDomain + ", SIP account not found.", null));
                        SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.Forbidden, null);
                        referTransaction.SendFinalResponse(errorResponse);
                    }
                    else
                    {
                        SIPEndPoint localSIPEndPoint = (!referRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(referRequest.Header.ProxyReceivedOn) : referRequest.LocalSIPEndPoint;
                        SIPEndPoint remoteEndPoint = (!referRequest.Header.ProxyReceivedFrom.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(referRequest.Header.ProxyReceivedFrom) : referRequest.RemoteSIPEndPoint;

                        SIPRequestAuthenticationResult authenticationResult = SIPAuthenticateRequest_External(localSIPEndPoint, remoteEndPoint, referRequest, sipAccount, Log_External);
                        if (authenticationResult.Authenticated)
                        {
                            if (authenticationResult.WasAuthenticatedByIP)
                            {
                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "REFER from " + remoteEndPoint.ToString() + " successfully authenticated by IP address.", sipAccount.Owner));
                            }
                            else
                            {
                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "REFER from " + remoteEndPoint.ToString() + " successfully authenticated by digest.", sipAccount.Owner));
                            }

                            return true;
                        }
                        else
                        {
                            // Send authorisation failure or required response
                            SIPResponse authReqdResponse = SIPTransport.GetResponse(referRequest, authenticationResult.ErrorResponse, null);
                            authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader;
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "REFER not authenticated for " + sipUsername + "@" + sipDomain + ", responding with " + authenticationResult.ErrorResponse + ".", null));
                            referTransaction.SendFinalResponse(authReqdResponse);

                            return false;
                        }
                    }
                }

                return false;
            }
            catch (Exception excp)
            {
                logger.Error("Exception SIDialogueManager AuthenticateReferRequest. " + excp.Message);
                SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.InternalServerError, null);
                referTransaction.SendFinalResponse(errorResponse);

                return false;
            }
        }
        public void Cancel()
        {
            try
            {
                m_callCancelled = true;

                // Cancel server call.
                if (m_serverTransaction == null)
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg " + m_sipCallDescriptor.Uri + ", server transaction has not been created yet no CANCEL request required.", Owner));
                }
                else if (m_cancelTransaction != null)
                {
                    if (m_cancelTransaction.TransactionState != SIPTransactionStatesEnum.Completed)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already been cancelled once, trying again.", Owner));
                        m_cancelTransaction.SendRequest(m_cancelTransaction.TransactionRequest);
                    }
                    else
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already responded to CANCEL, probably overlap in messages not re-sending.", Owner));
                    }
                }
                else //if (m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding || m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Trying)
                {
                    //logger.Debug("Cancelling forwarded call leg, sending CANCEL to " + ForwardedTransaction.TransactionRequest.URI.ToString() + " (transid: " + ForwardedTransaction.TransactionId + ").");
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg, sending CANCEL to " + m_serverTransaction.TransactionRequest.URI.ToString() + ".", Owner));

                    // No reponse has been received from the server so no CANCEL request neccessary, stop any retransmits of the INVITE.
                    m_serverTransaction.CancelCall();

                    SIPRequest cancelRequest = GetCancelRequest(m_serverTransaction.TransactionRequest);
                    m_cancelTransaction = m_sipTransport.CreateNonInviteTransaction(cancelRequest, m_serverEndPoint, m_serverTransaction.LocalSIPEndPoint, m_outboundProxy);
                    m_cancelTransaction.TransactionTraceMessage += TransactionTraceMessage;
                    //m_cancelTransaction.SendRequest(m_serverEndPoint, cancelRequest);
                    m_cancelTransaction.SendReliableRequest();
                }
                //else
                //{
                // No reponse has been received from the server so no CANCEL request neccessary, stop any retransmits of the INVITE.
                //    m_serverTransaction.CancelCall();
                //    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Cancelling forwarded call leg " + m_sipCallDescriptor.Uri.ToString() + ", no response from server has been received so no CANCEL request required.", Owner));
                //}

                FireCallFailed(this, "Call cancelled by user.");
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Exception CancelServerCall. " + excp.Message, Owner));
            }
        }
        /// <summary>
        /// Performs an attended transfer based on a REFER request with a Replaces parameter on the Refer-To header.
        /// </summary>
        /// <param name="dialogue">The dialogue matching the the REFER request headers (Call-ID, To tag and From tag).</param>
        /// <param name="referTransaction">The REFER request.</param>
        /// <param name="localEndPoint">The local SIP end point the REFER request was received on.</param>
        /// <param name="remoteEndPoint">The remote SIP end point the REFER request was received from.</param>
        private void ProcessAttendedRefer(SIPDialogue dialogue, SIPNonInviteTransaction referTransaction, SIPRequest referRequest, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint)
        {
            try
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Initiating attended transfer.", dialogue.Owner));
                SIPUserField referToField = SIPUserField.ParseSIPUserField(referRequest.Header.ReferTo);

                if (referToField == null)
                {
                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Error on transfer, could not parse Refer-To header: " + referRequest.Header.ReferTo + ".", dialogue.Owner));
                    SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.BadRequest, "Could not parse Refer-To header");
                    referTransaction.SendFinalResponse(errorResponse);
                }
                else
                {
                    string replaces = referToField.URI.Headers.Get(m_referReplacesParameter);

                    SIPDialogue replacesDialogue = GetDialogue(replaces);
                    if (replacesDialogue == null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Could not locate the dialogue for the Replaces parameter on an attended transfer.", dialogue.Owner));
                        SIPResponse errorResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.BadRequest, "Could not locate replaced dialogue");
                        referTransaction.SendFinalResponse(errorResponse);
                    }
                    else
                    {
                        logger.Debug("REFER dialogue being replaced " + replacesDialogue.DialogueName + ".");

                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Replacement dialogue found on Refer, accepting.", dialogue.Owner));

                        bool sendNotifications = true;
                        if(!referRequest.Header.ReferSub.IsNullOrBlank())
                        {
                            Boolean.TryParse(referRequest.Header.ReferSub, out sendNotifications);
                        }

                        SIPDialogue remainingDialogue = GetOppositeDialogue(replacesDialogue);
                        SIPDialogue remaining2Dialogue = GetOppositeDialogue(dialogue);

                        logger.Debug("REFER dialogue remaining " + remainingDialogue.DialogueName + ".");

                        Guid newBridgeId = Guid.NewGuid();
                        remainingDialogue.BridgeId = newBridgeId;
                        remainingDialogue.CSeq++;
                        remaining2Dialogue.BridgeId = newBridgeId;
                        remaining2Dialogue.CSeq++;

                        m_sipDialoguePersistor.Update(new SIPDialogueAsset(remainingDialogue));
                        m_sipDialoguePersistor.Update(new SIPDialogueAsset(remaining2Dialogue));

                        Log_External(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPDialogueUpdated, remainingDialogue.Owner, remainingDialogue.Id.ToString(), remainingDialogue.LocalUserField.URI));
                        Log_External(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPDialogueUpdated, remaining2Dialogue.Owner, remaining2Dialogue.Id.ToString(), remaining2Dialogue.LocalUserField.URI));
                        Log_External(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPDialogueTransfer, remainingDialogue.Owner, remainingDialogue.Id.ToString(), remainingDialogue.LocalUserField.URI));

                        SIPResponse acceptedResponse = SIPTransport.GetResponse(referRequest, SIPResponseStatusCodesEnum.Accepted, null);
                        referTransaction.SendFinalResponse(acceptedResponse);

                        if (sendNotifications)
                        {
                            SendNotifyRequestForRefer(referRequest, dialogue, localEndPoint, SIPResponseStatusCodesEnum.Trying, null);
                        }

                        logger.Debug("Reinviting " + remainingDialogue.DialogueName + " with " + remaining2Dialogue.DialogueName + ".");

                        ReInvite(remainingDialogue, remaining2Dialogue);
                        ReInvite(remaining2Dialogue, remainingDialogue);

                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Transfer dialogue re-invites complete.", dialogue.Owner));

                        if (sendNotifications)
                        {
                            SendNotifyRequestForRefer(referRequest, dialogue, localEndPoint, SIPResponseStatusCodesEnum.Ok, null);
                        }

                        // Hangup redundant dialogues.
                        logger.Debug("Hanging up redundant dialogues post transfer.");
                        logger.Debug("Hanging up " + dialogue.DialogueName + ".");
                        dialogue.Hangup(m_sipTransport, m_outboundProxy);
                        CallHungup(dialogue, "Attended transfer", false);
                        logger.Debug("Hanging up " + replacesDialogue.DialogueName + ".");
                        replacesDialogue.Hangup(m_sipTransport, m_outboundProxy);
                        CallHungup(replacesDialogue, "Attended transfer", false);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception ProcessAttendedRefer. " + excp.Message);
                throw;
            }
        }