示例#1
0
        public SIPDialogue(
            string callId,
            SIPRouteSet routeSet,
            SIPUserField localUser,
            SIPUserField remoteUser,
            int cseq,
            SIPURI remoteTarget,
            string localTag,
            string remoteTag,
            Guid cdrId,
            string owner,
            string adminMemberId,
            string sdp,
            string remoteSDP)
        {
            Id = Guid.NewGuid();

            CallId          = callId;
            RouteSet        = routeSet;
            LocalUserField  = localUser;
            LocalTag        = localTag;
            RemoteUserField = remoteUser;
            RemoteTag       = remoteTag;
            CSeq            = cseq;
            RemoteTarget    = remoteTarget;
            CDRId           = cdrId;
            Owner           = owner;
            AdminMemberId   = adminMemberId;
            SDP             = sdp;
            RemoteSDP       = remoteSDP;
            Inserted        = DateTimeOffset.UtcNow;
            Direction       = SIPCallDirection.None;
        }
示例#2
0
        public SIPDialogue(
            string callId,
            SIPRouteSet routeSet,
            SIPUserField localUser,
            SIPUserField remoteUser,
            int cseq,
            SIPURI remoteTarget,
            string localTag,
            string remoteTag,
            Guid cdrId,
            string sdp,
            string remoteSDP,
            SIPEndPoint remoteEndPoint)
        {
            Id = Guid.NewGuid();

            CallId            = callId;
            RouteSet          = routeSet;
            LocalUserField    = localUser;
            LocalTag          = localTag;
            RemoteUserField   = remoteUser;
            RemoteTag         = remoteTag;
            CSeq              = cseq;
            RemoteTarget      = remoteTarget;
            CDRId             = cdrId;
            SDP               = sdp;
            RemoteSDP         = remoteSDP;
            Inserted          = DateTime.UtcNow;
            Direction         = SIPCallDirection.None;
            RemoteSIPEndPoint = remoteEndPoint?.CopyOf();
        }
示例#3
0
        //public Dictionary<Guid, object> Load(XmlDocument dom)
        //{
        //    return SIPAssetXMLPersistor<SIPDialogueAsset>.LoadAssetsFromXMLRecordSet(dom);
        //}
#endif

        public void Load(XElement dialogueElement)
        {
            SIPDialogue                = new SIPDialogue();
            SIPDialogue.Id             = new Guid(dialogueElement.Element("id").Value);
            SIPDialogue.Owner          = dialogueElement.Element("owner").Value;
            SIPDialogue.AdminMemberId  = dialogueElement.Element("adminmemberid").Value;
            SIPDialogue.LocalTag       = dialogueElement.Element("localtag").Value;
            SIPDialogue.RemoteTag      = dialogueElement.Element("remotetag").Value;
            SIPDialogue.LocalUserField =
                SIPUserField.ParseSIPUserField(dialogueElement.Element("localuserfield").Value);
            SIPDialogue.RemoteUserField =
                SIPUserField.ParseSIPUserField(dialogueElement.Element("remoteuserfield").Value);
            SIPDialogue.CallId       = dialogueElement.Element("callid").Value;
            SIPDialogue.CSeq         = Convert.ToInt32(dialogueElement.Element("cseq").Value);
            SIPDialogue.BridgeId     = new Guid(dialogueElement.Element("bridgeid").Value);
            SIPDialogue.RemoteTarget = SIPURI.ParseSIPURI(dialogueElement.Element("remotetarget").Value);
            SIPDialogue.RouteSet     =
                (dialogueElement.Element("routeset") != null &&
                 !dialogueElement.Element("routeset").Value.IsNullOrBlank())
                    ? SIPRouteSet.ParseSIPRouteSet(dialogueElement.Element("routeset").Value)
                    : null;
            SIPDialogue.ProxySendFrom = (dialogueElement.Element("proxysipsocket") != null)
                ? dialogueElement.Element("proxysipsocket").Value
                : null;
            SIPDialogue.CDRId             = new Guid(dialogueElement.Element("cdrid").Value);
            SIPDialogue.CallDurationLimit = (dialogueElement.Element("calldurationlimit") != null)
                ? Convert.ToInt32(dialogueElement.Element("calldurationlimit").Value)
                : 0;
            SIPDialogue.Direction = (dialogueElement.Element("direction") != null)
                ? (SIPCallDirection)Enum.Parse(typeof(SIPCallDirection), dialogueElement.Element("direction").Value,
                                               true)
                : SIPCallDirection.None;
            Inserted     = DateTimeOffset.Parse(dialogueElement.Element("inserted").Value);
            TransferMode = dialogueElement.Element("transfermode").Value;
            SDP          = dialogueElement.Element("sdp").Value;
            RemoteSDP    = dialogueElement.Element("remotesdp").Value;
            //SIPDialogue.SwitchboardCallerDescription = (dialogueElement.Element("switchboardcallerdescription") != null) ? dialogueElement.Element("switchboardcallerdescription").Value : null;
            //SIPDialogue.SwitchboardDescription = (dialogueElement.Element("switchboarddescription") != null) ? dialogueElement.Element("switchboarddescription").Value : null;
            SIPDialogue.SwitchboardOwner = (dialogueElement.Element("switchboardowner") != null)
                ? dialogueElement.Element("switchboardowner").Value
                : null;
            SIPDialogue.SwitchboardLineName = (dialogueElement.Element("switchboardlinename") != null)
                ? dialogueElement.Element("switchboardlinename").Value
                : null;
            SIPDialogue.CRMPersonName = (dialogueElement.Element("crmpersonname") != null)
                ? dialogueElement.Element("crmpersonname").Value
                : null;
            SIPDialogue.CRMCompanyName = (dialogueElement.Element("crmcompanyname") != null)
                ? dialogueElement.Element("crmcompanyname").Value
                : null;
            SIPDialogue.CRMPictureURL = (dialogueElement.Element("crmpictureurl") != null)
                ? dialogueElement.Element("crmpictureurl").Value
                : null;
        }
