private void ServerTransactionFailed(SIPTransaction sipTransaction, SocketError failureReason) { if (!m_callCancelled) { CallFailed?.Invoke(this, failureReason.ToString(), null); } }
public void Reject(SIPResponseStatusCodesEnum rejectCode, string rejectReason, string[] customHeaders) { logger.Debug("SIPB2BUserAgent Reject."); UASStateChanged?.Invoke(this, rejectCode, rejectReason); SIPResponse uasfailureResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, rejectCode, rejectReason); m_uasTransaction.SendFinalResponse(uasfailureResponse); SIPResponse uacfailureResponse = SIPTransport.GetResponse(m_uacTransaction.TransactionRequest, rejectCode, rejectReason); if (customHeaders != null && customHeaders.Length > 0) { foreach (string header in customHeaders) { uacfailureResponse.Header.UnknownHeaders.Add(header); } } m_uacTransaction.GotResponse(m_blackhole, m_blackhole, uacfailureResponse); CallAnswered(this, uacfailureResponse); CallFailed.Invoke(this, "failed"); }
/// <summary> /// Cancels an in progress call. This method should be called prior to the remote user agent server answering the call. /// </summary> public void Cancel() { try { m_callCancelled = true; // Cancel server call. if (m_serverTransaction == null) { logger.LogDebug("Cancelling forwarded call leg " + m_sipCallDescriptor.Uri + ", server transaction has not been created yet no CANCEL request required."); } else if (m_cancelTransaction != null) { if (m_cancelTransaction.TransactionState != SIPTransactionStatesEnum.Completed) { logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already been cancelled once, trying again."); m_cancelTransaction.SendRequest(); } else { logger.LogDebug("Call " + m_serverTransaction.TransactionRequest.URI.ToString() + " has already responded to CANCEL, probably overlap in messages not re-sending."); } } else //if (m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding || m_serverTransaction.TransactionState == SIPTransactionStatesEnum.Trying) { logger.LogDebug("Cancelling forwarded call leg, sending CANCEL to " + m_serverTransaction.TransactionRequest.URI.ToString() + "."); // No response has been received from the server so no CANCEL request necessary, stop any retransmits of the INVITE. m_serverTransaction.CancelCall(); SIPRequest cancelRequest = GetCancelRequest(m_serverTransaction.TransactionRequest); // If auth header is included inside INVITE request, we re-include them inside CANCEL request if (m_serverTransaction.TransactionRequest.Header.HasAuthenticationHeader) { string username = (m_sipCallDescriptor.AuthUsername == null || m_sipCallDescriptor.AuthUsername.Trim().Length <= 0 ? m_sipCallDescriptor.Username : m_sipCallDescriptor.AuthUsername); SIPAuthorisationDigest authDigest = m_serverTransaction.TransactionRequest.Header.AuthenticationHeaders.First().SIPDigest; authDigest.SetCredentials(username, m_sipCallDescriptor.Password, m_sipCallDescriptor.Uri, SIPMethodsEnum.CANCEL.ToString()); var authHeader = new SIPAuthenticationHeader(authDigest); authHeader.SIPDigest.IncrementNonceCount(); authHeader.SIPDigest.Response = authDigest.GetDigest(); cancelRequest.Header.AuthenticationHeaders.Clear(); cancelRequest.Header.AuthenticationHeaders.Add(authHeader); } m_cancelTransaction = new SIPNonInviteTransaction(m_sipTransport, cancelRequest, m_outboundProxy); m_cancelTransaction.SendRequest(); } CallFailed?.Invoke(this, "Call cancelled by user.", null); } catch (Exception excp) { logger.LogError("Exception CancelServerCall. " + excp.Message); } }
private void ClientCallFailed(ISIPClientUserAgent uac, string error, SIPResponse errResponse) { if (!base.IsCancelled) { logger.LogDebug($"B2BUserAgent client call failed {error}."); var status = (errResponse != null) ? errResponse.Status : SIPResponseStatusCodesEnum.Decline; var errResp = SIPResponse.GetResponse(m_uasTransaction.TransactionRequest, status, errResponse?.ReasonPhrase); m_uasTransaction.SendFinalResponse(errResp); CallFailed?.Invoke(uac, error, errResponse); } }
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); } }
private void CallFailed(CallFailed call) { _dayPayment.Remove(call.PayPenalty); }
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)); } }
/// <summary> /// Initiates the call to the remote user agent server. /// </summary> /// <param name="sipCallDescriptor">The descriptor for the call that describes how to reach the user agent server and other properties.</param> /// <param name="serverEndPoint">Optional. If the server end point for the call is known or has been resolved in advance. If /// not set the SIP transport layer will attempt to resolve the destination at sending time.</param> public SIPRequest Call(SIPCallDescriptor sipCallDescriptor, SIPEndPoint serverEndPoint) { try { m_sipCallDescriptor = sipCallDescriptor; SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri); SIPRouteSet routeSet = null; logger.LogDebug($"UAC commencing call to {SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress}."); // A custom route set may have been specified for the call. if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1) { try { routeSet = new SIPRouteSet(); routeSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true)); } catch { logger.LogDebug("Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + m_sipCallDescriptor.RouteSet + "."); } } string content = sipCallDescriptor.Content; if (content.IsNullOrBlank()) { logger.LogDebug("Body on UAC call was empty."); } if (this.m_sipCallDescriptor.BranchId.IsNullOrBlank()) { this.m_sipCallDescriptor.BranchId = CallProperties.CreateBranchId(); } if (this.m_sipCallDescriptor.CallId.IsNullOrBlank()) { this.m_sipCallDescriptor.CallId = CallProperties.CreateNewCallId(); } SIPRequest inviteRequest = GetInviteRequest(m_sipCallDescriptor, m_sipCallDescriptor.BranchId, m_sipCallDescriptor.CallId, routeSet, content, sipCallDescriptor.ContentType); // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_serverTransaction = new UACInviteTransaction(m_sipTransport, inviteRequest, m_outboundProxy); m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; m_serverTransaction.UACInviteTransactionFailed += ServerTransactionFailed; m_serverTransaction.SendInviteRequest(); return(inviteRequest); } catch (ApplicationException appExcp) { m_serverTransaction?.CancelCall(appExcp.Message); CallFailed?.Invoke(this, appExcp.Message, null); return(null); } catch (Exception excp) { logger.LogError("Exception UserAgentClient Call. " + excp); m_serverTransaction?.CancelCall("Unknown exception"); CallFailed?.Invoke(this, excp.Message, null); return(null); } }
public static void NotifyCallFailed(Exception exception) { MainThread.BeginInvokeOnMainThread(() => CallFailed?.Invoke(null, exception)); }