public static void DNSNAPTRRecordLookup(string host, bool async, ref SIPDNSLookupResult lookupResult) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS NAPTR record lookup initiated for " + host + ".", null)); // Target is a hostname with no explicit port, DNS lookup for NAPTR records. DNSResponse naptrRecordResponse = DNSManager.Lookup(host, DNSQType.NAPTR, DNS_LOOKUP_TIMEOUT, null, true, async); if (naptrRecordResponse == null && async) { lookupResult.Pending = true; } else if (naptrRecordResponse.Timedout) { lookupResult.NAPTRTimedoutAt = DateTime.Now; } else if (naptrRecordResponse.Error == null && naptrRecordResponse.RecordNAPTR != null && naptrRecordResponse.RecordNAPTR.Length > 0) { foreach (RecordNAPTR naptrRecord in naptrRecordResponse.RecordNAPTR) { SIPDNSServiceResult sipNAPTRResult = new SIPDNSServiceResult(SIPServices.GetService(naptrRecord.Service), naptrRecord.Order, 0, naptrRecord.RR.TTL, naptrRecord.Replacement, 0, DateTime.Now); lookupResult.AddNAPTRResult(sipNAPTRResult); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS NAPTR record found for " + host + ", result " + naptrRecord.Service + " " + naptrRecord.Replacement + ".", null)); } } else { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no NAPTR records found for " + host + ".", null)); } }
private void SendInitialRegister() { try { if (m_attempts >= MAX_REGISTER_ATTEMPTS) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", m_owner)); m_isRegistered = false; if (RegistrationTemporaryFailure != null) { RegistrationTemporaryFailure(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts."); } m_waitForRegistrationMRE.Set(); } else { m_attempts++; SIPEndPoint registrarSIPEndPoint = m_outboundProxy; if (registrarSIPEndPoint == null) { SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false); if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Could not resolve " + m_registrarHost + ", " + lookupResult.LookupError, m_owner)); } else { registrarSIPEndPoint = lookupResult.GetSIPEndPoint(); } } if (registrarSIPEndPoint == null && RegistrationFailed != null) { RegistrationFailed(m_sipAccountAOR, "Could not resolve " + m_registrarHost + "."); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Initiating registration to " + m_registrarHost + " at " + registrarSIPEndPoint.ToString() + " for " + m_sipAccountAOR.ToString() + ".", m_owner)); SIPRequest regRequest = GetRegistrationRequest(m_localEndPoint); SIPNonInviteTransaction regTransaction = m_sipTransport.CreateNonInviteTransaction(regRequest, registrarSIPEndPoint, m_localEndPoint, m_outboundProxy); // These handlers need to be on their own threads to take the processing off the SIP transport layer. regTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { ServerResponseReceived(lep, rep, tn, rsp); }); }; regTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); }; m_sipTransport.SendSIPReliable(regTransaction); } } } catch (Exception excp) { logger.Error("Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message); if (RegistrationFailed != null) { RegistrationFailed(m_sipAccountAOR, "Exception SendInitialRegister to " + m_registrarHost + ". " + excp.Message); } } }
public static SIPDNSLookupResult DNSAAAARecordLookup(string host, int port, bool async, SIPURI uri, SIPDNSLookupResult lookupResult = null) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record lookup requested for " + host + ".", null)); SIPDNSLookupResult result = lookupResult ?? new SIPDNSLookupResult(uri); result.LookupError = null; DNSResponse aaaaRecordResponse = DNSManager.Lookup(host, QType.AAAA, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async); if (aaaaRecordResponse == null) { if (async) { result.Pending = true; } } else if (aaaaRecordResponse.Timedout) { result.ATimedoutAt = DateTime.Now; } else if (!string.IsNullOrWhiteSpace(aaaaRecordResponse.Error)) { result.LookupError = aaaaRecordResponse.Error; } else if (aaaaRecordResponse.RecordsAAAA == null || aaaaRecordResponse.RecordsAAAA.Length == 0) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no AAAA records found for " + host + ".", null)); result.LookupError = "No AAAA records found for " + host + "."; } else { SIPURI sipURI = result.URI; foreach (RecordAAAA aRecord in aaaaRecordResponse.RecordsAAAA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } } return(result); }
public static SIPDNSLookupResult DNSNameRecordLookup(string host, int port, bool async, SIPURI lookupURI, ref SIPDNSLookupResult lookupResult, bool?preferIPv6 = null) { SIPDNSLookupResult result = null; if (lookupResult.SIPSRVResults != null) { foreach (SIPDNSServiceResult nextSRVRecord in lookupResult.SIPSRVResults) { if (nextSRVRecord != null && nextSRVRecord.Data != null) { result = DNSNameRecordLookup(nextSRVRecord.Data, nextSRVRecord.Port, async, lookupResult.URI, lookupResult, preferIPv6); if (result.LookupError == null) { return(result); } } } } result = DNSNameRecordLookup(host, port, async, lookupResult.URI, lookupResult, preferIPv6); return(result); }
public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async) { try { if (sipURI == null) { throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI."); } string host = sipURI.Host; int port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort; bool explicitPort = false; if (sipURI.Host.IndexOf(':') != -1) { host = sipURI.Host.Split(':')[0]; Int32.TryParse(sipURI.Host.Split(':')[1], out port); explicitPort = true; } if (Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success) { // Target is an IP address, no DNS lookup required. IPAddress hostIP = IPAddress.Parse(host); SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return result; } else if (explicitPort) { // Target is a hostname with an explicit port, DNS lookup for A or AAAA record. return DNSARecordLookup(host, port, async, sipURI); } else { // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure. SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI); // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution. /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null)); DNSNAPTRRecordLookup(host, async, ref sipLookupResult); if (sipLookupResult.Pending) { if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString())) { m_inProgressSIPServiceLookups.Add(sipURI.ToString()); ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); }); } return sipLookupResult; }*/ DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult); if (sipLookupResult.Pending) { //logger.Debug("SIPDNSManager SRV lookup for " + host + " is pending."); return sipLookupResult; } else { //logger.Debug("SIPDNSManager SRV lookup for " + host + " is final."); SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI); } } } catch (Exception excp) { logger.Error("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message); m_inProgressSIPServiceLookups.Remove(sipURI.ToString()); return new SIPDNSLookupResult(sipURI, excp.Message); } }
public static void DNSSRVRecordLookup(SIPSchemesEnum scheme, SIPProtocolsEnum protocol, string host, bool async, ref SIPDNSLookupResult lookupResult) { SIPServicesEnum reqdNAPTRService = SIPServicesEnum.none; if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.udp) { reqdNAPTRService = SIPServicesEnum.sipudp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.siptcp; } else if (scheme == SIPSchemesEnum.sips && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.sipstcp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tls) { reqdNAPTRService = SIPServicesEnum.siptls; } // If there are NAPTR records available see if there is a matching one for the SIP scheme and protocol required. SIPDNSServiceResult naptrService = null; if (lookupResult.SIPNAPTRResults != null && lookupResult.SIPNAPTRResults.Count > 0) { if (reqdNAPTRService != SIPServicesEnum.none && lookupResult.SIPNAPTRResults.ContainsKey(reqdNAPTRService)) { naptrService = lookupResult.SIPNAPTRResults[reqdNAPTRService]; } } // Construct the SRV target to lookup depending on whether an NAPTR record was available or not. string srvLookup = null; if (naptrService != null) { srvLookup = naptrService.Data; } else { srvLookup = "_" + scheme.ToString() + "._" + protocol.ToString() + "." + host; } SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup requested for " + srvLookup + ".", null)); DNSResponse srvRecordResponse = DNSManager.Lookup(srvLookup, DNSQType.SRV, DNS_LOOKUP_TIMEOUT, null, true, async); if (srvRecordResponse == null && async) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup pending for " + srvLookup + ".", null)); lookupResult.Pending = true; } else if (srvRecordResponse.Timedout) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup timed out for " + srvLookup + ".", null)); lookupResult.SRVTimedoutAt = DateTime.Now; } else if (srvRecordResponse.Error != null) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup for " + srvLookup + " returned error of " + lookupResult.LookupError + ".", null)); } else if (srvRecordResponse.Error == null && srvRecordResponse.RecordSRV != null && srvRecordResponse.RecordSRV.Length > 0) { foreach (RecordSRV srvRecord in srvRecordResponse.RecordSRV) { SIPDNSServiceResult sipSRVResult = new SIPDNSServiceResult(reqdNAPTRService, srvRecord.Priority, srvRecord.Weight, srvRecord.RR.TTL, srvRecord.Target, srvRecord.Port, DateTime.Now); lookupResult.AddSRVResult(sipSRVResult); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record found for " + srvLookup + ", result " + srvRecord.Target + " " + srvRecord.Port + ".", null)); } } else { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no SRV records found for " + srvLookup + ".", null)); } }
public static SIPDNSLookupResult DNSARecordLookup(string host, int port, bool async, SIPURI uri) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record lookup requested for " + host + ".", null)); SIPDNSLookupResult result = new SIPDNSLookupResult(uri); DNSResponse aRecordResponse = DNSManager.Lookup(host, DNSQType.A, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async); if (aRecordResponse == null && async) { result.Pending = true; } else if (aRecordResponse.Timedout) { result.ATimedoutAt = DateTime.Now; } else if (aRecordResponse.Error != null) { result.LookupError = aRecordResponse.Error; } else if (aRecordResponse.RecordsA == null || aRecordResponse.RecordsA.Length == 0) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no A records found for " + host + ".", null)); result.LookupError = "No A records found for " + host + "."; } else { SIPURI sipURI = result.URI; foreach (RecordA aRecord in aRecordResponse.RecordsA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } } return result; }
/// <summary> /// The event handler for responses to the initial register request. /// </summary> private void ServerResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse) { try { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Server response " + sipResponse.Status + " received for " + m_sipAccountAOR.ToString() + ".", null)); if (sipResponse.Status == SIPResponseStatusCodesEnum.ProxyAuthenticationRequired || sipResponse.Status == SIPResponseStatusCodesEnum.Unauthorised) { if (sipResponse.Header.AuthenticationHeader != null) { if (m_attempts >= MAX_REGISTER_ATTEMPTS) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration to " + m_sipAccountAOR.ToString() + " reached the maximum number of allowed attempts without a failure condition.", null)); m_isRegistered = false; RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration reached the maximum number of allowed attempts."); m_waitForRegistrationMRE.Set(); } else { m_attempts++; SIPRequest authenticatedRequest = GetAuthenticatedRegistrationRequest(sipTransaction.TransactionRequest, sipResponse); SIPEndPoint registrarSIPEndPoint = m_outboundProxy; if (registrarSIPEndPoint == null) { SIPDNSLookupResult lookupResult = m_sipTransport.GetHostEndPoint(m_registrarHost, false); if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Could not resolve " + m_registrarHost + ", " + lookupResult.LookupError, null)); } else { registrarSIPEndPoint = lookupResult.GetSIPEndPoint(); } } if (registrarSIPEndPoint == null) { logger.LogWarning("SIPRegistrationAgent could not resolve " + m_registrarHost + "."); RegistrationFailed?.Invoke(m_sipAccountAOR, "Could not resolve " + m_registrarHost + "."); } else { SIPNonInviteTransaction regAuthTransaction = new SIPNonInviteTransaction(m_sipTransport, authenticatedRequest, registrarSIPEndPoint); regAuthTransaction.NonInviteTransactionFinalResponseReceived += (lep, rep, tn, rsp) => { ThreadPool.QueueUserWorkItem(delegate { AuthResponseReceived(lep, rep, tn, rsp); }); return(Task.FromResult(SocketError.Success)); }; regAuthTransaction.NonInviteTransactionTimedOut += (tn) => { ThreadPool.QueueUserWorkItem(delegate { RegistrationTimedOut(tn); }); }; m_sipTransport.SendTransaction(regAuthTransaction); } } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied for " + m_sipAccountAOR.ToString() + ".", null)); m_isRegistered = false; RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + " but no authentication header was supplied."); m_waitForRegistrationMRE.Set(); } } else { if (sipResponse.Status == SIPResponseStatusCodesEnum.Ok) { if (m_expiry > 0) { m_isRegistered = true; m_expiry = GetUpdatedExpiry(sipResponse); RegistrationSuccessful?.Invoke(m_sipAccountAOR); } else { m_isRegistered = false; RegistrationRemoved?.Invoke(m_sipAccountAOR); } m_waitForRegistrationMRE.Set(); } else if (sipResponse.Status == SIPResponseStatusCodesEnum.Forbidden || sipResponse.Status == SIPResponseStatusCodesEnum.NotFound) { // SIP account does not appear to exist. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ", no further registration attempts will be made.", null)); string reasonPhrase = (sipResponse.ReasonPhrase.IsNullOrBlank()) ? sipResponse.Status.ToString() : sipResponse.ReasonPhrase; RegistrationFailed?.Invoke(m_sipAccountAOR, "Registration failed with " + (int)sipResponse.Status + " " + reasonPhrase + "."); m_exit = true; m_waitForRegistrationMRE.Set(); } else if (sipResponse.Status == SIPResponseStatusCodesEnum.IntervalTooBrief && m_expiry != 0) { m_expiry = GetUpdatedExpiryForIntervalTooBrief(sipResponse); Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterInProgress, "Registration for " + m_sipAccountAOR.ToString() + " had a too short expiry, updated to +" + m_expiry + " and trying again.", null)); SendInitialRegister(); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.ContactRegisterFailed, "Registration failed with " + sipResponse.Status + " for " + m_sipAccountAOR.ToString() + ".", null)); m_isRegistered = false; RegistrationTemporaryFailure?.Invoke(m_sipAccountAOR, "Registration failed with " + sipResponse.Status + "."); m_waitForRegistrationMRE.Set(); } } } catch (Exception excp) { logger.LogError("Exception SIPRegistrationUserAgent ServerResponseReceived (" + remoteEndPoint + "). " + excp.Message); } }
/// <summary> /// Initiates a SUBSCRIBE request to a notification server. /// </summary> /// <param name="subscribeToURI">The SIP user that dialog notifications are being subscribed to.</param> public void Subscribe(SIPURI subscribeURI, int expiry, SIPEventPackage sipEventPackage, string subscribeCallID, SIPURI contactURI) { try { if (m_attempts >= MAX_SUBSCRIBE_ATTEMPTS) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NotifierClient, SIPMonitorEventTypesEnum.SubscribeFailed, "Susbcription to " + subscribeURI.ToString() + " reached the maximum number of allowed attempts without a failure condition.", null)); m_subscribed = false; SubscriptionFailed(subscribeURI, SIPResponseStatusCodesEnum.InternalServerError, "Subscription reached the maximum number of allowed attempts."); m_waitForSubscribeResponse.Set(); } else { m_attempts++; m_localCSeq++; SIPRequest subscribeRequest = m_sipTransport.GetRequest( SIPMethodsEnum.SUBSCRIBE, m_resourceURI, new SIPToHeader(null, subscribeURI, m_subscriptionToTag), null); if (contactURI != null) { subscribeRequest.Header.Contact = new List <SIPContactHeader>() { new SIPContactHeader(null, contactURI) }; } subscribeRequest.Header.From = new SIPFromHeader(null, new SIPURI(m_authUsername, m_authDomain, null, SIPSchemesEnum.sip, SIPProtocolsEnum.udp), m_subscriptionFromTag); subscribeRequest.Header.CSeq = m_localCSeq; subscribeRequest.Header.Expires = expiry; subscribeRequest.Header.Event = sipEventPackage.ToString(); subscribeRequest.Header.CallId = subscribeCallID; if (!m_filter.IsNullOrBlank()) { subscribeRequest.Body = m_filter; subscribeRequest.Header.ContentLength = m_filter.Length; subscribeRequest.Header.ContentType = m_filterTextType; } SIPEndPoint dstEndPoint = m_outboundProxy; if (dstEndPoint == null) { SIPDNSLookupResult lookupResult = m_sipTransport.GetURIEndPoint(m_resourceURI, false); if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NotifierClient, SIPMonitorEventTypesEnum.SubscribeFailed, "Could not resolve " + m_resourceURI.Host + ", " + lookupResult.LookupError, null)); } else { dstEndPoint = lookupResult.GetSIPEndPoint(); } } SIPNonInviteTransaction subscribeTransaction = m_sipTransport.CreateNonInviteTransaction(subscribeRequest, dstEndPoint, null, m_outboundProxy); subscribeTransaction.NonInviteTransactionFinalResponseReceived += SubscribeTransactionFinalResponseReceived; subscribeTransaction.NonInviteTransactionTimedOut += SubsribeTransactionTimedOut; m_sipTransport.SendSIPReliable(subscribeTransaction); LastSubscribeAttempt = DateTime.Now; } } catch (Exception excp) { logger.Error("Exception SIPNotifierClient Subscribe. " + excp.Message); SubscriptionFailed(m_resourceURI, SIPResponseStatusCodesEnum.InternalServerError, "Exception Subscribing. " + excp.Message); m_waitForSubscribeResponse.Set(); } }
public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async) { try { if (sipURI == null) { throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI."); } string host = sipURI.Host; int port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort; bool explicitPort = false; if (sipURI.Host.IndexOf(':') != -1) { host = sipURI.Host.Split(':')[0]; Int32.TryParse(sipURI.Host.Split(':')[1], out port); explicitPort = true; } if (Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success) { // Target is an IP address, no DNS lookup required. IPAddress hostIP = IPAddress.Parse(host); SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return(result); } else if (explicitPort) { // Target is a hostname with an explicit port, DNS lookup for A or AAAA record. return(DNSARecordLookup(host, port, async, sipURI)); } else { // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure. SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI); // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution. /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null)); * DNSNAPTRRecordLookup(host, async, ref sipLookupResult); * if (sipLookupResult.Pending) * { * if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString())) * { * m_inProgressSIPServiceLookups.Add(sipURI.ToString()); * ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); }); * } * return sipLookupResult; * }*/ DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult); if (sipLookupResult.Pending) { //logger.Debug("SIPDNSManager SRV lookup for " + host + " is pending."); return(sipLookupResult); } else { //logger.Debug("SIPDNSManager SRV lookup for " + host + " is final."); // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com). // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records. //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips) //{ // DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult); // SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); // int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; // return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI); //} //else //{ SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; return(DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI)); //} } } } catch (Exception excp) { logger.Error("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message); m_inProgressSIPServiceLookups.Remove(sipURI.ToString()); return(new SIPDNSLookupResult(sipURI, excp.Message)); } }
public static void DNSSRVRecordLookup(SIPSchemesEnum scheme, SIPProtocolsEnum protocol, string host, bool async, ref SIPDNSLookupResult lookupResult) { SIPServicesEnum reqdNAPTRService = SIPServicesEnum.none; if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.udp) { reqdNAPTRService = SIPServicesEnum.sipudp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.siptcp; } else if (scheme == SIPSchemesEnum.sips && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.sipstcp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tls) { reqdNAPTRService = SIPServicesEnum.siptls; } // If there are NAPTR records available see if there is a matching one for the SIP scheme and protocol required. SIPDNSServiceResult naptrService = null; if (lookupResult.SIPNAPTRResults != null && lookupResult.SIPNAPTRResults.Count > 0) { if (reqdNAPTRService != SIPServicesEnum.none && lookupResult.SIPNAPTRResults.ContainsKey(reqdNAPTRService)) { naptrService = lookupResult.SIPNAPTRResults[reqdNAPTRService]; } } // Construct the SRV target to lookup depending on whether an NAPTR record was available or not. string srvLookup = null; if (naptrService != null) { srvLookup = naptrService.Data; } else { if (scheme == SIPSchemesEnum.sips) { srvLookup = SIPDNSConstants.SRV_SIPS_TCP_QUERY_PREFIX + host; } else { srvLookup = "_" + scheme.ToString() + "._" + protocol.ToString() + "." + host; } } SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup requested for " + srvLookup + ".", null)); DNSResponse srvRecordResponse = DNSManager.Lookup(srvLookup, DNSQType.SRV, DNS_LOOKUP_TIMEOUT, null, true, async); if (srvRecordResponse == null && async) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup pending for " + srvLookup + ".", null)); lookupResult.Pending = true; } else if (srvRecordResponse.Timedout) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup timed out for " + srvLookup + ".", null)); lookupResult.SRVTimedoutAt = DateTime.Now; } else if (srvRecordResponse.Error != null) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup for " + srvLookup + " returned error of " + lookupResult.LookupError + ".", null)); } else if (srvRecordResponse.Error == null && srvRecordResponse.RecordSRV != null && srvRecordResponse.RecordSRV.Length > 0) { foreach (RecordSRV srvRecord in srvRecordResponse.RecordSRV) { SIPDNSServiceResult sipSRVResult = new SIPDNSServiceResult(reqdNAPTRService, srvRecord.Priority, srvRecord.Weight, srvRecord.RR.TTL, srvRecord.Target, srvRecord.Port, DateTime.Now); lookupResult.AddSRVResult(sipSRVResult); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record found for " + srvLookup + ", result " + srvRecord.Target + " " + srvRecord.Port + ".", null)); } } else { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no SRV records found for " + srvLookup + ".", null)); } }
public static void DNSSRVRecordLookup(SIPSchemesEnum scheme, SIPProtocolsEnum protocol, string host, bool async, ref SIPDNSLookupResult lookupResult) { SIPServicesEnum reqdNAPTRService = SIPServicesEnum.none; if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.udp) { reqdNAPTRService = SIPServicesEnum.sipudp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.siptcp; } else if (scheme == SIPSchemesEnum.sips && protocol == SIPProtocolsEnum.tcp) { reqdNAPTRService = SIPServicesEnum.sipstcp; } //rj2 2018-10-17: this looks wrong, but the www says: if sips then protocol is _tcp not _tls else if (scheme == SIPSchemesEnum.sips && protocol == SIPProtocolsEnum.tls) { reqdNAPTRService = SIPServicesEnum.sipstcp; } else if (scheme == SIPSchemesEnum.sip && protocol == SIPProtocolsEnum.tls) { reqdNAPTRService = SIPServicesEnum.siptls; } // If there are NAPTR records available see if there is a matching one for the SIP scheme and protocol required. // this works best (only works) if protocol in sip-uri matches sip-service of NAPTRRecord SIPDNSServiceResult naptrService = null; if (lookupResult.SIPNAPTRResults != null && lookupResult.SIPNAPTRResults.Count > 0) { if (reqdNAPTRService != SIPServicesEnum.none && lookupResult.SIPNAPTRResults.ContainsKey(reqdNAPTRService)) { naptrService = lookupResult.SIPNAPTRResults[reqdNAPTRService]; } } // Construct the SRV target to lookup depending on whether an NAPTR record was available or not. string srvLookup = null; if (naptrService != null) { srvLookup = naptrService.Data; } else { if (scheme == SIPSchemesEnum.sips) { srvLookup = SIPDNSConstants.SRV_SIPS_TCP_QUERY_PREFIX + host; } else { srvLookup = "_" + scheme.ToString() + "._" + protocol.ToString() + "." + host; } } SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup requested for " + srvLookup + ".", null)); DNSResponse srvRecordResponse = DNSManager.Lookup(srvLookup, QType.SRV, DNS_LOOKUP_TIMEOUT, null, true, async); if (srvRecordResponse == null && async) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup pending for " + srvLookup + ".", null)); lookupResult.Pending = true; } else if (srvRecordResponse.Timedout) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup timed out for " + srvLookup + ".", null)); lookupResult.SRVTimedoutAt = DateTime.Now; } else if (!string.IsNullOrWhiteSpace(srvRecordResponse.Error)) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record lookup for " + srvLookup + " returned error of " + lookupResult.LookupError + ".", null)); } else if (string.IsNullOrWhiteSpace(srvRecordResponse.Error) && srvRecordResponse.RecordSRV != null && srvRecordResponse.RecordSRV.Length > 0) { foreach (RecordSRV srvRecord in srvRecordResponse.RecordSRV) { SIPDNSServiceResult sipSRVResult = new SIPDNSServiceResult(reqdNAPTRService, srvRecord.PRIORITY, srvRecord.WEIGHT, srvRecord.RR.TTL, srvRecord.TARGET, srvRecord.PORT, DateTime.Now); lookupResult.AddSRVResult(sipSRVResult); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS SRV record found for " + srvLookup + ", result " + srvRecord.TARGET + " " + srvRecord.PORT + ".", null)); } } else { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no SRV records found for " + srvLookup + ".", null)); } }
public static SIPDNSLookupResult DNSNameRecordLookup(string host, int port, bool async, SIPURI uri, SIPDNSLookupResult lookupResult = null, bool?preferIPv6 = null, int recursionLevel = 0) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS Name record lookup requested for " + host + ".", null)); SIPDNSLookupResult result = lookupResult ?? new SIPDNSLookupResult(uri); result.LookupError = null; if (UseANYLookups) { DNSResponse aRecordResponse = DNSManager.Lookup(host, QType.ANY, DNS_A_RECORD_LOOKUP_TIMEOUT, null, true, async); if (aRecordResponse == null && async) { result.Pending = true; } else if (aRecordResponse == null) { } else if (aRecordResponse.Timedout) { result.ATimedoutAt = DateTime.Now; } else if (!string.IsNullOrWhiteSpace(aRecordResponse.Error)) { result.LookupError = aRecordResponse.Error; } else if ((aRecordResponse.RecordsAAAA == null || aRecordResponse.RecordsAAAA.Length == 0) && (aRecordResponse.RecordsA == null || aRecordResponse.RecordsA.Length == 0) && (aRecordResponse.RecordsCNAME == null || aRecordResponse.RecordsCNAME.Length == 0)) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS no CNAME, A or AAAA records found for " + host + ".", null)); result.LookupError = "No CNAME, A or AAAA records found for " + host + "."; } else { if (preferIPv6 == null) { preferIPv6 = SIPDNSManager.PreferIPv6NameResolution; } foreach (RecordCNAME aRecord in aRecordResponse.RecordsCNAME) { //CNAME could be another CNAME or A/AAAA Record -> max 3 levels recursive name resolution if (recursionLevel < 3) { SIPDNSLookupResult resultCName = DNSNameRecordLookup(aRecord.CNAME, port, async, uri, lookupResult, preferIPv6, recursionLevel + 1); if (resultCName != null) { foreach (SIPDNSLookupEndPoint ep in resultCName.EndPointResults) { result.AddLookupResult(ep); } } } } if (preferIPv6 == true) { SIPURI sipURI = result.URI; foreach (RecordAAAA aRecord in aRecordResponse.RecordsAAAA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } foreach (RecordA aRecord in aRecordResponse.RecordsA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } } else { SIPURI sipURI = result.URI; foreach (RecordA aRecord in aRecordResponse.RecordsA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS A record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } foreach (RecordAAAA aRecord in aRecordResponse.RecordsAAAA) { SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(aRecord.Address, port)), aRecord.RR.TTL); result.AddLookupResult(sipLookupEndPoint); SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS AAAA record found for " + host + ", result " + sipLookupEndPoint.LookupEndPoint.ToString() + ".", null)); } } } } if (result.LookupError != null || result.EndPointResults == null || result.EndPointResults.Count == 0) { if (preferIPv6 == true) { result = DNSAAAARecordLookup(host, port, async, uri, lookupResult); } else { result = DNSARecordLookup(host, port, async, uri, lookupResult); } } return(result); }
// TODO: Remove this nasty code duplication with ResolveSIPService! public static async Task <SIPDNSLookupResult> ResolveAsync(SIPURI sipURI, bool?preferIPv6 = null) { try { if (sipURI == null) { throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI."); } if (IPSocket.TryParseIPEndPoint(sipURI.MAddrOrHost, out var ipEndPoint)) { // Target is an IP address, no DNS lookup required. SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, ipEndPoint), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return(result); } else { string host = sipURI.MAddrOrHostAddress; //int port = IPSocket.ParsePortFromSocket(host); int port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort; if (preferIPv6 == null) { preferIPv6 = SIPDNSManager.PreferIPv6NameResolution; } bool explicitPort = false; try { //Parse returns true if sipURI.Host can be parsed as an ipaddress bool parseresult = SIPSorcery.Sys.IPSocket.Parse(sipURI.MAddrOrHost, out host, out port); explicitPort = port >= 0; if (!explicitPort) { //port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort; port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort; } if (parseresult == true) { IPAddress hostIP = IPAddress.Parse(host); SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return(result); } } catch (Exception ex) { SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + ex, null)); //rj2: if there is a parsing exception, then fallback to original sipsorcery parsing mechanism port = IPSocket.ParsePortFromSocket(sipURI.Host); explicitPort = port > 0; //if(Regex.Match(host, @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Success) if (SIPSorcery.Sys.IPSocket.IsIPAddress(host)) { // Target is an IP address, no DNS lookup required. IPAddress hostIP = IPAddress.Parse(host); SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, new IPEndPoint(hostIP, port)), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return(result); } } if (!explicitPort) { //port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort; port = sipURI.Protocol != SIPProtocolsEnum.tls ? m_defaultSIPPort : m_defaultSIPSPort; } if (host.Contains(".") == false || IPSocket.ParseHostFromSocket(host).EndsWith(MDNS_TLD)) { string hostOnly = IPSocket.ParseHostFromSocket(host); // If host is not fully qualified then assume there's no point using NAPTR or SRV record look ups and go straight to A's. if (hostOnly.ToLower() == System.Net.Dns.GetHostName()?.ToLower()) { // The lookup is for the current machine. var addressList = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList; if (addressList?.Length == 0) { return(new SIPDNSLookupResult(sipURI, $"Failed to resolve local machine hostname.")); } else { // Preference for IPv4 IP address for local host name lookup. IPAddress firstAddress = addressList.Where(x => x.AddressFamily == (preferIPv6 == true ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork)).FirstOrDefault() ?? addressList.FirstOrDefault(); SIPEndPoint resultEp = new SIPEndPoint(sipURI.Protocol, new IPEndPoint(firstAddress, port)); return(new SIPDNSLookupResult(sipURI, resultEp)); } } else { return(await Task.Run(() => DNSNameRecordLookup(hostOnly, port, false, sipURI, null, preferIPv6)).ConfigureAwait(false)); } } else if (explicitPort) { // If target is a hostname with an explicit port then SIP lookup rules state to use DNS lookup for A or AAAA record. host = host.Substring(0, host.LastIndexOf(':')); return(await Task.Run(() => DNSNameRecordLookup(host, port, false, sipURI, null, preferIPv6)).ConfigureAwait(false)); } else { // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure. SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI); // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution. //rj2: uncomment this section for telekom 1TR118 lookup SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null)); DNSNAPTRRecordLookup(host, false, ref sipLookupResult); if (sipLookupResult.Pending) { if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString())) { m_inProgressSIPServiceLookups.Add(sipURI.ToString()); //ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); }); System.Threading.ThreadPool.QueueUserWorkItem((obj) => ResolveSIPService(sipURI, false, preferIPv6)); } return(sipLookupResult); } return(await Task.Run(() => { DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, false, ref sipLookupResult); if (sipLookupResult.Pending) { //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is pending."); return sipLookupResult; } else { //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is final."); // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com). // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records. //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips) //{ // DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult); // SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); // int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; // return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI); //} //else //{ // SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); // int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; // return DNSARecordLookup(nextSRVRecord, host, lookupPort, false, sipLookupResult.URI); //} // The SRV record can indicate the SIP server is using a non-standard port. SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; return DNSNameRecordLookup(host, lookupPort, false, sipLookupResult.URI, ref sipLookupResult, preferIPv6); } }).ConfigureAwait(false)); } } } catch (Exception excp) { logger.LogError("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message); m_inProgressSIPServiceLookups.Remove(sipURI.ToString()); return(new SIPDNSLookupResult(sipURI, excp.Message)); } }
public static SIPDNSLookupResult ResolveSIPService(SIPURI sipURI, bool async) { try { if (sipURI == null) { throw new ArgumentNullException("sipURI", "Cannot resolve SIP service on a null URI."); } if (IPSocket.TryParseIPEndPoint(sipURI.Host, out var ipEndPoint)) { // Target is an IP address, no DNS lookup required. SIPDNSLookupEndPoint sipLookupEndPoint = new SIPDNSLookupEndPoint(new SIPEndPoint(sipURI.Protocol, ipEndPoint), 0); SIPDNSLookupResult result = new SIPDNSLookupResult(sipURI); result.AddLookupResult(sipLookupEndPoint); return(result); } else { string host = sipURI.Host; int port = IPSocket.ParsePortFromSocket(sipURI.Host); bool explicitPort = (port != 0); if (!explicitPort) { port = (sipURI.Scheme == SIPSchemesEnum.sip) ? m_defaultSIPPort : m_defaultSIPSPort; } if (host.Contains(".") == false) { string hostOnly = IPSocket.ParseHostFromSocket(host); // If host is not fully qualified then assume there's no point using NAPTR or SRV record look ups and go straight to A's. if (hostOnly.ToLower() == System.Net.Dns.GetHostName()?.ToLower()) { // The lookup is for the current machine. var addressList = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList; if (addressList?.Length == 0) { return(new SIPDNSLookupResult(sipURI, $"Failed to resolve local machine hostname.")); } else { // Preference for IPv4 IP address for local host anem lookup. IPAddress firstAddress = addressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault() ?? addressList.FirstOrDefault(); SIPEndPoint resultEp = new SIPEndPoint(sipURI.Protocol, new IPEndPoint(firstAddress, port)); return(new SIPDNSLookupResult(sipURI, resultEp)); } } else { return(DNSARecordLookup(hostOnly, port, async, sipURI)); } } else if (explicitPort) { // If target is a hostname with an explicit port then SIP lookup rules state to use DNS lookup for A or AAAA record. host = host.Substring(0, host.LastIndexOf(':')); return(DNSARecordLookup(host, port, async, sipURI)); } else { // Target is a hostname with no explicit port, use the whole NAPTR->SRV->A lookup procedure. SIPDNSLookupResult sipLookupResult = new SIPDNSLookupResult(sipURI); // Do without the NAPTR lookup for the time being. Very few organisations appear to use them and it can cost up to 2.5s to get a failed resolution. /*SIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.Unknown, SIPMonitorEventTypesEnum.DNS, "SIP DNS full lookup requested for " + sipURI.ToString() + ".", null)); * DNSNAPTRRecordLookup(host, async, ref sipLookupResult); * if (sipLookupResult.Pending) * { * if (!m_inProgressSIPServiceLookups.Contains(sipURI.ToString())) * { * m_inProgressSIPServiceLookups.Add(sipURI.ToString()); * ThreadPool.QueueUserWorkItem(delegate { ResolveSIPService(sipURI, false); }); * } * return sipLookupResult; * }*/ DNSSRVRecordLookup(sipURI.Scheme, sipURI.Protocol, host, async, ref sipLookupResult); if (sipLookupResult.Pending) { //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is pending."); return(sipLookupResult); } else { //logger.LogDebug("SIPDNSManager SRV lookup for " + host + " is final."); // Add some custom logic to cope with sips SRV records using _sips._tcp (e.g. free.call.ciscospark.com). // By default only _sips._tls SRV records are checked for. THis block adds an additional check for _sips._tcp SRV records. //if ((sipLookupResult.SIPSRVResults == null || sipLookupResult.SIPSRVResults.Count == 0) && sipURI.Scheme == SIPSchemesEnum.sips) //{ // DNSSRVRecordLookup(sipURI.Scheme, SIPProtocolsEnum.tcp, host, async, ref sipLookupResult); // SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); // int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; // return DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI); //} //else //{ SIPDNSServiceResult nextSRVRecord = sipLookupResult.GetNextUnusedSRV(); int lookupPort = (nextSRVRecord != null) ? nextSRVRecord.Port : port; return(DNSARecordLookup(nextSRVRecord, host, lookupPort, async, sipLookupResult.URI)); //} } } } } catch (Exception excp) { logger.LogError("Exception SIPDNSManager ResolveSIPService (" + sipURI.ToString() + "). " + excp.Message); m_inProgressSIPServiceLookups.Remove(sipURI.ToString()); return(new SIPDNSLookupResult(sipURI, excp.Message)); } }