public SIPEndPoint(SIPURI sipURI) { Protocol = sipURI.Protocol; IPEndPoint endPoint = IPSocket.ParseSocketString(sipURI.Host); Address = endPoint.Address; Port = (endPoint.Port == 0) ? (Protocol == SIPProtocolsEnum.tls) ? m_defaultSIPTLSPort : m_defaultSIPPort : endPoint.Port; }
public SIPEventPresenceTuple(string id, SIPEventPresenceStateEnum status, SIPURI contactURI, decimal contactPriority) { ID = id; Status = status; ContactURI = contactURI; ContactPriority = contactPriority; }
public SIPUserField(string name, SIPURI uri, string paramsAndHeaders) { Name = name; URI = uri; Parameters = new SIPParameters(paramsAndHeaders, PARAM_TAG_DELIMITER); }
public SIPEventDialogParticipant(string displayName, SIPURI uri, SIPURI targetURI, int cseq) { DisplayName = displayName; URI = uri; TargetURI = targetURI; CSeq = cseq; }
public SIPEndPoint(SIPURI sipURI) { Protocol = sipURI.Protocol; IPEndPoint endPoint = IPSocket.ParseSocketString(sipURI.Host); Address = endPoint.Address; Port = endPoint.Port; }
public void SetProviderFields(SIPProvider sipProvider) { ProviderID = sipProvider.ID; Owner = sipProvider.Owner; AdminMemberID = sipProvider.AdminMemberID; ProviderName = sipProvider.ProviderName; ProviderAuthUsername = (!sipProvider.ProviderAuthUsername.IsNullOrBlank()) ? sipProvider.ProviderAuthUsername : sipProvider.ProviderUsername; ProviderPassword = sipProvider.ProviderPassword; RegistrarServer = sipProvider.GetRegistrar(); RegistrarRealm = (!sipProvider.RegisterRealm.IsNullOrBlank()) ? sipProvider.RegisterRealm : RegistrarServer.Host; ProviderOutboundProxy = sipProvider.ProviderOutboundProxy; if (sipProvider.RegisterEnabled) { BindingExpiry = (sipProvider.RegisterExpiry.HasValue) ? sipProvider.RegisterExpiry.Value : 0; } else { BindingExpiry = 0; } string bindingId = null; SIPURI binding = (!BindingURI.IsNullOrBlank()) ? SIPURI.ParseSIPURIRelaxed(BindingURI) : null; if (binding != null && binding.Parameters.Has(REGAGENT_CONTACT_ID_KEY)) { bindingId = binding.Parameters.Get(REGAGENT_CONTACT_ID_KEY); } if (!sipProvider.RegisterContact.IsNullOrBlank()) { binding = SIPURI.ParseSIPURI(sipProvider.RegisterContact); if (!bindingId.IsNullOrBlank()) { binding.Parameters.Set(REGAGENT_CONTACT_ID_KEY, bindingId); } if (binding != null) { BindingURI = binding.ToString(); } else { BindingURI = null; BindingExpiry = 0; } } else { // The register contact field on the SIP Provider is empty. // This condition needs to be trearted as the binding being disabled and it needs to be removed. BindingExpiry = 0; } }
/// <summary> /// In transaction ACK requests are for non-2xx responses, i.e. INVITE rejected and no dialogue being created. /// </summary> private SIPRequest GetInTransactionACKRequest(SIPResponse sipResponse, SIPURI ackURI, SIPEndPoint localSIPEndPoint) { SIPRequest ackRequest = new SIPRequest(SIPMethodsEnum.ACK, ackURI.ToString()); ackRequest.LocalSIPEndPoint = localSIPEndPoint; SIPHeader header = new SIPHeader(TransactionRequest.Header.From, sipResponse.Header.To, sipResponse.Header.CSeq, sipResponse.Header.CallId); header.CSeqMethod = SIPMethodsEnum.ACK; header.AuthenticationHeader = TransactionRequest.Header.AuthenticationHeader; header.Routes = base.TransactionRequest.Header.Routes; header.ProxySendFrom = base.TransactionRequest.Header.ProxySendFrom; ackRequest.Header = header; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, sipResponse.Header.Vias.TopViaHeader.Branch); ackRequest.Header.Vias.PushViaHeader(viaHeader); return ackRequest; }
public SIPDNSLookupResult(SIPURI uri, string lookupError) { URI = uri; LookupError = lookupError; }
public SIPDNSLookupResult Resolve(SIPURI sipURI) { return SIPDNSManager.ResolveSIPService(sipURI, true); }
public SIPRegistrationUserAgent( SIPTransport sipTransport, SIPEndPoint outboundProxy, SIPEndPoint localEndPoint, SIPURI sipAccountAOR, string authUsername, string password, string realm, string registrarHost, SIPURI contactURI, int expiry, string owner, string adminMemberID, SIPMonitorLogDelegate logDelegate) { m_sipTransport = sipTransport; m_outboundProxy = outboundProxy; m_localEndPoint = localEndPoint; m_sipAccountAOR = sipAccountAOR; m_authUsername = authUsername; m_password = password; m_realm = realm; m_registrarHost = registrarHost; m_contactURI = contactURI; m_expiry = (expiry >= REGISTER_MINIMUM_EXPIRY && expiry <= MAX_EXPIRY) ? expiry : DEFAULT_REGISTER_EXPIRY; m_owner = owner; m_adminMemberID = adminMemberID; m_callID = Guid.NewGuid().ToString(); Log_External = logDelegate; }
public SIPEventPresence(SIPURI entity) { Entity = entity.CopyOf(); }
public SIPMonitorFilter(string filter) { if (!filter.IsNullOrBlank()) { string[] filterItems = Regex.Split(filter, @"\s+and\s+"); if (filterItems != null && filterItems.Length > 0) { foreach (string filterItem in filterItems) { string[] filterPair = filterItem.Trim().Split(' '); if (filterPair != null && filterPair.Length == 2) { string filterName = filterPair[0]; string filterValue = filterPair[1]; if (filterName == BASETYPE_FILTER_KEY) { BaseType = filterValue; } else if (filterName == EVENTTYPE_FILTER_KEY) { if (filterValue != null && Regex.Match(filterValue, @"\d{1,2}").Success) { EventTypeId = Convert.ToInt32(filterValue); } else { EventFilterDescr = filterValue; } } else if (filterName == MACHINE_EVENTTYPE_FILTER_KEY) { if (!filterValue.IsNullOrBlank()) { MachineEventTypeIds = new List<int>(); string[] ids = filterValue.Split(','); foreach (string id in ids) { int eventId = 0; if (Int32.TryParse(id, out eventId)) { MachineEventTypeIds.Add(eventId); } } } } else if (filterName == SERVERADDRESS_FILTER_KEY) { ServerIPAddress = filterValue; } else if (filterName == IPADDRESS_FILTER_KEY || filterName == IPADDRESSLONG_FILTER_KEY) { IPAddress = filterValue; } else if (filterName == USERNAME_FILTER_KEY) { Username = filterValue; } else if (filterName == SIPREQUEST_FILTER_KEY) { SIPRequestFilter = filterValue; } else if (filterName == SERVERTYPE_FILTER_KEY) { if (filterValue != null && Regex.Match(filterValue, @"\d{1,2}").Success) { ServerTypeId = Convert.ToInt32(filterValue); // Help the user out and set a wildcard type on the event if none has been selected. if (EventFilterDescr == null && EventTypeId == 0) { EventFilterDescr = WILDCARD; } } } else if (filterName == FILELOG_REQUEST_KEY) { if (filterValue != null) { FileLogname = filterValue; } } else if (filterName == FILELOG_MINUTESDURATION_KEY) { if (filterValue != null && Regex.Match(filterValue, @"\d").Success) { FileLogDuration = Convert.ToInt32(filterValue); if (FileLogDuration > MAX_FILEDURATION_MINUTES) { FileLogDuration = MAX_FILEDURATION_MINUTES; } } } else if (filterName == REGEX_FILTER_KEY) { if (filterValue != null) { RegexFilter = filterValue; } } else if (filterName == SIPEVENT_DIALOG_KEY) { BaseType = MACHINE_BASE_TYPE; SIPEventDialogURI = SIPURI.ParseSIPURI(filterValue); } else if (filterName == SIPEVENT_PRESENCE_KEY) { BaseType = MACHINE_BASE_TYPE; SIPEventPresenceURI = SIPURI.ParseSIPURI(filterValue); } else { throw new ApplicationException("Filter " + filterName + " was not recognised."); } } else { throw new ApplicationException("Invalid item in filter: " + filterItem.Trim() + "."); } } } else { throw new ApplicationException("Invalid filter format: " + filter + "."); } } }
private SIPProtocolsEnum GetRemoteTargetProtocol() { SIPURI dstURI = (RouteSet == null) ? RemoteTarget : RouteSet.TopRoute.URI; return(dstURI.Protocol); }
public SIPToHeader(string toName, SIPURI toURI, string toTag) { m_userField = new SIPUserField(toName, toURI, null); ToTag = toTag; }
public SIPParameterlessURI(SIPSchemesEnum scheme, string host, string user) { m_uri = new SIPURI(user, host, null); m_uri.Scheme = scheme; }
/// <summary> /// Resolve method that performs either an A or AAAA record lookup. If required /// a SRV record lookup will be performed prior to the A or AAAA lookup. /// </summary> /// <param name="uri">The SIP URI to lookup.</param> /// <param name="queryType">Whether the address lookup should be A or AAAA.</param> /// <returns>A SIPEndPoint or null.</returns> private static async Task <SIPEndPoint> Resolve(SIPURI uri, QueryType queryType) { if (uri == null || String.IsNullOrWhiteSpace(uri.MAddrOrHostAddress)) { throw new ArgumentNullException("uri", "SIP DNS resolve was supplied an empty input."); } if (!ushort.TryParse(uri.HostPort, out var uriPort)) { uriPort = SIPConstants.DEFAULT_SIP_PORT; } if (IPAddress.TryParse(uri.MAddrOrHostAddress, out var ipAddress)) { // Target is already an IP address, no DNS lookup required. return(new SIPEndPoint(uri.Protocol, ipAddress, uriPort)); } else { if (!uri.MAddrOrHostAddress.Contains(".") || uri.MAddrOrHostAddress.EndsWith(MDNS_TLD)) { AddressFamily family = (queryType == QueryType.AAAA) ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork; // The lookup is for a local network host. Use the OS DNS logic as the // main DNS client can be configured to use external DNS servers that won't // be able to lookup this hostname. IPHostEntry hostEntry = null; try { hostEntry = Dns.GetHostEntry(uri.MAddrOrHostAddress); } catch (SocketException) { // Socket exception gets thrown for failed lookups, } if (hostEntry != null) { var addressList = hostEntry.AddressList; if (addressList?.Length == 0) { logger.LogWarning($"Operating System DNS lookup failed for {uri.MAddrOrHostAddress}."); return(null); } else { if (addressList.Any(x => x.AddressFamily == family)) { var addressResult = addressList.First(x => x.AddressFamily == family); return(new SIPEndPoint(uri.Protocol, addressResult, uriPort)); } else { // Didn't get a result for the preferred address family so just use the // first available result. var addressResult = addressList.First(); return(new SIPEndPoint(uri.Protocol, addressResult, uriPort)); } } } else { return(null); } } else { if (uri.HostPort != null) { // Explicit port means no SRV lookup. return(HostQuery(uri.Protocol, uri.MAddrOrHostAddress, uriPort, queryType)); } else { // No explicit port so use a SRV -> (A | AAAA -> A | ANY) record lookup. var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri); try { ServiceHostEntry srvResult = null; var srvResults = await _lookupClient.ResolveServiceAsync(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()).ConfigureAwait(false); if (srvResults == null || srvResults.Count() == 0) { logger.LogWarning($"SIP DNS SRV lookup returned no results for {uri}."); } else { srvResult = srvResults.OrderBy(y => y.Priority).ThenByDescending(w => w.Weight).FirstOrDefault(); } string host = uri.MAddrOrHostAddress; // If no SRV results then fallback is to lookup the hostname directly. int port = SIPConstants.DEFAULT_SIP_PORT; // If no SRV results then fallback is to use the default port. if (srvResult != null) { host = srvResult.HostName; port = srvResult.Port; } return(HostQuery(uri.Protocol, host, port, queryType)); } catch (Exception e) { logger.LogWarning($"SIP DNS SRV lookup failure for {uri}. {e?.InnerException?.Message}"); } } } return(null); } }
public SIPParameterlessURI(SIPURI sipURI) { m_uri = sipURI; }
public SIPRequest(SIPMethodsEnum method, SIPURI uri) { Method = method; URI = uri; SIPVersion = m_sipFullVersion; }
public SIPRequest(SIPMethodsEnum method, string uri) { Method = method; URI = SIPURI.ParseSIPURI(uri); SIPVersion = m_sipFullVersion; }
public SIPRequest GetRequest(SIPMethodsEnum method, SIPURI uri, SIPToHeader to, SIPEndPoint localSIPEndPoint) { if (localSIPEndPoint == null) { localSIPEndPoint = GetDefaultSIPEndPoint(); } SIPRequest request = new SIPRequest(method, uri); request.LocalSIPEndPoint = localSIPEndPoint; SIPContactHeader contactHeader = new SIPContactHeader(null, new SIPURI(SIPSchemesEnum.sip, localSIPEndPoint)); SIPFromHeader fromHeader = new SIPFromHeader(null, contactHeader.ContactURI, CallProperties.CreateNewTag()); SIPHeader header = new SIPHeader(contactHeader, fromHeader, to, 1, CallProperties.CreateNewCallId()); request.Header = header; header.CSeqMethod = method; header.Allow = ALLOWED_SIP_METHODS; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId()); header.Vias.PushViaHeader(viaHeader); return request; }
private SIPEndPoint GetRemoteTargetEndpoint() { SIPURI dstURI = (RouteSet == null) ? RemoteTarget : RouteSet.TopRoute.URI; return(dstURI.ToSIPEndPoint()); }
public static SIPUserField ParseSIPUserField(string userFieldStr) { if (userFieldStr.IsNullOrBlank()) { throw new ArgumentException("A SIPUserField cannot be parsed from an empty string."); } SIPUserField userField = new SIPUserField(); string trimUserField = userFieldStr.Trim(); int position = trimUserField.IndexOf('<'); if (position == -1) { // Treat the field as a URI only, except that all parameters are Header parameters and not URI parameters // (RFC3261 section 20.39 which refers to 20.10 for parsing rules). string uriStr = trimUserField; int paramDelimPosn = trimUserField.IndexOf(PARAM_TAG_DELIMITER); if (paramDelimPosn != -1) { string paramStr = trimUserField.Substring(paramDelimPosn + 1).Trim(); userField.Parameters = new SIPParameters(paramStr, PARAM_TAG_DELIMITER); uriStr = trimUserField.Substring(0, paramDelimPosn); } userField.URI = SIPURI.ParseSIPURI(uriStr); } else { if (position > 0) { userField.Name = trimUserField.Substring(0, position).Trim().Trim('"'); trimUserField = trimUserField.Substring(position, trimUserField.Length - position); } int addrSpecLen = trimUserField.Length; position = trimUserField.IndexOf('>'); if (position != -1) { addrSpecLen = trimUserField.Length - 1; if (position != -1) { addrSpecLen = position - 1; string paramStr = trimUserField.Substring(position + 1).Trim(); userField.Parameters = new SIPParameters(paramStr, PARAM_TAG_DELIMITER); } string addrSpec = trimUserField.Substring(1, addrSpecLen); userField.URI = SIPURI.ParseSIPURI(addrSpec); } else { throw new SIPValidationException(SIPValidationFieldsEnum.ContactHeader, "A SIPUserField was missing the right quote, " + userFieldStr + "."); } } return(userField); }
/// <summary> /// New transaction ACK requests are for 2xx responses, i.e. INVITE accepted and dialogue being created. /// </summary> /// <remarks> /// From RFC 3261 Chapter 13.2.2.4 - ACK for 2xx final responses /// /// IMPORTANT: /// an ACK for a 2xx final response is a new transaction and has a new branch ID. /// /// The UAC core MUST generate an ACK request for each 2xx received from /// the transaction layer. The header fields of the ACK are constructed /// in the same way as for any request sent within a dialog (see Section /// 12) with the exception of the CSeq and the header fields related to /// authentication. The sequence number of the CSeq header field MUST be /// the same as the INVITE being acknowledged, but the CSeq method MUST /// be ACK. The ACK MUST contain the same credentials as the INVITE. If /// the 2xx contains an offer (based on the rules above), the ACK MUST /// carry an answer in its body. If the offer in the 2xx response is not /// acceptable, the UAC core MUST generate a valid answer in the ACK and /// then send a BYE immediately. /// </remarks> private SIPRequest GetNewTransactionAcknowledgeRequest(SIPMethodsEnum method, SIPResponse sipResponse, SIPURI ackURI) { SIPRequest ackRequest = new SIPRequest(method, ackURI.ToString()); ackRequest.SetSendFromHints(sipResponse.LocalSIPEndPoint); SIPHeader header = new SIPHeader(TransactionRequest.Header.From, sipResponse.Header.To, sipResponse.Header.CSeq, sipResponse.Header.CallId); header.CSeqMethod = method; header.AuthenticationHeader = TransactionRequest.Header.AuthenticationHeader; header.ProxySendFrom = base.TransactionRequest.Header.ProxySendFrom; // If the UAS supplies a desired Record-Route list use that first. Otherwise fall back to any Route list used in the original transaction. if (sipResponse.Header.RecordRoutes != null) { header.Routes = sipResponse.Header.RecordRoutes.Reversed(); } else if (base.TransactionRequest.Header.Routes != null) { header.Routes = base.TransactionRequest.Header.Routes; } ackRequest.Header = header; ackRequest.Header.Vias.PushViaHeader(SIPViaHeader.GetDefaultSIPViaHeader()); return(ackRequest); }
public static SIPURI ParseSIPURI(string uri) { try { SIPURI sipURI = new SIPURI(); if (uri == null || uri.Trim().Length == 0) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "A SIP URI cannot be parsed from an empty string."); } else { if (uri == m_sipRegisterRemoveAll) { sipURI.Host = m_sipRegisterRemoveAll; } else { int colonPosn = uri.IndexOf(SCHEME_ADDR_SEPARATOR); if (colonPosn == -1) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "SIP URI did not contain compulsory colon"); } else { try { sipURI.Scheme = SIPSchemesType.GetSchemeType(uri.Substring(0, colonPosn)); } catch { throw new SIPValidationException(SIPValidationFieldsEnum.URI, SIPResponseStatusCodesEnum.UnsupportedURIScheme, "SIP scheme " + uri.Substring(0, colonPosn) + " was not understood"); } string uriHostPortion = uri.Substring(colonPosn + 1); int ampPosn = uriHostPortion.IndexOf(USER_HOST_SEPARATOR); int paramHeaderPosn = -1; if (ampPosn != -1) { paramHeaderPosn = uriHostPortion.IndexOfAny(new char[] { PARAM_TAG_DELIMITER, HEADER_START_DELIMITER }, ampPosn); } else { // Host only SIP URI. paramHeaderPosn = uriHostPortion.IndexOfAny(new char[] { PARAM_TAG_DELIMITER, HEADER_START_DELIMITER }); } if (ampPosn != -1 && paramHeaderPosn != -1) { sipURI.User = uriHostPortion.Substring(0, ampPosn); sipURI.Host = uriHostPortion.Substring(ampPosn + 1, paramHeaderPosn - ampPosn - 1); string paramsAndHeaders = uriHostPortion.Substring(paramHeaderPosn); sipURI.ParseParamsAndHeaders(paramsAndHeaders); } else if (ampPosn == -1 && paramHeaderPosn == 0) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "No Host portion in SIP URI"); } else if (ampPosn == -1 && paramHeaderPosn != -1) { sipURI.Host = uriHostPortion.Substring(0, paramHeaderPosn); string paramsAndHeaders = uriHostPortion.Substring(paramHeaderPosn); sipURI.ParseParamsAndHeaders(paramsAndHeaders); } else if (ampPosn != -1) { sipURI.User = uriHostPortion.Substring(0, ampPosn); sipURI.Host = uriHostPortion.Substring(ampPosn + 1, uriHostPortion.Length - ampPosn - 1); } else { sipURI.Host = uriHostPortion; } if (sipURI.Host.IndexOfAny(m_invalidSIPHostChars) != -1) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "The SIP URI host portion contained an invalid character."); } } } return(sipURI); } } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.Error("Exception ParseSIPURI (URI=" + uri + "). " + excp.Message); throw new SIPValidationException(SIPValidationFieldsEnum.URI, "Unknown error parsing SIP URI."); } }
public bool Pending; // If an aysnc lookup request is made this will be set to true if no immediate result is available. public SIPDNSLookupResult(SIPURI uri) { URI = uri; }
public static bool AreEqual(SIPURI uri1, SIPURI uri2) { return(uri1 == uri2); }
/// <summary> /// Can't be used for local destinations! /// </summary> /// <param name="sipRequest"></param> /// <param name="command"></param> /// <returns></returns> private SIPCallDescriptor GetForwardsForExternalLeg( SIPRequest sipRequest, SIPURI callLegURI, string customContentType, string customContent, string fromDisplayName, string fromUsername, string fromHost, CRMHeaders contact) { try { SIPCallDescriptor sipCallDescriptor = null; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Attempting to locate a provider for call leg: " + callLegURI.ToString() + ".", m_username)); bool providerFound = false; string contentType = (sipRequest != null) ? sipRequest.Header.ContentType : null; string content = (sipRequest != null) ? sipRequest.Body : null; if (!customContentType.IsNullOrBlank()) { contentType = customContentType; } if (!customContent.IsNullOrBlank()) { content = customContent; } IPAddress publicSDPAddress = PublicIPAddress; if (publicSDPAddress == null && sipRequest != null) { publicSDPAddress = SIPPacketMangler.GetRequestIPAddress(sipRequest); } if (m_sipProviders != null) { foreach (SIPProvider provider in m_sipProviders) { if (callLegURI.Host.ToUpper() == provider.ProviderName.ToUpper()) { if (provider.ProviderType == ProviderTypes.GoogleVoice) { sipCallDescriptor = new SIPCallDescriptor( provider.ProviderUsername, provider.ProviderPassword, callLegURI.User + "@" + provider.ProviderName, provider.GVCallbackNumber, provider.GVCallbackPattern, (provider.GVCallbackType != null) ? (int)provider.GVCallbackType.Value : DEFAULT_GVCALLBACK_TYPE, content, contentType); sipCallDescriptor.CRMHeaders = contact; providerFound = true; break; } else { SIPURI providerURI = SIPURI.ParseSIPURI(provider.ProviderServer); if (providerURI != null) { providerURI.User = callLegURI.User; if (callLegURI.Parameters.Count > 0) { foreach (string parameterName in callLegURI.Parameters.GetKeys()) { if (!providerURI.Parameters.Has(parameterName)) { providerURI.Parameters.Set(parameterName, callLegURI.Parameters.Get(parameterName)); } } } if (callLegURI.Headers.Count > 0) { foreach (string headerName in callLegURI.Headers.GetKeys()) { if (!providerURI.Headers.Has(headerName)) { providerURI.Headers.Set(headerName, callLegURI.Headers.Get(headerName)); } } } SIPFromHeader fromHeader = ParseFromHeaderOption(provider.ProviderFrom, sipRequest, provider.ProviderUsername, providerURI.Host); sipCallDescriptor = new SIPCallDescriptor( provider.ProviderUsername, provider.ProviderPassword, providerURI.ToString(), fromHeader.ToString(), providerURI.ToString(), null, SIPCallDescriptor.ParseCustomHeaders(SubstituteRequestVars(sipRequest, provider.CustomHeaders)), provider.ProviderAuthUsername, SIPCallDirection.Out, contentType, content, publicSDPAddress); sipCallDescriptor.CRMHeaders = contact; if (!provider.ProviderOutboundProxy.IsNullOrBlank()) { sipCallDescriptor.ProxySendFrom = provider.ProviderOutboundProxy.Trim(); } providerFound = true; if (provider.ProviderFrom.IsNullOrBlank()) { // If there is already a custom From header set on the provider that overrides the general settings. sipCallDescriptor.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); } break; } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Could not parse SIP URI from Provider Server " + provider.ProviderServer + " in GetForwardsForExternalLeg.", m_username)); } } } } } if (!providerFound) { // Treat as an anonymous SIP URI. // Copy the From header so the tag can be removed before adding to the forwarded request. string fromHeaderStr = (sipRequest != null) ? sipRequest.Header.From.ToString() : m_anonymousFromURI; SIPFromHeader forwardedFromHeader = SIPFromHeader.ParseFromHeader(fromHeaderStr); forwardedFromHeader.FromTag = null; sipCallDescriptor = new SIPCallDescriptor( m_anonymousUsername, null, callLegURI.ToString(), forwardedFromHeader.ToString(), callLegURI.ToString(), null, null, null, SIPCallDirection.Out, contentType, content, publicSDPAddress); sipCallDescriptor.CRMHeaders = contact; sipCallDescriptor.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); } return sipCallDescriptor; } catch (Exception excp) { logger.Error("Exception GetForwardsForExternalLeg. " + excp.Message); return null; } }
/// <summary> /// Attempts a lookup from cache. /// </summary> /// <param name="uri"></param> /// <param name="startQuery"></param> /// <param name="preferIPv6"></param> /// <returns></returns> private static SIPEndPoint SIPLookupFromCache( SIPURI uri, QueryType startQuery, bool preferIPv6) { CancellationTokenSource cts = new CancellationTokenSource(); return(SIPLookupAsync(uri, startQuery, preferIPv6, cts.Token).Result); // TODO: Re-enable when DnsClient adds cache querying. //SIPEndPoint result = null; //QueryType queryType = startQuery; //string host = uri.MAddrOrHostAddress; //int port = SIPConstants.GetDefaultPort(uri.Protocol); //if (ushort.TryParse(uri.HostPort, out var uriPort)) //{ // port = uriPort; //} //bool isDone = false; //while (!isDone) //{ // switch (queryType) // { // case QueryType.SRV: // var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri); // string serviceHost = DnsQueryExtensions.ConcatResolveServiceName(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()); // var srvResult = _lookupClient.QueryCache(serviceHost, QueryType.SRV); // (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult); // if (srvHost != null) // { // host = srvHost; // port = srvPort != 0 ? srvPort : port; // } // queryType = preferIPv6 ? QueryType.AAAA : QueryType.A; // break; // case QueryType.AAAA: // var aaaaResult = _lookupClient.QueryCache(host, UseANYLookups ? QueryType.ANY : QueryType.AAAA, QueryClass.IN); // if (aaaaResult?.Answers?.Count > 0) // { // result = GetFromLookupResult(uri.Protocol, aaaaResult.Answers.OrderByDescending(x => x.RecordType).First(), port); // isDone = true; // } // else // { // queryType = QueryType.A; // } // break; // default: // // A record lookup. // var aResult = _lookupClient.QueryCache(host, QueryType.A, QueryClass.IN); // if (aResult != null) // { // if (aResult.Answers?.Count > 0) // { // result = GetFromLookupResult(uri.Protocol, aResult.Answers.First(), port); // } // else // { // // We got a result back but it was empty indicating an unresolvable host or // // some other DNS error condition. // result = SIPEndPoint.Empty; // } // } // isDone = true; // break; // } //} //return result; }
private SIPRequest GetOptionsRequest(SIPURI serverURI, int cseq, IPEndPoint contact) { SIPRequest optionsRequest = new SIPRequest(SIPMethodsEnum.OPTIONS, serverURI); SIPFromHeader fromHeader = new SIPFromHeader(null, SIPURI.ParseSIPURI("sip:" + contact.ToString()), null); SIPToHeader toHeader = new SIPToHeader(null, serverURI, null); string callId = CallProperties.CreateNewCallId(); string branchId = CallProperties.CreateBranchId(); SIPHeader header = new SIPHeader(fromHeader, toHeader, cseq, callId); header.CSeqMethod = SIPMethodsEnum.OPTIONS; header.MaxForwards = 0; SIPViaHeader viaHeader = new SIPViaHeader(contact.Address.ToString(), contact.Port, branchId); header.Vias.PushViaHeader(viaHeader); optionsRequest.Header = header; return optionsRequest; }
/// <summary> /// Attempts a lookup from DNS. /// </summary> /// <param name="uri"></param> /// <param name="startQuery"></param> /// <param name="preferIPv6"></param> /// <param name="ct"></param> /// <returns></returns> private static async Task <SIPEndPoint> SIPLookupAsync( SIPURI uri, QueryType startQuery, bool preferIPv6, CancellationToken ct) { SIPEndPoint result = null; QueryType queryType = startQuery; string host = uri.MAddrOrHostAddress; int port = SIPConstants.GetDefaultPort(uri.Protocol); if (ushort.TryParse(uri.HostPort, out var uriPort)) { port = uriPort; } bool isDone = false; while (!isDone && !ct.IsCancellationRequested) { switch (queryType) { case QueryType.SRV: try { var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri); //string serviceHost = DnsQueryExtensions.ConcatResolveServiceName(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()); //var srvResult = await _lookupClient.QueryAsync(serviceHost, QueryType.SRV, QueryClass.IN, ct).ConfigureAwait(false); var srvResult = await _lookupClient.ResolveServiceAsync(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()); (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult); if (srvHost != null) { host = srvHost; port = srvPort != 0 ? srvPort : port; } } catch (Exception srvExcp) { logger.LogWarning($"SIPDNS exception on SRV lookup. {srvExcp.Message}."); } queryType = preferIPv6 ? QueryType.AAAA : QueryType.A; break; case QueryType.AAAA: try { var aaaaResult = await _lookupClient.QueryAsync(host, UseANYLookups?QueryType.ANY : QueryType.AAAA, QueryClass.IN, ct).ConfigureAwait(false); if (aaaaResult?.Answers?.Count > 0) { result = GetFromLookupResult(uri.Protocol, aaaaResult.Answers.AddressRecords().OrderByDescending(x => x.RecordType).First(), port); isDone = true; } else { queryType = QueryType.A; } } catch (Exception srvExcp) { logger.LogWarning($"SIPDNS exception on AAAA lookup. {srvExcp.Message}."); queryType = QueryType.A; } break; default: // A record lookup. try { var aResult = await _lookupClient.QueryAsync(host, QueryType.A, QueryClass.IN, ct).ConfigureAwait(false); if (aResult != null) { if (aResult.Answers?.Count > 0) { result = GetFromLookupResult(uri.Protocol, aResult.Answers.AddressRecords().First(), port); } else { // We got a result back but it was empty indicating an unresolvable host or // some other DNS error condition. result = SIPEndPoint.Empty; } } } catch (Exception srvExcp) { logger.LogWarning($"SIPDNS exception on A lookup. {srvExcp.Message}."); result = SIPEndPoint.Empty; } isDone = true; break; } } return(result); }
public SIPCDR( SIPCallDirection callDirection, SIPURI destination, SIPFromHeader from, string callId, SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint) { CDRId = Guid.NewGuid(); Created = DateTimeOffset.UtcNow; CallDirection = callDirection; Destination = destination; From = from; CallId = callId; LocalSIPEndPoint = localSIPEndPoint; RemoteEndPoint = remoteEndPoint; InProgress = false; IsAnswered = false; IsHungup = false; CDRCreated(this); }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="ringTimeout"></param> /// <param name="answeredCallLimit"></param> /// <param name="redirectMode"></param> /// <param name="clientTransaction"></param> /// <param name="keepScriptAlive">If false will let the dial plan engine know the script has finished and the call is answered. For applications /// like Callback which need to have two calls answered it will be true.</param> /// <returns></returns> private DialPlanAppResult Dial( string data, int ringTimeout, int answeredCallLimit, SIPRequest clientRequest, CRMHeaders contact) { if (m_dialPlanContext.IsAnswered) { Log("The call has already been answered the Dial command was not processed."); return DialPlanAppResult.AlreadyAnswered; } else if (data.IsNullOrBlank()) { Log("The dial string cannot be empty when calling Dial."); return DialPlanAppResult.Error; } else if (m_callInitialisationCount > MAX_CALLS_ALLOWED) { Log("You have exceeded the maximum allowed calls for a dialplan execution."); return DialPlanAppResult.Error; } else { Log("Commencing Dial with: " + data + "."); DialPlanAppResult result = DialPlanAppResult.Unknown; m_waitForCallCompleted = new ManualResetEvent(false); SIPResponseStatusCodesEnum answeredStatus = SIPResponseStatusCodesEnum.None; string answeredReason = null; string answeredContentType = null; string answeredBody = null; SIPDialogue answeredDialogue = null; SIPDialogueTransferModesEnum uasTransferMode = SIPDialogueTransferModesEnum.Default; int numberLegs = 0; QueueNewCallDelegate queueNewCall = (m_callManager != null) ? m_callManager.QueueNewCall : (QueueNewCallDelegate)null; m_currentCall = new ForkCall(m_sipTransport, FireProxyLogEvent, queueNewCall, m_dialStringParser, Username, m_adminMemberId, m_outboundProxySocket, m_callManager, m_dialPlanContext, out LastDialled); m_currentCall.CallProgress += m_dialPlanContext.CallProgress; m_currentCall.CallFailed += (status, reason, headers) => { LastFailureStatus = status; LastFailureReason = reason; result = DialPlanAppResult.Failed; m_waitForCallCompleted.Set(); }; m_currentCall.CallAnswered += (status, reason, toTag, headers, contentType, body, dialogue, transferMode) => { answeredStatus = status; answeredReason = reason; answeredContentType = contentType; answeredBody = body; answeredDialogue = dialogue; uasTransferMode = transferMode; result = DialPlanAppResult.Answered; m_waitForCallCompleted.Set(); }; try { Queue<List<SIPCallDescriptor>> callsQueue = m_dialStringParser.ParseDialString( DialPlanContextsEnum.Script, clientRequest, data, m_customSIPHeaders, m_customContentType, m_customContent, m_dialPlanContext.CallersNetworkId, m_customFromName, m_customFromUser, m_customFromHost, contact, ServiceLevel); List<SIPCallDescriptor>[] callListArray = callsQueue.ToArray(); callsQueue.ToList().ForEach((list) => numberLegs += list.Count); if (numberLegs == 0) { Log("The dial string did not result in any call legs."); return DialPlanAppResult.Error; } else { m_callInitialisationCount += numberLegs; if (m_callInitialisationCount > MAX_CALLS_ALLOWED) { Log("You have exceeded the maximum allowed calls for a dialplan execution."); return DialPlanAppResult.Error; } } m_currentCall.Start(callsQueue); // Wait for an answer. if (ringTimeout <= 0 || ringTimeout * 1000 > m_maxRingTime) { ringTimeout = m_maxRingTime; } else { ringTimeout = ringTimeout * 1000; } ExtendScriptTimeout(ringTimeout / 1000 + DEFAULT_CREATECALL_RINGTIME); DateTime startTime = DateTime.Now; if (m_waitForCallCompleted.WaitOne(ringTimeout, false)) { if (!m_clientCallCancelled) { if (result == DialPlanAppResult.Answered) { // The call limit duration is only used if there hasn't already been a per leg duration set on the call. if (answeredCallLimit > 0 && answeredDialogue.CallDurationLimit == 0) { answeredDialogue.CallDurationLimit = answeredCallLimit; } m_dialPlanContext.CallAnswered(answeredStatus, answeredReason, null, null, answeredContentType, answeredBody, answeredDialogue, uasTransferMode); // Dial plan script stops once there is an answered call to bridge to or the client call is cancelled. Log("Dial command was successfully answered in " + DateTime.Now.Subtract(startTime).TotalSeconds.ToString("0.00") + "s."); // Do some Google Analytics call tracking. if (answeredDialogue.RemoteUserField != null) { SendGoogleAnalyticsEvent("Call", "Answered", answeredDialogue.RemoteUserField.URI.Host, 1); } m_executingScript.StopExecution(); } else if (result == DialPlanAppResult.Failed) { // Check whether any of the responses were redirects. if (LastDialled != null && LastDialled.Count > 0) { var redirect = (from trans in LastDialled where trans.TransactionFinalResponse != null && trans.TransactionFinalResponse.StatusCode >= 300 && trans.TransactionFinalResponse.StatusCode <= 399 && trans.TransactionFinalResponse.Header.Contact != null && trans.TransactionFinalResponse.Header.Contact.Count > 0 select trans.TransactionFinalResponse).FirstOrDefault(); if (redirect != null) { m_redirectResponse = redirect; m_redirectURI = RedirectResponse.Header.Contact[0].ContactURI; result = DialPlanAppResult.Redirect; } } } } } else { if (!m_clientCallCancelled) { // Call timed out. m_currentCall.CancelNotRequiredCallLegs(CallCancelCause.TimedOut); result = DialPlanAppResult.TimedOut; } } if (m_clientCallCancelled) { Log("Dial command was halted by cancellation of client call after " + DateTime.Now.Subtract(startTime).TotalSeconds.ToString("#.00") + "s."); m_executingScript.StopExecution(); } return result; } catch (ThreadAbortException) { return DialPlanAppResult.Unknown; } catch (Exception excp) { logger.Error("Exception DialPlanScriptFacade Dial. " + excp.Message); return DialPlanAppResult.Error; } } }
/// <summary> /// New transaction ACK requests are for 2xx responses, i.e. INVITE accepted and dialogue being created. /// </summary> /// <remarks> /// From RFC 3261 Chapter 17.1.1.3 - ACK for non-2xx final responses /// /// IMPORTANT: /// an ACK for a non-2xx response will also have the same branch ID as the INVITE whose response it acknowledges. /// /// The ACK request constructed by the client transaction MUST contain /// values for the Call-ID, From, and Request-URI that are equal to the /// values of those header fields in the request passed to the transport /// by the client transaction (call this the "original request"). The To /// header field in the ACK MUST equal the To header field in the /// response being acknowledged, and therefore will usually differ from /// the To header field in the original request by the addition of the /// tag parameter. The ACK MUST contain a single Via header field, and /// this MUST be equal to the top Via header field of the original /// request. The CSeq header field in the ACK MUST contain the same /// value for the sequence number as was present in the original request, /// but the method parameter MUST be equal to "ACK". /// /// If the INVITE request whose response is being acknowledged had Route /// header fields, those header fields MUST appear in the ACK. This is /// to ensure that the ACK can be routed properly through any downstream /// stateless proxies. /// /// From RFC 3261 Chapter 13.2.2.4 - ACK for 2xx final responses /// /// IMPORTANT: /// an ACK for a 2xx final response is a new transaction and has a new branch ID. /// /// The UAC core MUST generate an ACK request for each 2xx received from /// the transaction layer. The header fields of the ACK are constructed /// in the same way as for any request sent within a dialog (see Section /// 12) with the exception of the CSeq and the header fields related to /// authentication. The sequence number of the CSeq header field MUST be /// the same as the INVITE being acknowledged, but the CSeq method MUST /// be ACK. The ACK MUST contain the same credentials as the INVITE. If /// the 2xx contains an offer (based on the rules above), the ACK MUST /// carry an answer in its body. If the offer in the 2xx response is not /// acceptable, the UAC core MUST generate a valid answer in the ACK and /// then send a BYE immediately. /// </remarks> private SIPRequest GetNewTransactionACKRequest(SIPResponse sipResponse, SIPURI ackURI, SIPEndPoint localSIPEndPoint) { SIPRequest ackRequest = new SIPRequest(SIPMethodsEnum.ACK, ackURI.ToString()); ackRequest.LocalSIPEndPoint = localSIPEndPoint; SIPHeader header = new SIPHeader(TransactionRequest.Header.From, sipResponse.Header.To, sipResponse.Header.CSeq, sipResponse.Header.CallId); header.CSeqMethod = SIPMethodsEnum.ACK; header.AuthenticationHeader = TransactionRequest.Header.AuthenticationHeader; header.ProxySendFrom = base.TransactionRequest.Header.ProxySendFrom; if (sipResponse.Header.RecordRoutes != null) { header.Routes = sipResponse.Header.RecordRoutes.Reversed(); } ackRequest.Header = header; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId()); ackRequest.Header.Vias.PushViaHeader(viaHeader); return ackRequest; }
public static List<SIPContactHeader> CreateSIPContactList(SIPURI sipURI) { List<SIPContactHeader> contactHeaderList = new List<SIPContactHeader>(); contactHeaderList.Add(new SIPContactHeader(null, sipURI)); return contactHeaderList; }
public SIPRequest GetRequest(SIPMethodsEnum method, SIPURI uri) { return GetRequest(method, uri, new SIPToHeader(null, uri, null), null); }
public SIPRoute(SIPURI uri, bool looseRouter) { m_userField = new SIPUserField(); m_userField.URI = uri; this.IsStrictRouter = !looseRouter; }
public SIPDNSLookupResult GetURIEndPoint(SIPURI uri, bool async) { return ResolveSIPEndPoint_External(uri, async); }
public SIPEventDialogInfo(int version, SIPEventDialogInfoStateEnum state, SIPURI entity) { Version = version; State = state; Entity = entity.CopyOf(); }
public SIPContactHeader(string contactName, SIPURI contactURI) { m_userField = new SIPUserField(contactName, contactURI, null); }
private SIPRequest GetInviteRequest(SIPDialogue dialogue, SIPEndPoint localSIPEndPoint, string body) { SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, dialogue.RemoteTarget); SIPHeader inviteHeader = new SIPHeader(SIPFromHeader.ParseFromHeader(dialogue.LocalUserField.ToString()), SIPToHeader.ParseToHeader(dialogue.RemoteUserField.ToString()), dialogue.CSeq, dialogue.CallId); SIPURI contactURI = new SIPURI(dialogue.RemoteTarget.Scheme, localSIPEndPoint); inviteHeader.Contact = SIPContactHeader.ParseContactHeader("<" + contactURI.ToString() + ">"); inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE; inviteRequest.Header = inviteHeader; inviteRequest.Header.Routes = dialogue.RouteSet; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId()); inviteRequest.Header.Vias.PushViaHeader(viaHeader); inviteRequest.Body = body; inviteRequest.Header.ContentLength = body.Length; inviteRequest.Header.ContentType = "application/sdp"; return inviteRequest; }
public SIPRoute(SIPURI uri) { m_userField = new SIPUserField(); m_userField.URI = uri; }
private SIPRequest GetByeRequest(SIPResponse inviteResponse, SIPURI byeURI, SIPEndPoint localSIPEndPoint) { SIPRequest byeRequest = new SIPRequest(SIPMethodsEnum.BYE, byeURI); byeRequest.LocalSIPEndPoint = localSIPEndPoint; SIPFromHeader byeFromHeader = inviteResponse.Header.From; SIPToHeader byeToHeader = inviteResponse.Header.To; int cseq = inviteResponse.Header.CSeq + 1; SIPHeader byeHeader = new SIPHeader(byeFromHeader, byeToHeader, cseq, inviteResponse.Header.CallId); byeHeader.CSeqMethod = SIPMethodsEnum.BYE; byeHeader.ProxySendFrom = m_serverTransaction.TransactionRequest.Header.ProxySendFrom; byeRequest.Header = byeHeader; byeRequest.Header.Routes = (inviteResponse.Header.RecordRoutes != null) ? inviteResponse.Header.RecordRoutes.Reversed() : null; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId()); byeRequest.Header.Vias.PushViaHeader(viaHeader); return byeRequest; }
public SIPFromHeader(string fromName, SIPURI fromURI, string fromTag) { m_userField = new SIPUserField(fromName, fromURI, null); FromTag = fromTag; }
public static SIPURI ParseSIPURI(string uri) { try { SIPURI sipURI = new SIPURI(); if (String.IsNullOrEmpty(uri)) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "A SIP URI cannot be parsed from an empty string."); } else { if (uri == m_sipRegisterRemoveAll) { sipURI.Host = m_sipRegisterRemoveAll; } else { int colonPosn = uri.IndexOf(SCHEME_ADDR_SEPARATOR); if (colonPosn == -1) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "SIP URI did not contain compulsory colon"); } else { try { sipURI.Scheme = SIPSchemesType.GetSchemeType(uri.Substring(0, colonPosn)); } catch { throw new SIPValidationException(SIPValidationFieldsEnum.URI, SIPResponseStatusCodesEnum.UnsupportedURIScheme, "SIP scheme " + uri.Substring(0, colonPosn) + " was not understood"); } string uriHostPortion = uri.Substring(colonPosn + 1); int ampPosn = uriHostPortion.IndexOf(USER_HOST_SEPARATOR); int paramHeaderPosn = -1; if (ampPosn != -1) { paramHeaderPosn = uriHostPortion.IndexOfAny(new char[] { PARAM_TAG_DELIMITER, HEADER_START_DELIMITER }, ampPosn); } else { // Host only SIP URI. paramHeaderPosn = uriHostPortion.IndexOfAny(new char[] { PARAM_TAG_DELIMITER, HEADER_START_DELIMITER }); } if (ampPosn != -1 && paramHeaderPosn != -1) { sipURI.User = uriHostPortion.Substring(0, ampPosn); sipURI.Host = uriHostPortion.Substring(ampPosn + 1, paramHeaderPosn - ampPosn - 1); string paramsAndHeaders = uriHostPortion.Substring(paramHeaderPosn); sipURI.ParseParamsAndHeaders(paramsAndHeaders); } else if (ampPosn == -1 && paramHeaderPosn == 0) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "No Host portion in SIP URI"); } else if (ampPosn == -1 && paramHeaderPosn != -1) { sipURI.Host = uriHostPortion.Substring(0, paramHeaderPosn); string paramsAndHeaders = uriHostPortion.Substring(paramHeaderPosn); sipURI.ParseParamsAndHeaders(paramsAndHeaders); } else if (ampPosn != -1) { sipURI.User = uriHostPortion.Substring(0, ampPosn); sipURI.Host = uriHostPortion.Substring(ampPosn + 1, uriHostPortion.Length - ampPosn - 1); } else { sipURI.Host = uriHostPortion; } if (sipURI.Host.IndexOfAny(m_invalidSIPHostChars) != -1) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "The SIP URI host portion contained an invalid character."); } else if (sipURI.Host.IndexOf(':') != sipURI.Host.LastIndexOf(':')) { // If the host contains multiple ':' characters then it must be an IPv6 address which require a start '[' and and end ']'. if (sipURI.Host.ToCharArray()[0] != '[') { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "The SIP URI host portion contained an IPv6 address that was missing the start '['."); } else if (!sipURI.Host.EndsWith("]") && (sipURI.Host.ToCharArray().Length < sipURI.Host.LastIndexOf(':') + 1 || sipURI.Host.ToCharArray()[sipURI.Host.LastIndexOf(':') - 1] != ']')) { throw new SIPValidationException(SIPValidationFieldsEnum.URI, "The SIP URI host portion contained an IPv6 address that was missing the end ']'."); } //rj2: apply robustness principle mentioned in RFC 5118 4.10 while (sipURI.Host.Contains(":::")) { sipURI.Host = sipURI.Host.Replace(":::", "::"); } } } } return(sipURI); } } catch (SIPValidationException) { throw; } catch (Exception excp) { logger.LogError("Exception ParseSIPURI (URI=" + uri + "). " + excp.Message); throw new SIPValidationException(SIPValidationFieldsEnum.URI, "Unknown error parsing SIP URI."); } }
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); } }
/// <summary> /// Processes an in dialogue REFER request that specifies a new destination for an existing call leg. /// </summary> /// <param name="username">The username of the user the transfer is being processed for.</param> /// <param name="referTo">The Refer-To header URI from the REFER request.</param> /// <param name="dialplanName">The dialplan to use to process the transfer.</param> /// <param name="replacesCallID">The call ID that is being replaced by the new dialogue if one is created.</param> /// <returns>A SIP server user agent.</returns> public ISIPServerUserAgent BlindTransfer(string username, SIPURI referTo, string dialplanName, SIPDialogue replacesDialogue) { if (dialplanName.IsNullOrBlank()) { throw new ApplicationException("A dial plan name must be provided when processing a blind transfer."); } else if (referTo == null) { throw new ApplicationException("The refer to URI cannot be empty when processing a blind transfer."); } else if (replacesDialogue == null) { throw new ApplicationException("The blind transfer could not be initiated, the dialogue to transfer could not be found."); } //bool wasExecutionCountIncremented = false; Customer customer = null; SIPDialPlan dialPlan = null; try { customer = m_customerPersistor.Get(c => c.CustomerUsername == username); if (customer == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Blind transfer using dialplan " + dialplanName + " rejected for " + username + " and " + referTo.ToString() + ", as no matching user.", username)); throw new ApplicationException("No matching user was found, the blind transfer was not initiated."); } else if (customer.Suspended) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Blind transfer using dialplan " + dialplanName + " rejected for " + username + " and " + referTo.ToString() + ", user account is suspended.", username)); throw new ApplicationException("The user's account is suspended, the blind transfer was not initiated."); } else { dialPlan = GetDialPlan_External(d => d.Owner == username && d.DialPlanName == dialplanName); if (dialPlan == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Blind transfer rejected as no " + dialplanName + " dialplan exists.", username)); throw new ApplicationException("The blind transfer could not be initiated, no dialplan with name " + dialplanName + " could be found."); } else { if (!IsDialPlanExecutionAllowed(dialPlan, customer)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Execution of blind transfer for dialplan " + dialplanName + " was not processed as maximum execution count has been reached.", username)); throw new ApplicationException("The blind transfer was not initiated, dial plan execution exceeded maximum allowed"); } else { //IncrementCustomerExecutionCount(customer); Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Blind transfer for dialplan " + dialplanName + " starting for " + referTo.ToString() + ".", username)); SIPDialogue oppositeDialogue = m_sipDialogueManager.GetOppositeDialogue(replacesDialogue); ISIPServerUserAgent uas = new SIPTransferServerUserAgent(Log_External, m_sipDialogueManager.DialogueTransfer, m_sipTransport, m_outboundProxy, replacesDialogue, oppositeDialogue, referTo.ToString(), customer.CustomerUsername, customer.AdminId); DialPlanScriptContext scriptContext = new DialPlanScriptContext( Log_External, m_sipTransport, CreateDialogueBridge, m_outboundProxy, uas, dialPlan, GetSIPProviders_External(p => p.Owner == username, null, 0, Int32.MaxValue), m_traceDirectory, null, customer, null, GetCanonicalDomain_External); //scriptContext.DialPlanComplete += () => { DecrementCustomerExecutionCount(customer); }; m_dialPlanEngine.Execute(scriptContext, uas, SIPCallDirection.Out, CreateDialogueBridge, this); return uas; } } } } catch (ApplicationException) { throw; } catch (Exception excp) { logger.Error("Exception SIPCallManager BlindTransfer. " + excp.Message); //if (wasExecutionCountIncremented) //{ //DecrementDialPlanExecutionCount(dialPlan, customer.Id, originalExecutionCount); //DecrementCustomerExecutionCount(customer); //} throw; } }
/// <summary> /// Attempts a lookup from cache. /// </summary> /// <param name="uri"></param> /// <param name="startQuery"></param> /// <param name="preferIPv6"></param> /// <returns></returns> private static SIPEndPoint SIPLookupFromCache( SIPURI uri, QueryType startQuery, bool preferIPv6) { SIPEndPoint result = null; QueryType queryType = startQuery; string host = uri.MAddrOrHostAddress; int port = SIPConstants.GetDefaultPort(uri.Protocol); if (ushort.TryParse(uri.HostPort, out var uriPort)) { port = uriPort; } bool isDone = false; while (!isDone) { switch (queryType) { case QueryType.SRV: var srvProtocol = SIPServices.GetSRVProtocolForSIPURI(uri); string serviceHost = DnsQueryExtensions.ConcatServiceName(uri.MAddrOrHostAddress, uri.Scheme.ToString(), srvProtocol.ToString()); var srvResult = _lookupClient.QueryCache(serviceHost, QueryType.SRV); (var srvHost, var srvPort) = GetHostAndPortFromSrvResult(srvResult); if (srvHost != null) { host = srvHost; port = srvPort != 0 ? srvPort : port; } queryType = preferIPv6 ? QueryType.AAAA : QueryType.A; break; case QueryType.AAAA: var aaaaResult = _lookupClient.QueryCache(host, UseANYLookups ? QueryType.ANY : QueryType.AAAA, QueryClass.IN); if (aaaaResult?.Answers?.Count > 0) { result = GetFromLookupResult(uri.Protocol, aaaaResult.Answers.OrderByDescending(x => x.RecordType).First(), port); isDone = true; } else { queryType = QueryType.A; } break; default: // A record lookup. var aResult = _lookupClient.QueryCache(host, QueryType.A, QueryClass.IN); if (aResult != null) { if (aResult.Answers?.Count > 0) { result = GetFromLookupResult(uri.Protocol, aResult.Answers.First(), port); } else { // We got a result back but it was empty indicating an unresolvable host or // some other DNS error condition. result = SIPEndPoint.Empty; } } isDone = true; break; } } return(result); }