示例#4
0
 public void Load(DataRow row)
 {
     SIPDialogue                 = new SIPDialogue();
     SIPDialogue.Id              = new Guid(row["id"] as string);
     SIPDialogue.Owner           = row["owner"] as string;
     SIPDialogue.AdminMemberId   = row["adminmemberid"] as string;
     SIPDialogue.LocalTag        = row["localtag"] as string;
     SIPDialogue.RemoteTag       = row["remotetag"] as string;
     SIPDialogue.LocalUserField  = SIPUserField.ParseSIPUserField(row["localuserfield"] as string);
     SIPDialogue.RemoteUserField = SIPUserField.ParseSIPUserField(row["remoteuserfield"] as string);
     SIPDialogue.CallId          = row["callid"] as string;
     SIPDialogue.CSeq            = Convert.ToInt32(row["cseq"]);
     SIPDialogue.BridgeId        = new Guid(row["bridgeid"] as string);
     SIPDialogue.RemoteTarget    = SIPURI.ParseSIPURI(row["remotetarget"] as string);
     SIPDialogue.RouteSet        =
         (row["routeset"] != null && row["routeset"] != DBNull.Value &&
          !(row["routeset"] as string).IsNullOrBlank())
             ? SIPRouteSet.ParseSIPRouteSet(row["routeset"] as string)
             : null;
     SIPDialogue.ProxySendFrom = (row["proxysipsocket"] != null && row["proxysipsocket"] != DBNull.Value)
         ? row["proxysipsocket"] as string
         : null;
     SIPDialogue.CDRId             = new Guid(row["cdrid"] as string);
     SIPDialogue.CallDurationLimit =
         (row["calldurationlimit"] != null && row["calldurationlimit"] != DBNull.Value)
             ? Convert.ToInt32(row["calldurationlimit"])
             : 0;
     SIPDialogue.Direction = (row["direction"] != null)
         ? (SIPCallDirection)Enum.Parse(typeof(SIPCallDirection), row["direction"] as string, true)
         : SIPCallDirection.None;
     Inserted     = DateTimeOffset.Parse(row["inserted"] as string);
     TransferMode = row["transfermode"] as string;
     SDP          = row["sdp"] as string;
     RemoteSDP    = row["remotesdp"] as string;
     //SIPDialogue.SwitchboardCallerDescription = (row["switchboardcallerdescription"] != null && row["switchboardcallerdescription"] != DBNull.Value) ? row["switchboardcallerdescription"] as string : null;
     //SIPDialogue.SwitchboardDescription = (row["switchboarddescription"] != null && row["switchboarddescription"] != DBNull.Value) ? row["switchboarddescription"] as string : null;
     SIPDialogue.SwitchboardOwner = (row["switchboardowner"] != null && row["switchboardowner"] != DBNull.Value)
         ? row["switchboardowner"] as string
         : null;
     SIPDialogue.SwitchboardLineName =
         (row["switchboardlinename"] != null && row["switchboardlinename"] != DBNull.Value)
             ? row["switchboardlinename"] as string
             : null;
     SIPDialogue.CRMPersonName = (row["crmpersonname"] != null && row["crmpersonname"] != DBNull.Value)
         ? row["crmpersonname"] as string
         : null;
     SIPDialogue.CRMCompanyName = (row["crmcompanyname"] != null && row["crmcompanyname"] != DBNull.Value)
         ? row["crmcompanyname"] as string
         : null;
     SIPDialogue.CRMPictureURL = (row["crmpictureurl"] != null && row["crmpictureurl"] != DBNull.Value)
         ? row["crmpictureurl"] as string
         : null;
 }
