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