private SIPResponse GetCancelResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum sipResponseCode) { try { SIPResponse cancelResponse = new SIPResponse(sipResponseCode, null, sipRequest.LocalSIPEndPoint); SIPHeader requestHeader = sipRequest.Header; cancelResponse.Header = new SIPHeader(requestHeader.From, requestHeader.To, requestHeader.CSeq, requestHeader.CallId); cancelResponse.Header.CSeqMethod = SIPMethodsEnum.CANCEL; cancelResponse.Header.Vias = requestHeader.Vias; cancelResponse.Header.MaxForwards = Int32.MinValue; return cancelResponse; } catch (Exception excp) { logger.Error("Exception GetCancelResponse. " + excp.Message); throw excp; } }
public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum statusCode, string reason) { SIPResponse errorResponse = SIPTransport.GetResponse(sipRequest, statusCode, reason); m_sipTransport.SendResponse(m_outboundProxy, errorResponse); }
public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { try { if (m_uasTransaction.TransactionFinalResponse == null) { if ((int)failureStatus < 400) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS Reject was passed an invalid response status of " + (int)failureStatus + ", ignoring.", m_owner)); } else { if (UASStateChanged != null) { UASStateChanged(this, failureStatus, reasonPhrase); } string failureReason = (!reasonPhrase.IsNullOrBlank()) ? " and " + reasonPhrase : null; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call failed with a response status of " + (int)failureStatus + failureReason + ".", m_owner)); SIPResponse failureResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, failureStatus, reasonPhrase); if (customHeaders != null && customHeaders.Length > 0) { foreach (string header in customHeaders) { failureResponse.Header.UnknownHeaders.Add(header); } } m_uasTransaction.SendFinalResponse(failureResponse); } } else { logger.Warn("SIPServerUserAgent Reject fired on already answered call."); } } catch (Exception excp) { logger.Error("Exception SIPServerUserAgent Reject. " + excp.Message); } }
/// <summary> /// Used to create a SIP response when it was not possible to parse the incoming SIP request. /// </summary> public SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase) { try { if (localSIPEndPoint == null) { localSIPEndPoint = GetDefaultSIPEndPoint(); } SIPResponse response = new SIPResponse(responseCode, reasonPhrase, localSIPEndPoint); SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip; SIPFromHeader from = new SIPFromHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null); SIPToHeader to = new SIPToHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null); int cSeq = 1; string callId = CallProperties.CreateNewCallId(); response.Header = new SIPHeader(from, to, cSeq, callId); response.Header.CSeqMethod = SIPMethodsEnum.NONE; response.Header.Vias.PushViaHeader(new SIPViaHeader(new SIPEndPoint(localSIPEndPoint.Protocol, remoteEndPoint.GetIPEndPoint()), CallProperties.CreateBranchId())); response.Header.MaxForwards = Int32.MinValue; response.Header.Allow = ALLOWED_SIP_METHODS; return response; } catch (Exception excp) { logger.Error("Exception SIPTransport GetResponse. " + excp.Message); throw; } }
/// <summary> /// Handler for processing incoming SIP requests. /// </summary> /// <param name="localSIPEndPoint">The end point the request was received on.</param> /// <param name="remoteEndPoint">The end point the request came from.</param> /// <param name="sipRequest">The SIP request received.</param> private static async Task SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) { try { if (sipRequest.Method == SIPMethodsEnum.BYE) { throw new NotImplementedException(); } else if (sipRequest.Method == SIPMethodsEnum.CANCEL) { throw new NotImplementedException(); } else if (sipRequest.Method == SIPMethodsEnum.INVITE) { throw new NotImplementedException(); } else if (sipRequest.Method == SIPMethodsEnum.OPTIONS) { SIPResponse optionsResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); await _sipTransport.SendResponseAsync(optionsResponse); } else if (sipRequest.Method == SIPMethodsEnum.REGISTER) { SIPResponse tryingResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Trying, null); await _sipTransport.SendResponseAsync(tryingResponse); SIPResponseStatusCodesEnum registerResponse = SIPResponseStatusCodesEnum.Ok; if (sipRequest.Header.Contact != null && sipRequest.Header.Contact.Count > 0) { int expiry = sipRequest.Header.Contact[0].Expires > 0 ? sipRequest.Header.Contact[0].Expires : sipRequest.Header.Expires; var sipAccount = new SIPAccount(null, sipRequest.Header.From.FromURI.Host, sipRequest.Header.From.FromURI.User, null, null); SIPAccountBinding binding = new SIPAccountBinding(sipAccount, sipRequest.Header.Contact[0].ContactURI, remoteEndPoint, localSIPEndPoint, expiry); if (_sipRegistrations.ContainsKey(sipAccount.SIPUsername)) { _sipRegistrations.Remove(sipAccount.SIPUsername); } _sipRegistrations.Add(sipAccount.SIPUsername, binding); logger.LogDebug("Registered contact for " + sipAccount.SIPUsername + " as " + binding.RegisteredContact.ToString() + "."); } else { registerResponse = SIPResponseStatusCodesEnum.BadRequest; } SIPNonInviteTransaction registerTransaction = new SIPNonInviteTransaction(_sipTransport, sipRequest, null); SIPResponse okResponse = SIPResponse.GetResponse(sipRequest, registerResponse, null); registerTransaction.SendResponse(okResponse); } else { logger.LogDebug("SIP " + sipRequest.Method + " request received but no processing has been set up for it, rejecting."); } } catch (NotImplementedException) { logger.LogDebug(sipRequest.Method + " request processing not implemented for " + sipRequest.URI.ToParameterlessString() + " from " + remoteEndPoint + "."); SIPResponse notImplResponse = SIPResponse.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotImplemented, null); await _sipTransport.SendResponseAsync(notImplResponse); } }
public void AnswerNonInvite(SIPResponseStatusCodesEnum answerStatus, string reasonPhrase, string[] customHeaders, string contentType, string body) { throw new NotImplementedException(); }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody) { throw new NotImplementedException(); }
public SIPValidationException(SIPValidationFieldsEnum sipErrorField, SIPResponseStatusCodesEnum responseErrorCode, string message) : base(message) { SIPErrorField = sipErrorField; SIPResponseErrorCode = responseErrorCode; }
public void Answered(int answerStatusCode, SIPResponseStatusCodesEnum answerStatus, string answerReason) { try { IsAnswered = true; AnswerTime = DateTimeOffset.UtcNow; AnswerStatus = (int)answerStatus; AnswerReasonPhrase = answerReason; CDRAnswered(this); } catch (Exception excp) { logger.Error("Exception SIPCDR Answered. " + excp.Message); } }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string progressReason) { InProgress = true; ProgressTime = DateTimeOffset.UtcNow; ProgressStatus = (int)progressStatus; ProgressReasonPhrase = progressReason; }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { NoRingTimeout.Invoke(this); logger.Debug("SIPB2BUserAgent Redirect."); //m_uas.Redirect(redirectCode, redirectURI); }
private void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac) { try { Log("Progress response of " + progressStatus + " received on CallBack Dial" + "."); if (m_firstLegDialogue != null && !progressBody.IsNullOrBlank() && !m_firstLegEarlyMediaSet) { m_firstLegEarlyMediaSet = true; // The first leg is up and a call on the second leg has some early media that can be passed on. //m_callManager.ReInvite(m_firstLegDialogue, progressBody); } } catch (Exception excp) { logger.Error("Exception CallbackApp. " + excp.Message); } }
public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, m_transaction.TransactionRequest.Method + " request failed with a response status of " + (int)failureStatus + " " + reasonPhrase + ".", m_owner)); SIPResponse failureResponse = SIPTransport.GetResponse(m_transaction.TransactionRequest, failureStatus, reasonPhrase); m_transaction.SendFinalResponse(failureResponse); }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { throw new NotImplementedException(); }
private void Subscribe(SIPTransaction subscribeTransaction) { try { SIPRequest sipRequest = subscribeTransaction.TransactionRequest; string fromUser = sipRequest.Header.From.FromURI.User; string fromHost = sipRequest.Header.From.FromURI.Host; string canonicalDomain = GetCanonicalDomain_External(fromHost, true); if (canonicalDomain == null) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Subscribe request for " + fromHost + " rejected as no matching domain found.", null)); SIPResponse noDomainResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced"); subscribeTransaction.SendFinalResponse(noDomainResponse); return; } SIPAccount sipAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == fromUser && s.SIPDomain == canonicalDomain); SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(subscribeTransaction.LocalSIPEndPoint, subscribeTransaction.RemoteEndPoint, sipRequest, sipAccount, FireProxyLogEvent); if (!authenticationResult.Authenticated) { // 401 Response with a fresh nonce needs to be sent. SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null); authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader; subscribeTransaction.SendFinalResponse(authReqdResponse); if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Warn, "Forbidden " + fromUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom.ToString() + ", " + sipRequest.Header.UserAgent + ".", null)); } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Authentication required for " + fromUser + "@" + canonicalDomain + " from " + subscribeTransaction.RemoteEndPoint + ".", sipAccount.Owner)); } return; } else { if (sipRequest.Header.To.ToTag != null) { // Request is to renew an existing subscription. SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None; string errorResponseReason = null; string sessionID = m_subscriptionsManager.RenewSubscription(sipRequest, out errorResponse, out errorResponseReason); if (errorResponse != SIPResponseStatusCodesEnum.None) { // A subscription renewal attempt failed SIPResponse renewalErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason); subscribeTransaction.SendFinalResponse(renewalErrorResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription renewal failed for event type " + sipRequest.Header.Event + " " + sipRequest.URI.ToString() + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner)); } else if (sipRequest.Header.Expires == 0) { // Existing subscription was closed. SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); subscribeTransaction.SendFinalResponse(okResponse); } else { // Existing subscription was found. SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); subscribeTransaction.SendFinalResponse(okResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeRenew, "Subscription renewal for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner)); m_subscriptionsManager.SendFullStateNotify(sessionID); } } else { // Authenticated but the this is a new subscription request and authorisation to subscribe to the requested resource also needs to be checked. SIPURI canonicalResourceURI = sipRequest.URI.CopyOf(); string resourceCanonicalDomain = GetCanonicalDomain_External(canonicalResourceURI.Host, true); canonicalResourceURI.Host = resourceCanonicalDomain; SIPAccount resourceSIPAccount = null; if (resourceCanonicalDomain == null) { SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Domain " + resourceCanonicalDomain + " not serviced"); subscribeTransaction.SendFinalResponse(notFoundResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", domain not serviced.", sipAccount.Owner)); return; } if (canonicalResourceURI.User != m_wildcardUser) { resourceSIPAccount = m_sipAssetPersistor.Get(s => s.SIPUsername == canonicalResourceURI.User && s.SIPDomain == canonicalResourceURI.Host); if (resourceSIPAccount == null) { SIPResponse notFoundResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.NotFound, "Requested resource does not exist"); subscribeTransaction.SendFinalResponse(notFoundResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", SIP account does not exist.", sipAccount.Owner)); return; } } // Check the owner permissions on the requesting and subscribed resources. bool authorised = false; string adminID = null; if (canonicalResourceURI.User == m_wildcardUser || sipAccount.Owner == resourceSIPAccount.Owner) { authorised = true; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to common owner.", sipAccount.Owner)); } else { // Lookup the customer record for the requestor and check the administrative level on it. Customer requestingCustomer = GetCustomer_External(c => c.CustomerUsername == sipAccount.Owner); adminID = requestingCustomer.AdminId; if (!resourceSIPAccount.AdminMemberId.IsNullOrBlank() && requestingCustomer.AdminId == resourceSIPAccount.AdminMemberId) { authorised = true; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor admin permissions for domain " + resourceSIPAccount.AdminMemberId + ".", sipAccount.Owner)); } else if (requestingCustomer.AdminId == m_topLevelAdminID) { authorised = true; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAuth, "Subscription to " + canonicalResourceURI.ToString() + " authorised due to requestor having top level admin permissions.", sipAccount.Owner)); } } if (authorised) { // Request is to create a new subscription. SIPResponseStatusCodesEnum errorResponse = SIPResponseStatusCodesEnum.None; string errorResponseReason = null; string toTag = CallProperties.CreateNewTag(); string sessionID = m_subscriptionsManager.SubscribeClient(sipAccount.Owner, adminID, sipRequest, toTag, canonicalResourceURI, out errorResponse, out errorResponseReason); if (errorResponse != SIPResponseStatusCodesEnum.None) { SIPResponse subscribeErrorResponse = SIPTransport.GetResponse(sipRequest, errorResponse, errorResponseReason); subscribeTransaction.SendFinalResponse(subscribeErrorResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", " + errorResponse + " " + errorResponseReason + ".", sipAccount.Owner)); } else { SIPResponse okResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Ok, null); okResponse.Header.To.ToTag = toTag; okResponse.Header.Expires = sipRequest.Header.Expires; okResponse.Header.Contact = new List <SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(SIPSchemesEnum.sip, subscribeTransaction.LocalSIPEndPoint)) }; subscribeTransaction.SendFinalResponse(okResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Subscription accepted for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + " and expiry " + sipRequest.Header.Expires + ".", sipAccount.Owner)); if (sessionID != null) { m_subscriptionsManager.SendFullStateNotify(sessionID); } } } else { SIPResponse forbiddenResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Requested resource not authorised"); subscribeTransaction.SendFinalResponse(forbiddenResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Subscription failed for " + sipRequest.URI.ToString() + ", event type " + sipRequest.Header.Event + ", requesting account " + sipAccount.Owner + " was not authorised.", sipAccount.Owner)); } } } } catch (Exception excp) { logger.Error("Exception notifiercore subscribing. " + excp.Message + "\r\n" + subscribeTransaction.TransactionRequest.ToString()); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.Error, "Exception notifiercore subscribing. " + excp.Message, null)); SIPResponse errorResponse = SIPTransport.GetResponse(subscribeTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null); subscribeTransaction.SendFinalResponse(errorResponse); } }
private void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac) { SIPResponse progressResponse = new SIPResponse(progressStatus, reasonPhrase, null); CallRinging(this, progressResponse); }
private void SendNotifyRequestForRefer(SIPRequest referRequest, SIPDialogue referDialogue, SIPEndPoint localEndPoint, SIPResponseStatusCodesEnum responseCode, string responseReason) { try { //logger.Debug("Sending NOTIFY for refer subscription to " + referDialogue.RemoteTarget.ToParameterlessString() + ", status " + responseCode + " " + responseReason + "."); referDialogue.CSeq++; m_sipDialoguePersistor.UpdateProperty(referDialogue.Id, "CSeq", referDialogue.CSeq); SIPRequest notifyTryingRequest = GetNotifyRequest(referRequest, referDialogue, new SIPResponse(responseCode, responseReason, null), localEndPoint); SIPEndPoint forwardEndPoint = null; SIPDNSLookupResult lookupResult = m_sipTransport.GetRequestEndPoint(notifyTryingRequest, m_outboundProxy, false); if (lookupResult.LookupError != null) { logger.Warn("SendNotifyRequestForRefer Failed to resolve " + lookupResult.URI.Host + "."); } else { forwardEndPoint = lookupResult.GetSIPEndPoint(); } SIPNonInviteTransaction notifyTryingTransaction = m_sipTransport.CreateNonInviteTransaction(notifyTryingRequest, forwardEndPoint, localEndPoint, m_outboundProxy); notifyTryingTransaction.SendReliableRequest(); } catch (Exception excp) { logger.Error("Exception SendNotifyRequestForRefer. " + excp.Message); } }
public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { logger.Warn("SIPTransferServerUserAgent Reject called with " + failureStatus + " " + reasonPhrase + "."); UASStateChanged?.Invoke(this, failureStatus, reasonPhrase); }
public SIPRequestAuthenticationResult(SIPResponseStatusCodesEnum errorResponse, SIPAuthenticationHeader authenticationRequiredHeader) { Authenticated = false; ErrorResponse = errorResponse; AuthenticationRequiredHeader = authenticationRequiredHeader; }
private RegisterResultEnum Register(SIPTransaction registerTransaction) { try { SIPRequest sipRequest = registerTransaction.TransactionRequest; SIPURI registerURI = sipRequest.URI; SIPToHeader toHeader = sipRequest.Header.To; string toUser = toHeader.ToURI.User; string canonicalDomain = toHeader.ToURI.Host; int requestedExpiry = GetRequestedExpiry(sipRequest); if (canonicalDomain == null) { SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced"); registerTransaction.SendFinalResponse(noDomainResponse); return(RegisterResultEnum.DomainNotServiced); } SIPAccount sipAccount = new SIPAccount { Id = Guid.NewGuid(), Owner = "admin", SIPUsername = toUser, SIPDomain = canonicalDomain }; SIPRequestAuthenticationResult authenticationResult = _sipRequestAuthenticator_External?.Invoke(registerTransaction.LocalSIPEndPoint, registerTransaction.RemoteEndPoint, sipRequest, sipAccount); if (!_needAuthentication) { SIPResponse okRes = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okRes); if (requestedExpiry > 0) { CacheDeviceItem(sipRequest); RegisterReceived?.Invoke(sipRequest, _localSipAccount); } if (requestedExpiry == 0) { RemoveDeviceItem(sipRequest); UnRegisterReceived?.Invoke(sipRequest, _localSipAccount); } return(RegisterResultEnum.AuthenticationRequired); } if (!authenticationResult.Authenticated) { // 401 Response with a fresh nonce needs to be sent. SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null); authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader; registerTransaction.SendFinalResponse(authReqdResponse); if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden) { return(RegisterResultEnum.Forbidden); } else { return(RegisterResultEnum.AuthenticationRequired); } } else { if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0) { SIPResponse okResponse = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okResponse); if (requestedExpiry > 0) { CacheDeviceItem(sipRequest); RegisterReceived?.Invoke(sipRequest, _localSipAccount); } if (requestedExpiry == 0) { RemoveDeviceItem(sipRequest); UnRegisterReceived?.Invoke(sipRequest, _localSipAccount); } } else { SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? registerTransaction.RemoteEndPoint; SIPEndPoint proxySIPEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn); SIPEndPoint registrarEndPoint = registerTransaction.LocalSIPEndPoint; SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok; DateTime startTime = DateTime.Now; TimeSpan duration = DateTime.Now.Subtract(startTime); if (updateResult == SIPResponseStatusCodesEnum.Ok) { string proxySocketStr = (proxySIPEndPoint != null) ? " (proxy=" + proxySIPEndPoint.ToString() + ")" : null; SIPResponse okResponse = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okResponse); if (requestedExpiry > 0) { CacheDeviceItem(sipRequest); RegisterReceived?.Invoke(sipRequest, _localSipAccount); } if (requestedExpiry == 0) { RemoveDeviceItem(sipRequest); UnRegisterReceived?.Invoke(sipRequest, _localSipAccount); } } else { sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry; SIPResponse okResponse = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okResponse); } } return(RegisterResultEnum.Authenticated); } } catch (Exception excp) { string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" + registerTransaction.TransactionRequest.ToString(); logger.Error(regErrorMessage); try { SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null); registerTransaction.SendFinalResponse(errorResponse); } catch { } return(RegisterResultEnum.Error); } }
/// <summary> /// Helper method for dynamic proxy runtime script. /// </summary> /// <param name="responseCode"></param> /// <param name="localEndPoint"></param> /// <param name="remoteEndPoint"></param> /// <param name="sipRequest"></param> public void Respond(SIPRequest sipRequest, SIPResponseStatusCodesEnum responseCode, string reasonPhrase) { SIPResponse response = SIPTransport.GetResponse(sipRequest, responseCode, reasonPhrase); m_sipTransport.SendResponse(response); }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { Redirect(redirectCode, redirectURI, null); }
/// <summary> /// Updates the bindings list for a registrar's address-of-records. /// </summary> /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param> /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param> /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param> /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param> /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns> public List <SIPRegistrarBinding> UpdateBindings( SIPAccount sipAccount, SIPEndPoint proxySIPEndPoint, SIPEndPoint remoteSIPEndPoint, SIPEndPoint registrarSIPEndPoint, List <SIPContactHeader> contactHeaders, string callId, int cseq, //int contactHeaderExpiresValue, int expiresHeaderValue, string userAgent, out SIPResponseStatusCodesEnum responseStatus, out string responseMessage) { //logger.Debug("UpdateBinding " + bindingURI.ToString() + "."); int maxAllowedExpiry = (m_userAgentConfigs != null) ? m_userAgentConfigs.GetMaxAllowedExpiry(userAgent) : SIPUserAgentConfiguration.DEFAULT_MAX_EXPIRY_SECONDS; responseMessage = null; string sipAccountAOR = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain; responseStatus = SIPResponseStatusCodesEnum.Ok; try { userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent; List <SIPRegistrarBinding> bindings = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue); foreach (SIPContactHeader contactHeader in contactHeaders) { SIPURI bindingURI = contactHeader.ContactURI.CopyOf(); int contactHeaderExpiresValue = contactHeader.Expires; int bindingExpiry = 0; if (bindingURI.Host == m_sipRegisterRemoveAll) { if (contactHeaders.Count > 1) { // If a register request specifies remove all it cannot contain any other binding requests. FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request.", sipAccount.SIPUsername)); responseStatus = SIPResponseStatusCodesEnum.BadRequest; break; } #region Process remove all bindings. if (expiresHeaderValue == 0) { // Removing all bindings for user. FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + ".", sipAccount.SIPUsername)); // Mark all the current bindings as expired. if (bindings != null && bindings.Count > 0) { for (int index = 0; index < bindings.Count; index++) { bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll; bindings[index].Expiry = 0; m_bindingsPersistor.Update(bindings[index]); // Remove the NAT keep-alive job if present. if (m_natKeepAliveJobs.ContainsKey(bindings[index].RemoteSIPSocket)) { m_natKeepAliveJobs[bindings[index].RemoteSIPSocket].CancelJob(); } } } FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); responseStatus = SIPResponseStatusCodesEnum.Ok; } else { // Remove all header cannot be present with other headers and must have an Expiry equal to 0. responseStatus = SIPResponseStatusCodesEnum.BadRequest; } #endregion } else { int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue; requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry; // This will happen if the Expires header and the Expiry on the Contact are both missing. bindingExpiry = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry; bindingExpiry = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry; bindingURI.Parameters.Remove(m_sipExpiresParameterKey); SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString()); if (binding != null) { if (requestedExpiry <= 0) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingExpired, "Binding expired by client for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ".", sipAccount.SIPUsername)); bindings.Remove(binding); m_bindingsPersistor.Delete(binding); bindingExpiry = 0; FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); // Remove the NAT keep-alive job if present. if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket)) { m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob(); } } else { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Binding update request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner)); binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled); DateTime startTime = DateTime.Now; m_bindingsPersistor.Update(binding); TimeSpan duration = DateTime.Now.Subtract(startTime); //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null)); FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); // Add a NAT keep-alive job if required. if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null) { AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, binding, bindingExpiry); } } } else { if (requestedExpiry > 0) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "New binding request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner)); if (bindings.Count >= m_maxBindingsPerAccount) { // Need to remove the oldest binding to stay within limit. //SIPRegistrarBinding oldestBinding = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue).OrderBy(x => x.LastUpdateUTC).Last(); SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last(); FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "Binding limit exceeded for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + " removing oldest binding to stay within limit of " + m_maxBindingsPerAccount + ".", sipAccount.Owner)); m_bindingsPersistor.Delete(oldestBinding); if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket)) { m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob(); } } SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry); DateTime startTime = DateTime.Now; bindings.Add(newBinding); m_bindingsPersistor.Add(newBinding); TimeSpan duration = DateTime.Now.Subtract(startTime); //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database add time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null)); // Add a NAT keep-alive job if required. if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null) { AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, newBinding, bindingExpiry); } FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); } else { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingFailed, "New binding received for " + sipAccountAOR + " with expired contact," + bindingURI.ToString() + " no update.", sipAccount.Owner)); bindingExpiry = 0; } } responseStatus = SIPResponseStatusCodesEnum.Ok; } } return(bindings); } catch (Exception excp) { logger.Error("Exception UpdateBinding. " + excp.Message); FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registrar error updating binding: " + excp.Message + " Binding not updated.", sipAccount.SIPUsername)); responseStatus = SIPResponseStatusCodesEnum.InternalServerError; return(null); } }
public void Answered(int answerStatusCode, SIPResponseStatusCodesEnum answerStatus, string answerReason, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint) { try { IsAnswered = true; AnswerTime = DateTimeOffset.UtcNow; AnswerStatus = (int)answerStatus; AnswerReasonPhrase = answerReason; AnsweredAt = DateTime.Now; if (localEndPoint != null) { LocalSIPEndPoint = localEndPoint; } if (remoteEndPoint != null) { RemoteEndPoint = remoteEndPoint; } CDRAnswered(this); } catch (Exception excp) { logger.Error("Exception SIPCDR Answered. " + excp); } }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody) { try { if (!IsUASAnswered) { if ((int)progressStatus >= 200) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call was passed an invalid response status of " + (int)progressStatus + ", ignoring.", m_owner)); } else { if (UASStateChanged != null) { UASStateChanged(this, progressStatus, reasonPhrase); } // Allow all Trying responses through as some may contain additional useful information on the call state for the caller. // Also if the response is a 183 Session Progress with audio forward it. if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding && progressStatus != SIPResponseStatusCodesEnum.Trying && !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call ignoring progress response with status of " + (int)progressStatus + " as already in " + m_uasTransaction.TransactionState + ".", m_owner)); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call progressing with " + progressStatus + ".", m_owner)); SIPResponse progressResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, progressStatus, reasonPhrase); if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying) { progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag; } if (!m_gruu.IsNullOrBlank()) { // wenn wir das wieder löschen muss die gruu im contact header manuell rein! progressResponse.Header.To.ToURI.Parameters.Set(SIPCallDescriptor.GRUU_KEY, m_gruu); } if (!progressBody.IsNullOrBlank()) { progressResponse.Body = progressBody; progressResponse.Header.ContentType = progressContentType; progressResponse.Header.ContentLength = progressBody.Length; } //added contact header for RFC 4235 compliance progressResponse.Header.Contact = SIPContactHeader.ParseContactHeader("<" + m_uasTransaction.TransactionRequest.Header.To.ToURI.ToString() + ">"); if (customHeaders != null && customHeaders.Length > 0) { foreach (string header in customHeaders) { progressResponse.Header.UnknownHeaders.Add(header); } } m_uasTransaction.SendInformationalResponse(progressResponse); } } } else { logger.Warn("SIPServerUserAgent Progress fired on already answered call."); } } catch (Exception excp) { logger.Error("Exception SIPServerUserAgent Progress. " + excp.Message); } }
public void CallAnswered(SIPResponseStatusCodesEnum answeredStatus, string reasonPhrase, string toTag, string[] customHeaders, string answeredContentType, string answeredBody, SIPDialogue answeredDialogue, SIPDialogueTransferModesEnum uasTransferMode) { try { if (!m_isAnswered) { m_isAnswered = true; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Answering client call with a response status of " + (int)answeredStatus + ".", Owner)); SIPDialogue uasDialogue = m_sipServerUserAgent.Answer(answeredContentType, answeredBody, toTag, answeredDialogue, uasTransferMode); if (!m_sipServerUserAgent.IsB2B && answeredDialogue != null) { if (uasDialogue != null) { // Duplicate switchboard dialogue settings. uasDialogue.SwitchboardDescription = answeredDialogue.SwitchboardDescription; uasDialogue.SwitchboardCallerDescription = answeredDialogue.SwitchboardCallerDescription; uasDialogue.SwitchboardOwner = answeredDialogue.SwitchboardOwner; // Record the now established call with the call manager for in dialogue management and hangups. CreateBridge_External(uasDialogue, answeredDialogue, m_dialPlan.Owner); } else { logger.Warn("Failed to get a SIPDialogue from UAS.Answer."); } } } else { logger.Warn("DialPlanContext CallAnswered fired on already answered call."); } } catch (Exception excp) { logger.Error("Exception DialPlanContext CallAnswered. " + excp.Message); } finally { DialPlanExecutionFinished(); } }
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 + "."); 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; if (CallAnswered != null) { CallAnswered(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); } }
public void CallFailed(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { try { if (!m_isAnswered) { m_isAnswered = true; if ((int)failureStatus >= 300 && (int)failureStatus <= 399) { SIPURI redirectURI = SIPURI.ParseSIPURIRelaxed(customHeaders[0]); m_sipServerUserAgent.Redirect(failureStatus, redirectURI); } else { m_sipServerUserAgent.Reject(failureStatus, reasonPhrase, customHeaders); } } } catch (Exception excp) { logger.Error("Exception DialPlanContext CallFailed. " + excp.Message); } finally { DialPlanExecutionFinished(); } }
private SIPResponse GetErrorResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum errorResponseCode, string errorMessage) { try { SIPResponse errorResponse = SIPTransport.GetResponse(sipRequest, errorResponseCode, null); if (errorMessage != null) { errorResponse.ReasonPhrase = errorMessage; } SIPHeader requestHeader = sipRequest.Header; SIPHeader errorHeader = new SIPHeader(requestHeader.Contact, requestHeader.From, requestHeader.To, requestHeader.CSeq, requestHeader.CallId); if (errorHeader.To.ToTag == null || errorHeader.To.ToTag.Trim().Length == 0) { errorHeader.To.ToTag = CallProperties.CreateNewTag(); } errorHeader.CSeqMethod = requestHeader.CSeqMethod; errorHeader.Vias = requestHeader.Vias; errorHeader.Server = m_serverAgent; errorHeader.MaxForwards = Int32.MinValue; errorResponse.Header = errorHeader; return errorResponse; } catch (Exception excp) { logger.Error("Exception GetErrorResponse. " + excp.Message); throw excp; } }
public void CallProgress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody, ISIPClientUserAgent uac) { if (!m_isAnswered) { m_sipServerUserAgent.Progress(progressStatus, reasonPhrase, customHeaders, progressContentType, progressBody); if (uac != null && uac.CallDescriptor.RequestCallerDetails && CallerCRMDetails != null) { if (CallerCRMDetails.Pending && !m_uacWaitingForCallDetails.Contains(uac) && !m_uacCallDetailsSent.Contains(uac)) { m_uacWaitingForCallDetails.Add(uac); } else if (!CallerCRMDetails.Pending && !m_uacCallDetailsSent.Contains(uac)) { // Send the call details to the client user agent. uac.Update(CallerCRMDetails); } } } }
/// <summary> /// Updates the bindings list for a registrar's address-of-records. /// </summary> /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param> /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param> /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param> /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param> /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns> public List<SIPRegistrarBinding> UpdateBindings( SIPAccount sipAccount, SIPEndPoint proxySIPEndPoint, SIPEndPoint remoteSIPEndPoint, SIPEndPoint registrarSIPEndPoint, List<SIPContactHeader> contactHeaders, string callId, int cseq, //int contactHeaderExpiresValue, int expiresHeaderValue, string userAgent, out SIPResponseStatusCodesEnum responseStatus, out string responseMessage) { //logger.Debug("UpdateBinding " + bindingURI.ToString() + "."); int maxAllowedExpiry = m_userAgentConfigs.GetMaxAllowedExpiry(userAgent); responseMessage = null; string sipAccountAOR = sipAccount.SIPUsername + "@" + sipAccount.SIPDomain; responseStatus = SIPResponseStatusCodesEnum.Ok; try { userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent; List<SIPRegistrarBinding> bindings = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue); foreach (SIPContactHeader contactHeader in contactHeaders) { SIPURI bindingURI = contactHeader.ContactURI.CopyOf(); int contactHeaderExpiresValue = contactHeader.Expires; int bindingExpiry = 0; if (bindingURI.Host == m_sipRegisterRemoveAll) { if (contactHeaders.Count > 1) { // If a register request specifies remove all it cannot contain any other binding requests. FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request.", sipAccount.SIPUsername)); responseStatus = SIPResponseStatusCodesEnum.BadRequest; break; } #region Process remove all bindings. if (expiresHeaderValue == 0) { // Removing all bindings for user. FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingRemoval, "Remove all bindings requested for " + sipAccountAOR + ".", sipAccount.SIPUsername)); // Mark all the current bindings as expired. if (bindings != null && bindings.Count > 0) { for (int index = 0; index < bindings.Count; index++) { bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll; bindings[index].Expiry = 0; m_bindingsPersistor.Update(bindings[index]); // Remove the NAT keep-alive job if present. if (m_natKeepAliveJobs.ContainsKey(bindings[index].RemoteSIPSocket)) { m_natKeepAliveJobs[bindings[index].RemoteSIPSocket].CancelJob(); } } } FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); responseStatus = SIPResponseStatusCodesEnum.Ok; } else { // Remove all header cannot be present with other headers and must have an Expiry equal to 0. responseStatus = SIPResponseStatusCodesEnum.BadRequest; } #endregion } else { int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue; requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry; // This will happen if the Expires header and the Expiry on the Contact are both missing. bindingExpiry = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry; bindingExpiry = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry; bindingURI.Parameters.Remove(m_sipExpiresParameterKey); SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString()); if (binding != null) { if (requestedExpiry <= 0) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingExpired, "Binding expired by client for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ".", sipAccount.SIPUsername)); bindings.Remove(binding); m_bindingsPersistor.Delete(binding); bindingExpiry = 0; FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); // Remove the NAT keep-alive job if present. if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket)) { m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob(); } } else { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Binding update request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner)); binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled); DateTime startTime = DateTime.Now; m_bindingsPersistor.Update(binding); TimeSpan duration = DateTime.Now.Subtract(startTime); //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null)); FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); // Add a NAT keep-alive job if required. if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null) { AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, binding, bindingExpiry); } } } else { if (requestedExpiry > 0) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "New binding request for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + ", expiry requested " + requestedExpiry + "s granted " + bindingExpiry + "s.", sipAccount.Owner)); if (bindings.Count >= m_maxBindingsPerAccount) { // Need to remove the oldest binding to stay within limit. //SIPRegistrarBinding oldestBinding = m_bindingsPersistor.Get(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue).OrderBy(x => x.LastUpdateUTC).Last(); SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last(); FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingInProgress, "Binding limit exceeded for " + sipAccountAOR + " from " + remoteSIPEndPoint.ToString() + " removing oldest binding to stay within limit of " + m_maxBindingsPerAccount + ".", sipAccount.Owner)); m_bindingsPersistor.Delete(oldestBinding); if (m_natKeepAliveJobs.ContainsKey(binding.RemoteSIPSocket)) { m_natKeepAliveJobs[binding.RemoteSIPSocket].CancelJob(); } } SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry); DateTime startTime = DateTime.Now; bindings.Add(newBinding); m_bindingsPersistor.Add(newBinding); TimeSpan duration = DateTime.Now.Subtract(startTime); //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database add time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null)); // Add a NAT keep-alive job if required. if (sipAccount.SendNATKeepAlives && proxySIPEndPoint != null) { AddNATKeepAliveJob(sipAccount, remoteSIPEndPoint, proxySIPEndPoint, newBinding, bindingExpiry); } FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); } else { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.BindingFailed, "New binding received for " + sipAccountAOR + " with expired contact," + bindingURI.ToString() + " no update.", sipAccount.Owner)); bindingExpiry = 0; } } responseStatus = SIPResponseStatusCodesEnum.Ok; } } return bindings; } catch (Exception excp) { logger.Error("Exception UpdateBinding. " + excp.Message); FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registrar error updating binding: " + excp.Message + " Binding not updated.", sipAccount.SIPUsername)); responseStatus = SIPResponseStatusCodesEnum.InternalServerError; return null; } }
private RegisterResultEnum Register(SIPTransaction registerTransaction) { try { SIPRequest sipRequest = registerTransaction.TransactionRequest; SIPURI registerURI = sipRequest.URI; SIPToHeader toHeader = sipRequest.Header.To; string toUser = toHeader.ToURI.User; string canonicalDomain = (m_strictRealmHandling) ? GetCanonicalDomain_External(toHeader.ToURI.Host, true) : toHeader.ToURI.Host; int requestedExpiry = GetRequestedExpiry(sipRequest); if (canonicalDomain == null) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for " + toHeader.ToURI.Host + " rejected as no matching domain found.", null)); SIPResponse noDomainResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.Forbidden, "Domain not serviced"); registerTransaction.SendFinalResponse(noDomainResponse); return(RegisterResultEnum.DomainNotServiced); } SIPAccountAsset sipAccountAsset = GetSIPAccount_External(s => s.SIPUsername == toUser && s.SIPDomain == canonicalDomain); SIPRequestAuthenticationResult authenticationResult = SIPRequestAuthenticator_External(registerTransaction.LocalSIPEndPoint, registerTransaction.RemoteEndPoint, sipRequest, sipAccountAsset.SIPAccount, FireProxyLogEvent); if (!authenticationResult.Authenticated) { // 401 Response with a fresh nonce needs to be sent. SIPResponse authReqdResponse = SIPTransport.GetResponse(sipRequest, authenticationResult.ErrorResponse, null); authReqdResponse.Header.AuthenticationHeader = authenticationResult.AuthenticationRequiredHeader; registerTransaction.SendFinalResponse(authReqdResponse); if (authenticationResult.ErrorResponse == SIPResponseStatusCodesEnum.Forbidden) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Forbidden " + toUser + "@" + canonicalDomain + " does not exist, " + sipRequest.Header.ProxyReceivedFrom + ", " + sipRequest.Header.UserAgent + ".", null)); return(RegisterResultEnum.Forbidden); } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Registrar, "Authentication required for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser)); return(RegisterResultEnum.AuthenticationRequired); } } else { // Authenticated. //if (!sipRequest.Header.UserAgent.IsNullOrBlank() && !m_switchboarduserAgentPrefix.IsNullOrBlank() && sipRequest.Header.UserAgent.StartsWith(m_switchboarduserAgentPrefix)) //{ // // Check that the switchboard user is authorised. // var customer = CustomerPersistor_External.Get(x => x.CustomerUsername == sipAccount.Owner); // if (!(customer.ServiceLevel == CustomerServiceLevels.Switchboard.ToString() || customer.ServiceLevel == CustomerServiceLevels.Gold.ToString())) // { // FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Warn, "Register request for switchboard from " + toHeader.ToURI.Host + " rejected as not correct service level.", sipAccount.Owner)); // SIPResponse payReqdResponse = GetErrorResponse(sipRequest, SIPResponseStatusCodesEnum.PaymentRequired, "You need to purchase a Switchboard service"); // registerTransaction.SendFinalResponse(payReqdResponse); // return RegisterResultEnum.SwitchboardPaymentRequired; // } //} if (sipRequest.Header.Contact == null || sipRequest.Header.Contact.Count == 0) { // No contacts header to update bindings with, return a list of the current bindings. List <SIPRegistrarBinding> bindings = m_registrarBindingsManager.GetBindings(sipAccountAsset.Id); //List<SIPContactHeader> contactsList = m_registrarBindingsManager.GetContactHeader(); // registration.GetContactHeader(true, null); if (bindings != null) { sipRequest.Header.Contact = GetContactHeader(bindings); } SIPResponse okResponse = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okResponse); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Empty registration request successful for " + toUser + "@" + canonicalDomain + " from " + sipRequest.Header.ProxyReceivedFrom + ".", toUser)); } else { SIPEndPoint uacRemoteEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedFrom) ?? registerTransaction.RemoteEndPoint; SIPEndPoint proxySIPEndPoint = SIPEndPoint.TryParse(sipRequest.Header.ProxyReceivedOn); SIPEndPoint registrarEndPoint = registerTransaction.LocalSIPEndPoint; SIPResponseStatusCodesEnum updateResult = SIPResponseStatusCodesEnum.Ok; string updateMessage = null; DateTime startTime = DateTime.Now; List <SIPRegistrarBinding> bindingsList = m_registrarBindingsManager.UpdateBindings( sipAccountAsset.SIPAccount, proxySIPEndPoint, uacRemoteEndPoint, registrarEndPoint, //sipRequest.Header.Contact[0].ContactURI.CopyOf(), sipRequest.Header.Contact, sipRequest.Header.CallId, sipRequest.Header.CSeq, //sipRequest.Header.Contact[0].Expires, sipRequest.Header.Expires, sipRequest.Header.UserAgent, out updateResult, out updateMessage); //int bindingExpiry = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString()); TimeSpan duration = DateTime.Now.Subtract(startTime); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding update time for " + toUser + "@" + canonicalDomain + " took " + duration.TotalMilliseconds + "ms.", null)); if (updateResult == SIPResponseStatusCodesEnum.Ok) { string proxySocketStr = (proxySIPEndPoint != null) ? " (proxy=" + proxySIPEndPoint.ToString() + ")" : null; int bindingCount = 1; foreach (SIPRegistrarBinding binding in bindingsList) { string bindingIndex = (bindingsList.Count == 1) ? String.Empty : " (" + bindingCount + ")"; //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + proxySocketStr + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser)); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegisterSuccess, "Registration successful for " + toUser + "@" + canonicalDomain + " from " + uacRemoteEndPoint + ", binding " + binding.ContactSIPURI.ToParameterlessString() + ";expiry=" + binding.Expiry + bindingIndex + ".", toUser)); //FireProxyLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, toUser, uacRemoteEndPoint, sipAccount.Id.ToString())); bindingCount++; } // The standard states that the Ok response should contain the list of current bindings but that breaks some UAs. As a // compromise the list is returned with the Contact that UAC sent as the first one in the list. bool contactListSupported = m_userAgentConfigs.GetUserAgentContactListSupport(sipRequest.Header.UserAgent); if (contactListSupported) { sipRequest.Header.Contact = GetContactHeader(bindingsList); } else { // Some user agents can't match the contact header if the expiry is added to it. sipRequest.Header.Contact[0].Expires = GetBindingExpiry(bindingsList, sipRequest.Header.Contact[0].ContactURI.ToString());; } SIPResponse okResponse = GetOkResponse(sipRequest); // If a request was made for a switchboard token and a certificate is available to sign the tokens then generate it. //if (sipRequest.Header.SwitchboardTokenRequest > 0 && m_switchbboardRSAProvider != null) //{ // SwitchboardToken token = new SwitchboardToken(sipRequest.Header.SwitchboardTokenRequest, sipAccount.Owner, uacRemoteEndPoint.Address.ToString()); // lock (m_switchbboardRSAProvider) // { // token.SignedHash = Convert.ToBase64String(m_switchbboardRSAProvider.SignHash(Crypto.GetSHAHash(token.GetHashString()), null)); // } // string tokenXML = token.ToXML(true); // logger.Debug("Switchboard token set for " + sipAccount.Owner + " with expiry of " + token.Expiry + "s."); // okResponse.Header.SwitchboardToken = Crypto.SymmetricEncrypt(sipAccount.SIPPassword, sipRequest.Header.AuthenticationHeader.SIPDigest.Nonce, tokenXML); //} registerTransaction.SendFinalResponse(okResponse); } else { // The binding update failed even though the REGISTER request was authorised. This is probably due to a // temporary problem connecting to the bindings data store. Send Ok but set the binding expiry to the minimum so // that the UA will try again as soon as possible. FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, "Registration request successful but binding update failed for " + toUser + "@" + canonicalDomain + " from " + registerTransaction.RemoteEndPoint + ".", toUser)); sipRequest.Header.Contact[0].Expires = m_minimumBindingExpiry; SIPResponse okResponse = GetOkResponse(sipRequest); registerTransaction.SendFinalResponse(okResponse); } } return(RegisterResultEnum.Authenticated); } } catch (Exception excp) { string regErrorMessage = "Exception registrarcore registering. " + excp.Message + "\r\n" + registerTransaction.TransactionRequest.ToString(); logger.Error(regErrorMessage); FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.Error, regErrorMessage, null)); try { SIPResponse errorResponse = GetErrorResponse(registerTransaction.TransactionRequest, SIPResponseStatusCodesEnum.InternalServerError, null); registerTransaction.SendFinalResponse(errorResponse); } catch { } return(RegisterResultEnum.Error); } }
public SIPValidationException(SIPValidationFieldsEnum sipErrorField, string message) : base(message) { SIPErrorField = sipErrorField; SIPResponseErrorCode = SIPResponseStatusCodesEnum.BadRequest; }
/// <summary> /// Attempts to renew an existing subscription. /// </summary> /// <returns>The session ID if the renewal was successful or null if it wasn't.</returns> public string RenewSubscription(SIPRequest subscribeRequest, out SIPResponseStatusCodesEnum errorResponse, out string errorReason) { errorResponse = SIPResponseStatusCodesEnum.None; errorReason = null; try { int expiry = subscribeRequest.Header.Expires; string toTag = subscribeRequest.Header.To.ToTag; string fromTag = subscribeRequest.Header.From.FromTag; string callID = subscribeRequest.Header.CallId; int cseq = subscribeRequest.Header.CSeq; // Check for an existing subscription. SIPEventSubscription existingSubscription = (from sub in m_subscriptions.Values where sub.SubscriptionDialogue.CallId == callID select sub).FirstOrDefault(); if (existingSubscription != null) { if (expiry == 0) { // Subsciption is being cancelled. StopSubscription(existingSubscription); return(null); } else if (cseq > existingSubscription.SubscriptionDialogue.RemoteCSeq) { logger.Debug("Renewing subscription for " + existingSubscription.SessionID + " and " + existingSubscription.SubscriptionDialogue.Owner + "."); existingSubscription.SubscriptionDialogue.RemoteCSeq = cseq; //existingSubscription.ProxySendFrom = (!subscribeRequest.Header.ProxyReceivedOn.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(subscribeRequest.Header.ProxyReceivedOn) : null; string extensionResult = m_publisher.ExtendSession(m_notificationsAddress, existingSubscription.SessionID, expiry); if (extensionResult != null) { // One or more of the monitor servers could not extend the session. Close all the existing sessions and re-create. MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeFailed, "Monitor session extension for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + " failed. " + extensionResult, existingSubscription.SubscriptionDialogue.Owner)); m_publisher.CloseSession(m_notificationsAddress, existingSubscription.SessionID); // Need to re-establish the sessions with the notification servers. string subscribeError = null; string sessionID = Guid.NewGuid().ToString(); m_publisher.Subscribe(existingSubscription.SubscriptionDialogue.Owner, existingSubscription.SubscriptionDialogue.AdminMemberId, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), existingSubscription.MonitorFilter, expiry, null, out subscribeError); if (subscribeError != null) { throw new ApplicationException(subscribeError); } else { lock (m_subscriptions) { m_subscriptions.Remove(existingSubscription.SessionID); existingSubscription.SessionID = sessionID; m_subscriptions.Add(sessionID, existingSubscription); } MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "Monitor session recreated for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + ".", existingSubscription.SubscriptionDialogue.Owner)); } } MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeRenew, "Monitor session successfully renewed for " + existingSubscription.SubscriptionEventPackage.ToString() + " " + existingSubscription.ResourceURI.ToString() + ".", existingSubscription.SubscriptionDialogue.Owner)); return(existingSubscription.SessionID); } else { throw new ApplicationException("A duplicate SUBSCRIBE request was received by NotifierSubscriptionsManager."); } } else { //throw new ApplicationException("No existing subscription could be found for a subscribe renewal request."); errorResponse = SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist; errorReason = "Subscription dialog not found"; return(null); } } catch (Exception excp) { logger.Error("Exception RenewSubscription. " + excp.Message); throw; } }
/// <summary> /// Updates the bindings list for a registrar's address-of-records. /// </summary> /// <param name="proxyEndPoint">If the request arrived at this registrar via a proxy then this will contain the end point of the proxy.</param> /// <param name="uacRecvdEndPoint">The public end point the UAC REGISTER request was deemded to have originated from.</param> /// <param name="registrarEndPoint">The registrar end point the registration request was received on.</param> /// <param name="maxAllowedExpiry">The maximum allowed expiry that can be granted to this binding request.</param> /// <returns>If the binding update was successful the expiry time for it is returned otherwise 0.</returns> public List <SIPRegistrarBinding> UpdateBindings( SIPAccount sipAccount, SIPEndPoint proxySIPEndPoint, SIPEndPoint remoteSIPEndPoint, SIPEndPoint registrarSIPEndPoint, List <SIPContactHeader> contactHeaders, string callId, int cseq, int expiresHeaderValue, string userAgent, out SIPResponseStatusCodesEnum responseStatus, out string responseMessage) { //logger.Debug("UpdateBinding " + bindingURI.ToString() + "."); int maxAllowedExpiry = DEFAULT_MAX_EXPIRY_SECONDS; responseMessage = null; string sipAccountAOR = sipAccount.AOR; responseStatus = SIPResponseStatusCodesEnum.Ok; try { userAgent = (userAgent != null && userAgent.Length > MAX_USERAGENT_LENGTH) ? userAgent.Substring(0, MAX_USERAGENT_LENGTH) : userAgent; List <SIPRegistrarBinding> bindings = m_registrarBindingDataLayer.GetForSIPAccount(sipAccount.ID); foreach (SIPContactHeader contactHeader in contactHeaders) { SIPURI bindingURI = contactHeader.ContactURI.CopyOf(); int contactHeaderExpiresValue = contactHeader.Expires; int bindingExpiry = 0; if (bindingURI.Host == m_sipRegisterRemoveAll) { if (contactHeaders.Count > 1) { // If a register request specifies remove all it cannot contain any other binding requests. Logger.LogDebug("Remove all bindings requested for " + sipAccountAOR + " but mutliple bindings specified, rejecting as a bad request."); responseStatus = SIPResponseStatusCodesEnum.BadRequest; break; } #region Process remove all bindings. if (expiresHeaderValue == 0) { // Removing all bindings for user. Logger.LogDebug("Remove all bindings requested for " + sipAccountAOR + "."); // Mark all the current bindings as expired. if (bindings != null && bindings.Count > 0) { for (int index = 0; index < bindings.Count; index++) { //bindings[index].RemovalReason = SIPBindingRemovalReason.ClientExpiredAll; bindings[index].Expiry = 0; //m_bindingsPersistor.Update(bindings[index]); } } //FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingRemoval, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); responseStatus = SIPResponseStatusCodesEnum.Ok; } else { // Remove all header cannot be present with other headers and must have an Expiry equal to 0. responseStatus = SIPResponseStatusCodesEnum.BadRequest; } #endregion } else { int requestedExpiry = (contactHeaderExpiresValue != -1) ? contactHeaderExpiresValue : expiresHeaderValue; requestedExpiry = (requestedExpiry == -1) ? maxAllowedExpiry : requestedExpiry; // This will happen if the Expires header and the Expiry on the Contact are both missing. bindingExpiry = (requestedExpiry > maxAllowedExpiry) ? maxAllowedExpiry : requestedExpiry; bindingExpiry = (bindingExpiry < MINIMUM_EXPIRY_SECONDS) ? MINIMUM_EXPIRY_SECONDS : bindingExpiry; bindingURI.Parameters.Remove(m_sipExpiresParameterKey); //SIPRegistrarBinding binding = GetBindingForContactURI(bindings, bindingURI.ToString()); SIPRegistrarBinding binding = bindings.Where(x => x.ContactURI == bindingURI.ToString()).FirstOrDefault(); if (binding != null) { if (requestedExpiry <= 0) { Logger.LogDebug($"Binding expired by client for {sipAccountAOR} from {remoteSIPEndPoint}."); bindings.Remove(binding); m_registrarBindingDataLayer.Delete(binding.ID); bindingExpiry = 0; } else { Logger.LogDebug($"Binding update request for {sipAccountAOR} from {remoteSIPEndPoint}, expiry requested {requestedExpiry}s granted {bindingExpiry}s."); //binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, sipAccount.DontMangleEnabled); //binding.RefreshBinding(bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, false); //DateTime startTime = DateTime.Now; //m_bindingsPersistor.Update(binding); //m_registrarBindingDataLayer.Update(binding); m_registrarBindingDataLayer.RefreshBinding(binding.ID, bindingExpiry, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, false); //TimeSpan duration = DateTime.Now.Subtract(startTime); //FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Registrar, SIPMonitorEventTypesEnum.RegistrarTiming, "Binding database update time for " + sipAccountAOR + " took " + duration.TotalMilliseconds + "ms.", null)); //FireSIPMonitorLogEvent(new SIPMonitorMachineEvent(SIPMonitorMachineEventTypesEnum.SIPRegistrarBindingUpdate, sipAccount.Owner, sipAccount.Id.ToString(), SIPURI.ParseSIPURIRelaxed(sipAccountAOR))); } } else { if (requestedExpiry > 0) { Logger.LogDebug($"New binding request for {sipAccountAOR} from {remoteSIPEndPoint}, expiry requested {requestedExpiry}s granted {bindingExpiry}s."); if (bindings.Count >= m_maxBindingsPerAccount) { // Need to remove the oldest binding to stay within limit. SIPRegistrarBinding oldestBinding = bindings.OrderBy(x => x.LastUpdate).Last(); Logger.LogDebug($"Binding limit exceeded for {sipAccountAOR} from {remoteSIPEndPoint} removing oldest binding to stay within limit of {m_maxBindingsPerAccount}."); m_registrarBindingDataLayer.Delete(oldestBinding.ID); } SIPRegistrarBinding newBinding = new SIPRegistrarBinding(sipAccount, bindingURI, callId, cseq, userAgent, remoteSIPEndPoint, proxySIPEndPoint, registrarSIPEndPoint, bindingExpiry); m_registrarBindingDataLayer.Add(newBinding); } else { Logger.LogDebug($"New binding received for {sipAccountAOR} with expired contact, {bindingURI} no update."); bindingExpiry = 0; } } responseStatus = SIPResponseStatusCodesEnum.Ok; } } return(m_registrarBindingDataLayer.GetForSIPAccount(sipAccount.ID)); } catch (Exception excp) { Logger.LogError("Exception UpdateBinding. " + excp); responseStatus = SIPResponseStatusCodesEnum.InternalServerError; return(null); } }
public string SubscribeClient( string owner, string adminID, SIPRequest subscribeRequest, string toTag, SIPURI canonicalResourceURI, out SIPResponseStatusCodesEnum errorResponse, out string errorReason) { try { errorResponse = SIPResponseStatusCodesEnum.None; errorReason = null; SIPURI resourceURI = subscribeRequest.URI.CopyOf(); SIPEventPackage eventPackage = SIPEventPackage.Parse(subscribeRequest.Header.Event); int expiry = subscribeRequest.Header.Expires; if (!(eventPackage == SIPEventPackage.Dialog || eventPackage == SIPEventPackage.Presence)) { throw new ApplicationException("Event package " + eventPackage.ToString() + " is not supported by the subscriptions manager."); } else { if (expiry > 0) { string subscribeError = null; string sessionID = Guid.NewGuid().ToString(); SIPDialogue subscribeDialogue = new SIPDialogue(subscribeRequest, owner, adminID, toTag); if (eventPackage == SIPEventPackage.Dialog) { string monitorFilter = "dialog " + canonicalResourceURI.ToString(); if (!subscribeRequest.Body.IsNullOrBlank()) { monitorFilter += " and " + subscribeRequest.Body; } m_publisher.Subscribe(owner, adminID, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), monitorFilter, expiry, null, out subscribeError); if (subscribeError != null) { throw new ApplicationException(subscribeError); } else { SIPDialogEventSubscription subscription = new SIPDialogEventSubscription(MonitorLogEvent_External, sessionID, resourceURI, canonicalResourceURI, monitorFilter, subscribeDialogue, expiry, GetDialogues_External, GetDialogue_External); m_subscriptions.Add(sessionID, subscription); MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "New dialog subscription created for " + resourceURI.ToString() + ", expiry " + expiry + "s.", owner)); } } else if (eventPackage == SIPEventPackage.Presence) { string monitorFilter = "presence " + canonicalResourceURI.ToString(); m_publisher.Subscribe(owner, adminID, m_notificationsAddress, sessionID, SIPMonitorClientTypesEnum.Machine.ToString(), monitorFilter, expiry, null, out subscribeError); if (subscribeError != null) { throw new ApplicationException(subscribeError); } else { bool switchboardAccountsOnly = subscribeRequest.Body == SIPPresenceEventSubscription.SWITCHBOARD_FILTER; SIPPresenceEventSubscription subscription = new SIPPresenceEventSubscription(MonitorLogEvent_External, sessionID, resourceURI, canonicalResourceURI, monitorFilter, subscribeDialogue, expiry, m_sipAssetPersistor.Get, m_sipAssetPersistor.GetProperty, GetSIPRegistrarBindingsCount_External, switchboardAccountsOnly); m_subscriptions.Add(sessionID, subscription); MonitorLogEvent_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Notifier, SIPMonitorEventTypesEnum.SubscribeAccept, "New presence subscription created for " + resourceURI.ToString() + ", expiry " + expiry + "s.", owner)); } } return(sessionID); } return(null); } } catch (Exception excp) { logger.Error("Exception NotifierSubscriptionsManager SubscribeClient. " + excp.Message); throw; } }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { NoRingTimeout.Invoke(this); throw new NotImplementedException("SIPTransferServerUserAgent Redirect"); }
/// <summary> /// Used to create a SIP response for a request when it was not possible to parse the incoming SIP request. /// The response generated by this method may or may not make it back to the requester. Because the SIP /// request could not be parsed there are no Via headers available and without those the return network /// path is missing. Instead a new Via header is generated that may get through if the requester is only /// one SIP hop away. /// </summary> /// <param name="localSIPEndPoint">The local SIP end point the request was received on.</param> /// <param name="remoteSIPEndPoint">The remote SIP end point the request was received on.</param> /// <param name="responseCode">The response code to set on the response.</param> /// <param name="reasonPhrase">Optional reason phrase to set on the response (keep short).</param> public static SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteSIPEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase) { try { SIPResponse response = new SIPResponse(responseCode, reasonPhrase); response.SetSendFromHints(localSIPEndPoint); SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip; SIPFromHeader from = new SIPFromHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null); SIPToHeader to = new SIPToHeader(null, new SIPURI(sipScheme, localSIPEndPoint), null); int cSeq = 1; string callId = CallProperties.CreateNewCallId(); response.Header = new SIPHeader(from, to, cSeq, callId); response.Header.CSeqMethod = SIPMethodsEnum.NONE; response.Header.Vias.PushViaHeader(new SIPViaHeader(new SIPEndPoint(localSIPEndPoint.Protocol, remoteSIPEndPoint.GetIPEndPoint()), CallProperties.CreateBranchId())); response.Header.MaxForwards = Int32.MinValue; response.Header.Allow = m_allowedSIPMethods; return(response); } catch (Exception excp) { logger.LogError("Exception SIPResponse.GetResponse. " + excp.Message); throw; } }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { UASStateChanged.Invoke(this, SIPResponseStatusCodesEnum.ExtensionRequired, "ExtensionRequired"); throw new NotImplementedException(); }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { throw new NotImplementedException("SIPTransferServerUserAgent Redirect"); }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody) { try { if (!IsUASAnswered) { if ((int)progressStatus >= 200) { } else { if (UASStateChanged != null) { UASStateChanged(this, progressStatus, reasonPhrase); } // Allow all Trying responses through as some may contain additional useful information on the call state for the caller. // Also if the response is a 183 Session Progress with audio forward it. if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding && progressStatus != SIPResponseStatusCodesEnum.Trying && !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null)) { } else { SIPResponse progressResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, progressStatus, reasonPhrase); if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying) { progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag; } if (!progressBody.IsNullOrBlank()) { progressResponse.Body = progressBody; progressResponse.Header.ContentType = progressContentType; progressResponse.Header.ContentLength = progressBody.Length; } if (customHeaders != null && customHeaders.Length > 0) { foreach (string header in customHeaders) { progressResponse.Header.UnknownHeaders.Add(header); } } m_uasTransaction.SendInformationalResponse(progressResponse); } } } else { Logger.Logger.Warn("SIPServerUserAgent Progress fired on already answered call."); } } catch (Exception excp) { Logger.Logger.Error("Exception SIPServerUserAgent Progress. ->" + excp.Message); } }
public void Reject(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase) { Reject(failureStatus, reasonPhrase, null); }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string progressReason, SIPEndPoint localEndPoint, SIPEndPoint remoteEndPoint) { InProgress = true; ProgressTime = DateTimeOffset.UtcNow; ProgressStatus = (int)progressStatus; ProgressReasonPhrase = progressReason; if (localEndPoint != null) { LocalSIPEndPoint = localEndPoint; } if (remoteEndPoint != null) { RemoteEndPoint = remoteEndPoint; } }
public void Progress(SIPResponseStatusCodesEnum progressStatus, string reasonPhrase, string[] customHeaders, string progressContentType, string progressBody) { try { if (!IsUASAnswered) { if ((int)progressStatus >= 200) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call was passed an invalid response status of " + (int)progressStatus + ", ignoring.", m_owner)); } else { UASStateChanged?.Invoke(this, progressStatus, reasonPhrase); // Allow all Trying responses through as some may contain additional useful information on the call state for the caller. // Also if the response is a 183 Session Progress with audio forward it. if (m_uasTransaction.TransactionState == SIPTransactionStatesEnum.Proceeding && progressStatus != SIPResponseStatusCodesEnum.Trying && !(progressStatus == SIPResponseStatusCodesEnum.SessionProgress && progressBody != null)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call ignoring progress response with status of " + (int)progressStatus + " as already in " + m_uasTransaction.TransactionState + ".", m_owner)); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "UAS call progressing with " + progressStatus + ".", m_owner)); SIPResponse progressResponse = SIPResponse.GetResponse(m_uasTransaction.TransactionRequest, progressStatus, reasonPhrase); if (progressResponse.Status != SIPResponseStatusCodesEnum.Trying) { progressResponse.Header.To.ToTag = m_uasTransaction.LocalTag; } if (!progressBody.IsNullOrBlank()) { progressResponse.Body = progressBody; progressResponse.Header.ContentType = progressContentType; progressResponse.Header.ContentLength = progressBody.Length; } if (customHeaders != null && customHeaders.Length > 0) { foreach (string header in customHeaders) { progressResponse.Header.UnknownHeaders.Add(header); } } m_uasTransaction.SendProvisionalResponse(progressResponse); } } } else { logger.LogWarning("SIPServerUserAgent Progress fired on already answered call."); } } catch (Exception excp) { logger.LogError("Exception SIPServerUserAgent Progress. " + excp.Message); } }
public static SIPResponse GetResponse(SIPRequest sipRequest, SIPResponseStatusCodesEnum responseCode, string reasonPhrase) { try { SIPResponse response = new SIPResponse(responseCode, reasonPhrase, sipRequest.LocalSIPEndPoint); if (reasonPhrase != null) { response.ReasonPhrase = reasonPhrase; } SIPHeader requestHeader = sipRequest.Header; SIPFromHeader from = (requestHeader == null || requestHeader.From != null) ? requestHeader.From : new SIPFromHeader(null, new SIPURI(sipRequest.URI.Scheme, sipRequest.LocalSIPEndPoint), null); SIPToHeader to = (requestHeader == null || requestHeader.To != null) ? requestHeader.To : new SIPToHeader(null, new SIPURI(sipRequest.URI.Scheme, sipRequest.LocalSIPEndPoint), null); int cSeq = (requestHeader == null || requestHeader.CSeq != -1) ? requestHeader.CSeq : 1; string callId = (requestHeader == null || requestHeader.CallId != null) ? requestHeader.CallId : CallProperties.CreateNewCallId(); response.Header = new SIPHeader(from, to, cSeq, callId); response.Header.CSeqMethod = (requestHeader != null) ? requestHeader.CSeqMethod : SIPMethodsEnum.NONE; if (requestHeader == null || requestHeader.Vias == null || requestHeader.Vias.Length == 0) { response.Header.Vias.PushViaHeader(new SIPViaHeader(sipRequest.RemoteSIPEndPoint, CallProperties.CreateBranchId())); } else { response.Header.Vias = requestHeader.Vias; } response.Header.MaxForwards = Int32.MinValue; response.Header.Allow = ALLOWED_SIP_METHODS; return response; } catch (Exception excp) { logger.Error("Exception SIPTransport GetResponse. " + excp.Message); throw excp; } }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { try { if (m_uasTransaction.TransactionFinalResponse == null) { SIPResponse redirectResponse = SIPTransport.GetResponse(m_uasTransaction.TransactionRequest, redirectCode, null); redirectResponse.Header.Contact = SIPContactHeader.CreateSIPContactList(redirectURI); m_uasTransaction.SendFinalResponse(redirectResponse); } } catch (Exception excp) { logger.Error("Exception SIPServerUserAgent Redirect. " + excp.Message); } }
private SIPResponse GetResponse(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponseStatusCodesEnum responseCode, string reasonPhrase, SIPRequest request) { try { SIPResponse response = new SIPResponse(responseCode, reasonPhrase, localSIPEndPoint); SIPSchemesEnum sipScheme = (localSIPEndPoint.Protocol == SIPProtocolsEnum.tls) ? SIPSchemesEnum.sips : SIPSchemesEnum.sip; SIPFromHeader from = request.Header.From; from.FromTag = request.Header.From.FromTag; SIPToHeader to = request.Header.To; response.Header = new SIPHeader(from, to, request.Header.CSeq, request.Header.CallId) { CSeqMethod = request.Header.CSeqMethod, Vias = request.Header.Vias, UserAgent = SIPConstants.SIP_USERAGENT_STRING, CSeq = request.Header.CSeq }; if (response.Header.To.ToTag == null || request.Header.To.ToTag.Trim().Length == 0) { response.Header.To.ToTag = CallProperties.CreateNewTag(); } return(response); } catch (Exception excp) { logger.Error("Exception SIPTransport GetResponse. " + excp.Message); throw; } }
/// <summary> /// Starts a call based on multiple forking call legs. As each call leg fails the next leg is popped off the queue and attempted. /// </summary> /// <param name="callsQueue"></param> public void Start(Queue<List<SIPCallDescriptor>> callsQueue) { if (callsQueue == null || callsQueue.Count == 0) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No callable destinations were provided in Dial command, returning.", m_username)); m_lastFailureStatus = SIPResponseStatusCodesEnum.InternalServerError; m_lastFailureReason = "Call list was empty"; CallLegCompleted(); } else { m_priorityCallsQueue = callsQueue; List<SIPCallDescriptor> calls = m_priorityCallsQueue.Dequeue(); Start(calls); } }
public void Redirect(SIPResponseStatusCodesEnum redirectCode, SIPURI redirectURI) { logger.LogDebug("SIPB2BUserAgent Redirect."); //m_uas.Redirect(redirectCode, redirectURI); }
/*private void UACCallTrying(ISIPClientUserAgent uac, SIPResponse sipResponse) { try { // Test for the custom multiple redirect response. if (sipResponse.Status == SIPResponseStatusCodesEnum.MultipleRedirect) { ProcessRedirect(uac, sipResponse); } } catch (Exception excp) { logger.Error("Exception ForkCall UACCallTrying. " + excp.Message); } }*/ /// <summary> /// This event occurs if it was not possible to initiate a call to the destination specified in the forwarded call. An example /// would be an unresolvable hostname in the destination URI. /// </summary> /// <param name="sipSwitchCall"></param> /// <param name="errorMessage"></param> private void UACCallFailed(ISIPClientUserAgent uac, string errorMessage) { lock (m_switchCalls) { m_switchCalls.Remove(uac); } m_lastFailureStatus = SIPResponseStatusCodesEnum.TemporarilyUnavailable; m_lastFailureReason = errorMessage; if (m_switchCallTransactions != null && uac.ServerTransaction != null) { m_switchCallTransactions.Add(uac.ServerTransaction); } uac.CallAnswered -= UACCallAnswered; uac.CallFailed -= UACCallFailed; uac.CallRinging -= UACCallProgress; CallLegCompleted(); }
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 + "."); 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; if (CallAnswered != null) { CallAnswered(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); } }