示例#5
0
        public void ParseSIPRouteSetTest()
        {
            Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name);

            string      routeSetString = "<sip:127.0.0.1:5434;lr>,<sip:10.0.0.1>,<sip:192.168.0.1;ftag=12345;lr=on>";
            SIPRouteSet routeSet       = SIPRouteSet.ParseSIPRouteSet(routeSetString);

            Console.WriteLine(routeSet.ToString());

            Assert.IsTrue(routeSet.Length == 3, "The parsed route set had an incorrect length.");
            Assert.IsTrue(routeSet.ToString() == routeSetString, "The parsed route set did not produce the same string as the original parsed value.");
            SIPRoute topRoute = routeSet.PopRoute();

            Assert.IsTrue(topRoute.Host == "127.0.0.1:5434", "The first route host was not parsed correctly.");
            Assert.IsFalse(topRoute.IsStrictRouter, "The first route host was not correctly recognised as a loose router.");
            topRoute = routeSet.PopRoute();
            Assert.IsTrue(topRoute.Host == "10.0.0.1", "The second route host was not parsed correctly.");
            Assert.IsTrue(topRoute.IsStrictRouter, "The second route host was not correctly recognised as a strict router.");
            topRoute = routeSet.PopRoute();
            Assert.IsTrue(topRoute.Host == "192.168.0.1", "The third route host was not parsed correctly.");
            Assert.IsFalse(topRoute.IsStrictRouter, "The third route host was not correctly recognised as a loose router.");
            Assert.IsTrue(topRoute.URI.Parameters.Get("ftag") == "12345", "The ftag parameter on the third route was not correctly parsed.");
        }
