public SIPDialogue Answer(string contentType, string body, SIPDialogue answeredDialogue, SIPDialogueTransferModesEnum transferMode) { try { logger.Debug("SIPB2BUserAgent Answer."); m_sipDialogue = answeredDialogue; UASStateChanged?.Invoke(this, SIPResponseStatusCodesEnum.Ok, null); SIPResponse uasOkResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, SIPResponseStatusCodesEnum.Ok, null); m_uasTransaction.SendFinalResponse(uasOkResponse); m_uasTransaction.ACKReceived(m_blackhole, m_blackhole, null); SIPResponse uacOkResponse = SIPTransport.GetResponse(m_uacTransaction.TransactionRequest, SIPResponseStatusCodesEnum.Ok, null); uacOkResponse.Header.Contact = new List <SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(SIPSchemesEnum.sip, m_blackhole)) }; m_uacTransaction.GotResponse(m_blackhole, m_blackhole, uacOkResponse); uacOkResponse.Header.ContentType = contentType; if (!body.IsNullOrBlank()) { uacOkResponse.Body = body; uacOkResponse.Header.ContentLength = body.Length; } CallAnswered.Invoke(this, uacOkResponse); return(null); } catch (Exception excp) { logger.Error("Exception SIPB2BUSerAgent Answer. " + excp.Message); throw; } }
private void HandleCallAnswered(Answered answered) { var eventToStore = new CallAnswered() { ConversationId = Guid.Parse(FormatUuid(answered.ConversationUuid)) }; this._session.Events.Append(eventToStore.ConversationId, eventToStore); }
private void ClientCallAnswered(ISIPClientUserAgent uac, SIPResponse resp) { logger.LogDebug($"B2BUserAgent client call answered {resp.ShortDescription}."); if (resp.Status == SIPResponseStatusCodesEnum.Ok) { base.Answer(resp.Header.ContentType, resp.Body, SIPDialogueTransferModesEnum.NotAllowed); CallAnswered?.Invoke(uac, resp); } else { var failureResponse = SIPResponse.GetResponse(m_uasTransaction.TransactionRequest, resp.Status, resp.ReasonPhrase); m_uasTransaction.SendFinalResponse(failureResponse); CallFailed?.Invoke(uac, failureResponse.ReasonPhrase, failureResponse); } }
public void Apply(CallAnswered answered) { this.Answered = true; }
private void UACCallAnswered(ISIPClientUserAgent answeredUAC, SIPResponse answeredResponse) { try { // Remove the current call from the pending list. lock (m_switchCalls) { m_switchCalls.Remove(answeredUAC); } if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null) { m_switchCallTransactions.Add(answeredUAC.ServerTransaction); } if (answeredResponse != null && answeredResponse.StatusCode >= 200 && answeredResponse.StatusCode <= 299) { #region 2xx final response. if (!m_callAnswered && !m_commandCancelled) { // This is the first call we've got an answer on. m_callAnswered = true; m_answeredUAC = answeredUAC; AnsweredSIPResponse = answeredResponse; SIPDialogueTransferModesEnum uasTransferMode = SIPDialogueTransferModesEnum.Default; if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.NotAllowed) { answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed; uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed; } else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.BlindPlaceCall) { answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall; uasTransferMode = SIPDialogueTransferModesEnum.BlindPlaceCall; } else if (m_answeredUAC.CallDescriptor.TransferMode == SIPDialogueTransferModesEnum.PassThru) { answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.PassThru; uasTransferMode = SIPDialogueTransferModesEnum.PassThru; } /*else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Caller) * { * answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.NotAllowed; * uasTransferMode = SIPDialogueTransferModesEnum.Allowed; * } * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Callee) * { * answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed; * uasTransferMode = SIPDialogueTransferModesEnum.NotAllowed; * } * else if (m_answeredUAC.CallDescriptor.TransferMode == SIPCallTransferModesEnum.Both) * { * answeredUAC.SIPDialogue.TransferMode = SIPDialogueTransferModesEnum.Allowed; * uasTransferMode = SIPDialogueTransferModesEnum.Allowed; * }*/ if (CallAnswered != null) { logger.Debug("Transfer mode=" + m_answeredUAC.CallDescriptor.TransferMode + "."); if (answeredUAC.CallDescriptor.ReinviteDelay > 0) { answeredUAC.SIPDialogue.ReinviteDelay = answeredUAC.CallDescriptor.ReinviteDelay; } CallAnswered(answeredResponse.Status, answeredResponse.ReasonPhrase, null, null, answeredResponse.Header.ContentType, answeredResponse.Body, answeredUAC.SIPDialogue, uasTransferMode); // Cancel/hangup and other calls on this leg that are still around. CancelNotRequiredCallLegs(CallCancelCause.NormalClearing); } } else { // Call already answered or cancelled, hangup (send BYE). FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username)); SIPDialogue sipDialogue = new SIPDialogue(answeredUAC.ServerTransaction, m_username, m_adminMemberId); sipDialogue.Hangup(m_sipTransport, m_outboundProxySocket); } #endregion CallLegCompleted(); } else if (answeredUAC.SIPDialogue != null) { // Google Voice calls create the dialogue without using a SIP response. if (!m_callAnswered && !m_commandCancelled) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered.", m_username)); // This is the first call we've got an answer on. m_callAnswered = true; m_answeredUAC = answeredUAC; CallAnswered?.Invoke(SIPResponseStatusCodesEnum.Ok, null, null, null, answeredUAC.SIPDialogue.ContentType, answeredUAC.SIPDialogue.RemoteSDP, answeredUAC.SIPDialogue, SIPDialogueTransferModesEnum.NotAllowed); // Cancel/hangup and other calls on this leg that are still around. CancelNotRequiredCallLegs(CallCancelCause.NormalClearing); } else { // Call already answered or cancelled, hangup (send BYE). FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg for Google Voice call to " + answeredUAC.CallDescriptor.Uri + " answered but call was already answered or cancelled, hanging up.", m_username)); answeredUAC.SIPDialogue.Hangup(m_sipTransport, m_outboundProxySocket); } } else if (answeredResponse != null && answeredResponse.StatusCode >= 300 && answeredResponse.StatusCode <= 399) { ProcessRedirect(answeredUAC, answeredResponse); } else if (answeredResponse != null) { // This call leg failed, record the failure status and reason. m_lastFailureStatus = answeredResponse.Status; m_lastFailureReason = answeredResponse.ReasonPhrase; if (m_switchCallTransactions != null && answeredUAC.ServerTransaction != null) { m_switchCallTransactions.Add(answeredUAC.ServerTransaction); } CallLegCompleted(); } } catch (Exception excp) { logger.Error("Exception ForkCall UACCallAnswered. " + excp); } }
private Task <SocketError> ServerFinalResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse) { try { logger.LogDebug("Response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + " for " + m_serverTransaction.TransactionRequest.URI.ToString() + "."); m_serverTransaction.UACInviteTransactionInformationResponseReceived -= ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived -= ServerFinalResponseReceived; if (m_callCancelled && sipResponse.Status == SIPResponseStatusCodesEnum.RequestTerminated) { // No action required. Correctly received request terminated on an INVITE we cancelled. } else if (m_callCancelled) { #region Call has been cancelled, hangup. if (m_hungupOnCancel) { logger.LogDebug("A cancelled call to " + m_sipCallDescriptor.Uri + " has been answered AND has already been hungup, no further action being taken."); } else { m_hungupOnCancel = true; logger.LogDebug("A cancelled call to " + m_sipCallDescriptor.Uri + " has been answered, hanging up."); if (sipResponse.Header.Contact != null && sipResponse.Header.Contact.Count > 0) { SIPURI byeURI = sipResponse.Header.Contact[0].ContactURI; SIPRequest byeRequest = GetByeRequest(sipResponse, byeURI); SIPNonInviteTransaction byeTransaction = new SIPNonInviteTransaction(m_sipTransport, byeRequest, m_outboundProxy); byeTransaction.SendRequest(); } else { logger.LogDebug("No contact header provided on response for cancelled call to " + m_sipCallDescriptor.Uri + " no further action."); } } #endregion } else if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) { #region Authenticate client call to third party server. if (!m_callCancelled) { if (m_sipCallDescriptor.Password.IsNullOrBlank()) { // No point trying to authenticate if there is no password to use. logger.LogDebug("Forward leg failed, authentication was requested but no credentials were available."); CallFailed?.Invoke(this, "Authentication requested when no credentials available", sipResponse); } else if (m_serverAuthAttempts == 0) { m_serverAuthAttempts = 1; // Resend INVITE with credentials. string username = (m_sipCallDescriptor.AuthUsername != null && m_sipCallDescriptor.AuthUsername.Trim().Length > 0) ? m_sipCallDescriptor.AuthUsername : m_sipCallDescriptor.Username; var authRequest = m_serverTransaction.TransactionRequest.DuplicateAndAuthenticate(sipResponse.Header.AuthenticationHeaders, username, m_sipCallDescriptor.Password); // Create a new UAC transaction to establish the authenticated server call. m_serverTransaction = new UACInviteTransaction(m_sipTransport, authRequest, m_outboundProxy); if (m_serverTransaction.CDR != null) { m_serverTransaction.CDR.Updated(); } m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; m_serverTransaction.UACInviteTransactionFailed += ServerTransactionFailed; m_serverTransaction.SendInviteRequest(); } else { CallFailed?.Invoke(this, "Authentication with provided credentials failed", sipResponse); } } #endregion } else { if (sipResponse.StatusCode >= 200 && sipResponse.StatusCode <= 299) { m_sipDialogue = new SIPDialogue(m_serverTransaction); m_sipDialogue.CallDurationLimit = m_sipCallDescriptor.CallDurationLimit; } CallAnswered?.Invoke(this, sipResponse); } return(Task.FromResult(SocketError.Success)); } catch (Exception excp) { logger.LogDebug("Exception ServerFinalResponseReceived. " + excp); return(Task.FromResult(SocketError.Fault)); } }