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;
        }
Example #8
0
 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 + ".");
                }
            }
        }
Example #13
0
        private SIPProtocolsEnum GetRemoteTargetProtocol()
        {
            SIPURI dstURI = (RouteSet == null) ? RemoteTarget : RouteSet.TopRoute.URI;

            return(dstURI.Protocol);
        }
Example #14
0
 public SIPToHeader(string toName, SIPURI toURI, string toTag)
 {
     m_userField = new SIPUserField(toName, toURI, null);
     ToTag = toTag;
 }
Example #15
0
 public SIPParameterlessURI(SIPSchemesEnum scheme, string host, string user)
 {
     m_uri        = new SIPURI(user, host, null);
     m_uri.Scheme = scheme;
 }
Example #16
0
        /// <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);
            }
        }
Example #17
0
 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;
 }
Example #20
0
        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;
        }
Example #21
0
        private SIPEndPoint GetRemoteTargetEndpoint()
        {
            SIPURI dstURI = (RouteSet == null) ? RemoteTarget : RouteSet.TopRoute.URI;

            return(dstURI.ToSIPEndPoint());
        }
Example #22
0
        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 SIPParameterlessURI(SIPURI sipURI)
		{
            m_uri = sipURI;
		}
Example #25
0
        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.");
            }
        }
Example #26
0
        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;
        }
Example #27
0
 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;
            }
        }
Example #29
0
        /// <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;
            }
Example #31
0
        /// <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);
        }
Example #32
0
        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;
        }
Example #35
0
        public static List<SIPContactHeader> CreateSIPContactList(SIPURI sipURI)
        {
            List<SIPContactHeader> contactHeaderList = new List<SIPContactHeader>();
            contactHeaderList.Add(new SIPContactHeader(null, sipURI));

            return contactHeaderList;
        }
Example #36
0
 public SIPRequest GetRequest(SIPMethodsEnum method, SIPURI uri)
 {
     return GetRequest(method, uri, new SIPToHeader(null, uri, null), null);
 }
Example #37
0
 public SIPRoute(SIPURI uri, bool looseRouter)
 {
     m_userField = new SIPUserField();
     m_userField.URI = uri;
     this.IsStrictRouter = !looseRouter;
 }
Example #38
0
 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();
 }
Example #40
0
 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;
        }
Example #42
0
 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;
        }
Example #44
0
 public SIPFromHeader(string fromName, SIPURI fromURI, string fromTag)
 {
     m_userField = new SIPUserField(fromName, fromURI, null);
     FromTag = fromTag;
 }
Example #45
0
        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);
     }
 }
Example #47
0
        /// <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;
            }
        }
 public SIPParameterlessURI(SIPSchemesEnum scheme, string host, string user)
 {
     m_uri = new SIPURI(user, host, null);
     m_uri.Scheme = scheme;
 }
Example #49
0
        /// <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);
        }