示例#6
0
        public SIPDialogue ToSIPDialogue()
        {
            SIPDialogue dialogue = new SIPDialogue();

            dialogue.Id                = ID;
            dialogue.CDRId             = CDRID.GetValueOrDefault();
            dialogue.LocalTag          = LocalTag;
            dialogue.RemoteTag         = RemoteTag;
            dialogue.CallId            = CallID;
            dialogue.CSeq              = CSeq;
            dialogue.BridgeId          = BridgeID;
            dialogue.RemoteTarget      = SIPURI.ParseSIPURIRelaxed(RemoteTarget);
            dialogue.LocalUserField    = SIPUserField.ParseSIPUserField(LocalUserField);
            dialogue.RemoteUserField   = SIPUserField.ParseSIPUserField(RemoteUserField);
            dialogue.ProxySendFrom     = ProxySendFrom;
            dialogue.RouteSet          = string.IsNullOrWhiteSpace(RouteSet) ? null : SIPRouteSet.ParseSIPRouteSet(RouteSet);
            dialogue.CallDurationLimit = CallDurationLimit.GetValueOrDefault();
            dialogue.Direction         = Enum.Parse <SIPCallDirection>(Direction, true);
            dialogue.Inserted          = Inserted;
            dialogue.RemoteSIPEndPoint = (RemoteSocket != null) ? SIPEndPoint.ParseSIPEndPoint(RemoteSocket) : null;

            return(dialogue);
        }
        private SIPRequest GetInviteRequest(SIPCallDescriptor sipCallDescriptor, string branchId, string callId, SIPRouteSet routeSet, string content, string contentType)
        {
            SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, sipCallDescriptor.Uri);

            SIPHeader inviteHeader = new SIPHeader(sipCallDescriptor.GetFromHeader(), SIPToHeader.ParseToHeader(sipCallDescriptor.To), 1, callId);

            inviteHeader.From.FromTag = CallProperties.CreateNewTag();

            inviteHeader.Contact = new List <SIPContactHeader>()
            {
                SIPContactHeader.GetDefaultSIPContactHeader(inviteRequest.URI.Scheme)
            };
            inviteHeader.Contact[0].ContactURI.User = sipCallDescriptor.Username;
            inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE;
            inviteHeader.UserAgent  = SIPConstants.SipUserAgentVersionString;
            inviteHeader.Routes     = routeSet;
            inviteHeader.Supported  = SIPExtensionHeaders.REPLACES + ", " + SIPExtensionHeaders.NO_REFER_SUB
                                      + ((PrackSupported == true) ? ", " + SIPExtensionHeaders.PRACK : "");

            inviteRequest.Header = inviteHeader;

            if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
            {
                inviteHeader.ProxySendFrom = sipCallDescriptor.ProxySendFrom;
            }

            SIPViaHeader viaHeader = new SIPViaHeader(new IPEndPoint(IPAddress.Any, 0), branchId);

            inviteRequest.Header.Vias.PushViaHeader(viaHeader);

            inviteRequest.Body = content;
            inviteRequest.Header.ContentLength = (inviteRequest.Body != null) ? inviteRequest.Body.Length : 0;
            inviteRequest.Header.ContentType   = contentType;

            try
            {
                if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0)
                {
                    foreach (string customHeader in sipCallDescriptor.CustomHeaders)
                    {
                        if (customHeader.IsNullOrBlank())
                        {
                            continue;
                        }
                        else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT))
                        {
                            inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim();
                        }
                        else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_TO + ":"))
                        {
                            var customToHeader = SIPUserField.ParseSIPUserField(customHeader.Substring(customHeader.IndexOf(":") + 1).Trim());
                            if (customToHeader != null)
                            {
                                inviteRequest.Header.To.ToUserField = customToHeader;
                            }
                        }
                        else
                        {
                            inviteRequest.Header.UnknownHeaders.Add(customHeader);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders);
            }

            if (AdjustInvite != null)
            {
                inviteRequest = AdjustInvite(inviteRequest);
            }

            return(inviteRequest);
        }
        /// <summary>
        /// Initiates the call to the remote user agent server.
        /// </summary>
        /// <param name="sipCallDescriptor">The descriptor for the call that describes how to reach the user agent server and other properties.</param>
        /// <param name="serverEndPoint">Optional. If the server end point for the call is known or has been resolved in advance. If
        /// not set the SIP transport layer will attempt to resolve the destination at sending time.</param>
        public SIPRequest Call(SIPCallDescriptor sipCallDescriptor, SIPEndPoint serverEndPoint)
        {
            try
            {
                m_sipCallDescriptor = sipCallDescriptor;
                SIPURI      callURI  = SIPURI.ParseSIPURI(sipCallDescriptor.Uri);
                SIPRouteSet routeSet = null;

                logger.LogDebug($"UAC commencing call to {SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress}.");

                // A custom route set may have been specified for the call.
                if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1)
                {
                    try
                    {
                        routeSet = new SIPRouteSet();
                        routeSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true));
                    }
                    catch
                    {
                        logger.LogDebug("Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + m_sipCallDescriptor.RouteSet + ".");
                    }
                }

                string content = sipCallDescriptor.Content;

                if (content.IsNullOrBlank())
                {
                    logger.LogDebug("Body on UAC call was empty.");
                }

                if (this.m_sipCallDescriptor.BranchId.IsNullOrBlank())
                {
                    this.m_sipCallDescriptor.BranchId = CallProperties.CreateBranchId();
                }

                if (this.m_sipCallDescriptor.CallId.IsNullOrBlank())
                {
                    this.m_sipCallDescriptor.CallId = CallProperties.CreateNewCallId();
                }

                SIPRequest inviteRequest = GetInviteRequest(m_sipCallDescriptor, m_sipCallDescriptor.BranchId, m_sipCallDescriptor.CallId, routeSet, content, sipCallDescriptor.ContentType);

                // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call.
                m_serverTransaction = new UACInviteTransaction(m_sipTransport, inviteRequest, m_outboundProxy);

                m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived;
                m_serverTransaction.UACInviteTransactionFinalResponseReceived       += ServerFinalResponseReceived;
                m_serverTransaction.UACInviteTransactionFailed += ServerTransactionFailed;

                m_serverTransaction.SendInviteRequest();

                return(inviteRequest);
            }
            catch (ApplicationException appExcp)
            {
                m_serverTransaction?.CancelCall(appExcp.Message);
                CallFailed?.Invoke(this, appExcp.Message, null);
                return(null);
            }
            catch (Exception excp)
            {
                logger.LogError("Exception UserAgentClient Call. " + excp);
                m_serverTransaction?.CancelCall("Unknown exception");
                CallFailed?.Invoke(this, excp.Message, null);
                return(null);
            }
        }
        /// <summary>
        /// Gets the destination of the remote SIP end point for this call.
        /// </summary>
        /// <param name="sipCallDescriptor">The call descriptor containing the settings to use to place the call.</param>
        /// <returns>The server end point for the call.</returns>
        public async Task <SIPEndPoint> GetCallDestination(SIPCallDescriptor sipCallDescriptor)
        {
            SIPURI      callURI        = SIPURI.ParseSIPURI(sipCallDescriptor.Uri);
            SIPEndPoint serverEndPoint = null;

            // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
            if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
            {
                serverEndPoint = m_outboundProxy;
            }
            else if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
            {
                // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                //SIPEndPoint outboundProxyEndPoint = SIPEndPoint.ParseSIPEndPoint(sipCallDescriptor.ProxySendFrom);
                //m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, outboundProxyEndPoint.Address, SIPConstants.DEFAULT_SIP_PORT);
                //m_serverEndPoint = m_outboundProxy;
                m_outboundProxy = SIPEndPoint.ParseSIPEndPoint(sipCallDescriptor.ProxySendFrom);
                serverEndPoint  = m_outboundProxy;
                logger.LogDebug($"SIPClientUserAgent Call using alternate outbound proxy of {serverEndPoint}.");
            }
            else if (m_outboundProxy != null)
            {
                // Using the system outbound proxy only, no additional user routing requirements.
                serverEndPoint = m_outboundProxy;
            }

            // No outbound proxy, determine the forward destination based on the SIP request.
            if (serverEndPoint == null)
            {
                //SIPDNSLookupResult lookupResult = null;
                SIPEndPoint lookupResult = null;
                double      lookupDurationMilliseconds = 0;

                if (sipCallDescriptor.RouteSet != null && sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1)
                {
                    var routeSet = new SIPRouteSet();
                    routeSet.PushRoute(new SIPRoute(sipCallDescriptor.RouteSet, true));
                    logger.LogDebug("Route set for call " + routeSet.ToString() + ".");
                    //lookupResult = m_sipTransport.GetURIEndPoint(routeSet.TopRoute.URI, false);
                    lookupResult = await m_sipTransport.ResolveSIPUriAsync(routeSet.TopRoute.URI).ConfigureAwait(false);
                }
                else
                {
                    logger.LogDebug("SIPClientUserAgent attempting to resolve " + callURI.Host + ".");
                    //lookupResult = m_sipTransport.GetURIEndPoint(callURI, false);
                    DateTime lookupStartedAt = DateTime.Now;
                    lookupResult = await m_sipTransport.ResolveSIPUriAsync(callURI).ConfigureAwait(false);

                    lookupDurationMilliseconds = DateTime.Now.Subtract(lookupStartedAt).TotalMilliseconds;
                }

                if (lookupResult == null)
                {
                    logger.LogDebug($"SIPClientUserAgent DNS failure resolving {callURI.Host} in {lookupDurationMilliseconds:0.##}ms. Call cannot proceed.");
                }
                else
                {
                    logger.LogDebug($"SIPClientUserAgent resolved {callURI.Host} to {lookupResult} in {lookupDurationMilliseconds:0.##}ms.");
                    serverEndPoint = lookupResult;
                }
            }

            return(serverEndPoint);
        }
