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; } }