示例#10
0
        //private void ByeFinalResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse)
        //{
        //    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "BYE response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + ".", Owner));
        //}
        private SIPRequest GetInviteRequest(SIPCallDescriptor sipCallDescriptor, string branchId, string callId, SIPEndPoint localSIPEndPoint, SIPRouteSet routeSet, string content, string contentType)
        {
            SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, sipCallDescriptor.Uri);
            inviteRequest.LocalSIPEndPoint = localSIPEndPoint;

            SIPHeader inviteHeader = new SIPHeader(sipCallDescriptor.GetFromHeader(), SIPToHeader.ParseToHeader(sipCallDescriptor.To), 1, callId);

            inviteHeader.From.FromTag = CallProperties.CreateNewTag();

            // For incoming calls forwarded via the dial plan the username needs to go into the Contact header.
            inviteHeader.Contact = new List<SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(inviteRequest.URI.Scheme, localSIPEndPoint)) };
            inviteHeader.Contact[0].ContactURI.User = sipCallDescriptor.Username;
            inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE;
            inviteHeader.UserAgent = m_userAgent;
            inviteHeader.Routes = routeSet;
            inviteRequest.Header = inviteHeader;

            if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
            {
                inviteHeader.ProxySendFrom = sipCallDescriptor.ProxySendFrom;
            }

            SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, branchId);
            inviteRequest.Header.Vias.PushViaHeader(viaHeader);

            inviteRequest.Body = content;
            inviteRequest.Header.ContentLength = (inviteRequest.Body != null) ? inviteRequest.Body.Length : 0;
            inviteRequest.Header.ContentType = contentType;

            // Add custom switchboard headers.
            if (CallDescriptor.SwitchboardHeaders != null)
            {
                inviteHeader.SwitchboardOriginalCallID = CallDescriptor.SwitchboardHeaders.SwitchboardOriginalCallID;
                //inviteHeader.SwitchboardCallerDescription = CallDescriptor.SwitchboardHeaders.SwitchboardCallerDescription;
                inviteHeader.SwitchboardLineName = CallDescriptor.SwitchboardHeaders.SwitchboardLineName;
                //inviteHeader.SwitchboardOwner = CallDescriptor.SwitchboardHeaders.SwitchboardOwner;
                //inviteHeader.SwitchboardOriginalFrom = CallDescriptor.SwitchboardHeaders.SwitchboardOriginalFrom;
            }

            // Add custom CRM headers.
            if (CallDescriptor.CRMHeaders != null)
            {
                inviteHeader.CRMPersonName = CallDescriptor.CRMHeaders.PersonName;
                inviteHeader.CRMCompanyName = CallDescriptor.CRMHeaders.CompanyName;
                inviteHeader.CRMPictureURL = CallDescriptor.CRMHeaders.AvatarURL;
            }

            try
            {
                if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0)
                {
                    foreach (string customHeader in sipCallDescriptor.CustomHeaders)
                    {
                        if (customHeader.IsNullOrBlank())
                        {
                            continue;
                        }
                        else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT))
                        {
                            inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim();
                        }
                        else
                        {
                            inviteRequest.Header.UnknownHeaders.Add(customHeader);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders);
            }

            return inviteRequest;
        }
示例#11
0
        public void Call(SIPCallDescriptor sipCallDescriptor)
        {
            try
            {
                m_sipCallDescriptor = sipCallDescriptor;
                SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri);
                SIPRouteSet routeSet = null;

                if (!m_callCancelled)
                {
                    // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                    if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                    {
                        m_serverEndPoint = m_outboundProxy;
                    }
                    else if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
                    {
                        // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                        SIPEndPoint outboundProxyEndPoint = SIPEndPoint.ParseSIPEndPoint(sipCallDescriptor.ProxySendFrom);
                        m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort));
                        m_serverEndPoint = m_outboundProxy;
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "SIPClientUserAgent Call using alternate outbound proxy of " + m_outboundProxy + ".", Owner));
                    }
                    else if (m_outboundProxy != null)
                    {
                        // Using the system outbound proxy only, no additional user routing requirements.
                        m_serverEndPoint = m_outboundProxy;
                    }

                    // A custom route set may have been specified for the call.
                    if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1)
                    {
                        try
                        {
                            routeSet = new SIPRouteSet();
                            routeSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true));
                        }
                        catch
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + m_sipCallDescriptor.RouteSet + ".", Owner));
                        }
                    }

                    // No outbound proxy, determine the forward destination based on the SIP request.
                    if (m_serverEndPoint == null)
                    {
                        SIPDNSLookupResult lookupResult = null;

                        if (routeSet == null || routeSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Attempting to resolve " + callURI.Host + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(callURI, false);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Route set for call " + routeSet.ToString() + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(routeSet.TopRoute.URI, false);
                        }

                        if (lookupResult.LookupError != null)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Call cannot proceed.", Owner));
                        }
                        else
                        {
                            m_serverEndPoint = lookupResult.GetSIPEndPoint();
                        }
                    }

                    if (m_callCancelled)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call was cancelled during DNS resolution of " + callURI.Host, Owner));
                        FireCallFailed(this, "Cancelled by caller");
                    }
                    else if (m_serverEndPoint != null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Switching to " + SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress + " via " + m_serverEndPoint + ".", Owner));

                        m_localSIPEndPoint = m_sipTransport.GetDefaultSIPEndPoint(m_serverEndPoint);
                        if (m_localSIPEndPoint == null)
                        {
                            throw new ApplicationException("The call could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + ".");
                        }

                        string content = sipCallDescriptor.Content;

                        if (content.IsNullOrBlank())
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Body on UAC call was empty.", Owner));
                        }
                        else if (m_sipCallDescriptor.ContentType == m_sdpContentType)
                        {
                            if (!m_sipCallDescriptor.MangleResponseSDP)
                            {
                                IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content);
                                if (sdpEndPoint != null)
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call was set to NOT mangle, RTP socket " + sdpEndPoint.ToString() + ".", Owner));
                                }
                                else
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call was set to NOT mangle, RTP socket could not be determined.", Owner));
                                }
                            }
                            else
                            {
                                IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content);
                                if (sdpEndPoint != null)
                                {
                                    if (!IPSocket.IsPrivateAddress(sdpEndPoint.Address.ToString()))
                                    {
                                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had public IP not mangled, RTP socket " + sdpEndPoint.ToString() + ".", Owner));
                                    }
                                    else
                                    {
                                        bool wasSDPMangled = false;
                                        if (sipCallDescriptor.MangleIPAddress != null)
                                        {
                                            if (sdpEndPoint != null)
                                            {
                                                content = SIPPacketMangler.MangleSDP(content, sipCallDescriptor.MangleIPAddress.ToString(), out wasSDPMangled);
                                            }
                                        }

                                        if (wasSDPMangled)
                                        {
                                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had RTP socket mangled from " + sdpEndPoint.ToString() + " to " + sipCallDescriptor.MangleIPAddress.ToString() + ":" + sdpEndPoint.Port + ".", Owner));
                                        }
                                        else if (sdpEndPoint != null)
                                        {
                                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC could not be mangled, using original RTP socket of " + sdpEndPoint.ToString() + ".", Owner));
                                        }
                                    }
                                }
                                else
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP RTP socket on UAC call could not be determined.", Owner));
                                }
                            }
                        }

                        SIPRequest switchServerInvite = GetInviteRequest(m_sipCallDescriptor, CallProperties.CreateBranchId(), CallProperties.CreateNewCallId(), m_localSIPEndPoint, routeSet, content, sipCallDescriptor.ContentType);

                        // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call.
                        m_serverTransaction = m_sipTransport.CreateUACTransaction(switchServerInvite, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy);
                        m_serverTransaction.CDR.DialPlanContextID = m_sipCallDescriptor.DialPlanContextID;

                        #region Real-time call control processing.

                        string rtccError = null;

                        if (m_serverTransaction.CDR != null)
                        {
                            m_serverTransaction.CDR.Owner = Owner;
                            m_serverTransaction.CDR.AdminMemberId = AdminMemberId;

                            m_serverTransaction.CDR.Updated();

            #if !SILVERLIGHT

                            if (m_sipCallDescriptor.AccountCode != null && RtccGetCustomer_External != null)
                            {
                                //var customerAccount = m_customerAccountDataLayer.CheckAccountCode(Owner, m_sipCallDescriptor.AccountCode);
                                var customerAccount = RtccGetCustomer_External(Owner, m_sipCallDescriptor.AccountCode);

                                if (customerAccount == null)
                                {
                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as no account exists for account code or number " + m_sipCallDescriptor.AccountCode + ".", Owner));
                                    rtccLogger.Debug("A billable call could not proceed as no account exists for account code or number " + m_sipCallDescriptor.AccountCode + " and owner " + Owner + ".");
                                    rtccError = "Real-time call control invalid account code";
                                }
                                else
                                {
                                    AccountCode = customerAccount.AccountCode;

                                    string rateDestination = m_sipCallDescriptor.Uri;
                                    if (SIPURI.TryParse(m_sipCallDescriptor.Uri))
                                    {
                                        rateDestination = SIPURI.ParseSIPURIRelaxed(m_sipCallDescriptor.Uri).User;
                                    }

                                    //var rate = m_customerAccountDataLayer.GetRate(Owner, m_sipCallDescriptor.RateCode, rateDestination, customerAccount.RatePlan);
                                    var rate = RtccGetRate_External(Owner, m_sipCallDescriptor.RateCode, rateDestination, customerAccount.RatePlan);

                                    if (rate == null)
                                    {
                                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as no rate could be determined for destination " + rateDestination + ".", Owner));
                                        rtccLogger.Debug("A billable call could not proceed as no rate could be determined for destination " + rateDestination + " and owner " + Owner + ".");
                                        rtccError = "Real-time call control no rate";
                                    }
                                    else
                                    {
                                        Rate = rate.RatePerIncrement;

                                        if (rate.RatePerIncrement == 0 && rate.SetupCost == 0)
                                        {
                                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "The rate and setup cost for the " + rateDestination + "were both zero. The call will be allowed to proceed with no RTCC reservation.", Owner));
                                        }
                                        else
                                        {
                                            //decimal balance = m_customerAccountDataLayer.GetBalance(AccountCode);
                                            decimal balance = RtccGetBalance_External(AccountCode);

                                            if (balance < Rate)
                                            {
                                                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as the available credit for " + AccountCode + " was not sufficient for 60 seconds to destination " + rateDestination + ".", Owner));
                                                rtccLogger.Debug("A billable call could not proceed as the available credit for " + AccountCode + " was not sufficient for 60 seconds to destination " + rateDestination + " and owner " + Owner + ".");
                                                rtccError = "Real-time call control insufficient credit";
                                            }
                                            else
                                            {
                                                int intialSeconds = 0;
                                                //var reservationCost = m_customerAccountDataLayer.ReserveInitialCredit(AccountCode, rate, m_serverTransaction.CDR, out intialSeconds);
                                                var reservationCost = RtccReserveInitialCredit_External(AccountCode, rate.ID, m_serverTransaction.CDR, out intialSeconds);

                                                if (reservationCost == Decimal.MinusOne)
                                                {
                                                    Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call will not proceed as the intial real-time call control credit reservation failed.", Owner));
                                                    rtccLogger.Debug("Call will not proceed as the intial real-time call control credit reservation failed for owner " + Owner + ".");
                                                    rtccError = "Real-time call control initial reservation failed";
                                                }
                                                else
                                                {
                                                    ReservedCredit = reservationCost;
                                                    ReservedSeconds = intialSeconds;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
            #endif

                        }

                        #endregion

                        if (rtccError == null)
                        {
                            m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived;
                            m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived;
                            m_serverTransaction.UACInviteTransactionTimedOut += ServerTimedOut;
                            m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage;

                            m_serverTransaction.SendInviteRequest(m_serverEndPoint, m_serverTransaction.TransactionRequest);
                        }
                        else
                        {
                            m_serverTransaction.CancelCall(rtccError);
                            FireCallFailed(this, rtccError);
                        }
                    }
                    else
                    {
                        if (routeSet == null || routeSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner));
                            m_serverTransaction?.CancelCall("Unresolvable destination " + callURI.Host);
                            FireCallFailed(this, "unresolvable destination " + callURI.Host);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve top Route host " + routeSet.TopRoute.Host, Owner));
                            m_serverTransaction?.CancelCall("Unresolvable destination " + routeSet.TopRoute.Host);
                            FireCallFailed(this, "unresolvable destination " + routeSet.TopRoute.Host);
                        }
                    }
                }
            }
            catch (ApplicationException appExcp)
            {
                m_serverTransaction?.CancelCall(appExcp.Message);
                FireCallFailed(this, appExcp.Message);
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Exception UserAgentClient Call. " + excp.Message, Owner));
                m_serverTransaction?.CancelCall("Unknown exception");
                FireCallFailed(this, excp.Message);
            }
        }
        public void ReferOutOfDialog(SIPURI fromUri, SIPURI toUri, SIPURI referToUri, ReplacesCallDescriptor sipReplacesCallDescriptor)
        {
            try
            {
                m_sipCallDescriptor = new SIPCallDescriptor(null,toUri.ToString(),fromUri.ToString(),null,null);
                m_sipCallDescriptor.Gruu = toUri.Parameters.Get(SIPCallDescriptor.GRUU_KEY);
                m_sipCallDescriptor.ReplacesCall = sipReplacesCallDescriptor;

                SIPURI callURI = SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri);

                    // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden.
                    if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address))
                    {
                        m_serverEndPoint = m_outboundProxy;
                    }
                    else if (!m_sipCallDescriptor.ProxySendFrom.IsNullOrBlank())
                    {
                        // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of.
                        SIPEndPoint outboundProxyEndPoint = SIPEndPoint.ParseSIPEndPoint(m_sipCallDescriptor.ProxySendFrom);
                        m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort));
                        m_serverEndPoint = m_outboundProxy;
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "SIPReferClientUserAgent refer request using alternate outbound proxy of " + m_outboundProxy + ".", Owner));
                    }
                    else if (m_outboundProxy != null)
                    {
                        // Using the system outbound proxy only, no additional user routing requirements.
                        m_serverEndPoint = m_outboundProxy;
                    }

                    // A custom route set may have been specified for the call.
                    if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1)
                    {
                        try
                        {
                            RouteSet = new SIPRouteSet();
                            RouteSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true));
                        }
                        catch
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Error an outbound proxy value was not recognised in SIPReferClientUserAgent refer request. " + m_sipCallDescriptor.RouteSet + ".", Owner));
                        }
                    }

                    // No outbound proxy, determine the forward destination based on the SIP request.
                    if (m_serverEndPoint == null)
                    {
                        SIPDNSLookupResult lookupResult = null;

                        if (RouteSet == null || RouteSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Attempting to resolve " + callURI.Host + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(callURI, false);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Route set for refer request " + RouteSet.ToString() + ".", Owner));
                            lookupResult = m_sipTransport.GetURIEndPoint(RouteSet.TopRoute.URI, false);
                        }

                        if (lookupResult.LookupError != null)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Refer request cannot proceed.", Owner));
                        }
                        else
                        {
                            m_serverEndPoint = lookupResult.GetSIPEndPoint();
                        }
                    }

                    if (m_serverEndPoint != null)
                    {
                        Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Switching to " + SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress + " via " + m_serverEndPoint + ".", Owner));

                        m_localSIPEndPoint = m_sipTransport.GetDefaultSIPEndPoint(m_serverEndPoint);
                        if (m_localSIPEndPoint == null)
                        {
                            throw new ApplicationException("The refer request could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + ".");
                        }

                        SIPRequest referRequest = GetReferRequest(m_localSIPEndPoint,referToUri, sipReplacesCallDescriptor);

                        // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call.
                        m_serverTransaction = m_sipTransport.CreateNonInviteTransaction(referRequest, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy);

                        m_serverTransaction.NonInviteTransactionFinalResponseReceived += m_serverTransaction_NonInviteTransactionFinalResponseReceived;
                        m_serverTransaction.NonInviteTransactionTimedOut += m_serverTransaction_NonInviteTransactionTimedOut;
                        m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage;

                        m_serverTransaction.SendReliableRequest();

                    }
                    else
                    {
                        if (RouteSet == null || RouteSet.Length == 0)
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner));
                            FireReferFailed(this, "unresolvable destination " + callURI.Host);
                        }
                        else
                        {
                            Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve top Route host " + RouteSet.TopRoute.Host, Owner));
                            FireReferFailed(this, "unresolvable destination " + RouteSet.TopRoute.Host);
                        }
                    }
            }
            catch (ApplicationException appExcp)
            {
                FireReferFailed(this, appExcp.Message);
            }
            catch (Exception excp)
            {
                Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Exception UserAgentClient Call. " + excp.Message, Owner));
                FireReferFailed(this, excp.Message);
            }
        }