Guides & Howto's

You are currently browsing the archive for the Guides & Howto's category.

Upate: There’s a bit of confusion around what needs to happen to take advantage of this latest fix.

  • 1. NO changes need to be made to SIP accounts or the SIP account a particular ATA/Phone is using,
  • 2. A change does need to be made to the registration contact being used for a provider IF it’s used for Google Voice callbacks AND the contact username is NOT the same as the web login username.

As people quickly discovered the new redundant sipsorcery deployment did not play happily with matching callbacks on Google Voice calls. The reason is that Google Voice calls from sipsorcery are not a SIP call at all but instead are initated with a HTTP request to Google Voice which generates a callback to a 3rd party SIP provider such as Gizmo (via SIP) or SIPGate (via PSTN) which if the provider is configured correctly forwards the call back to sipsorcery. If that all goes smoothly the sipsorcery server will receive the call and attempt to match it up to the SIP call that initiated the whole thing. Messy, yes; complicated, yes; one big hack, yes; since Google Voice don’t currently provide a public SIP gateway this mechanism is the only way to use Google Voice with sipsorcery, not that that’s a major goal of the project but it seemed like an interesting challenge at the time.

Anyway the introduction of a dual server deployment at sipsorcery meant that the forwarded call from the 3rd party SIP provider could now arrive at either server. That’s not an issue for pure SIP calls and the sipsorcery application servers are smart enough to know which proxy to use when forwarding to registered SIP accounts. However it is an issue when waiting for the Google Voice callback since the originating SIP call exists on a single specific server and if the forwarded callback does not arrive at the same server they won’t be matched up and more than likely the forwarded call will get rejected or cause a different phone to ring.

I have now put in a workaround (hack to a hack to a hack sort of thing) that will allow the callbacks to be correctly matched up. The caveat is that the forwarded call from the 3rd party SIP provider MUST be to the username of the owning account that is it can’t be to any old sipsorcery SIP account it MUST be a SIP account that has the same name as the username that’s used to login to the web site.

The new mechanism relies on telling the sipsorcery SIP proxies, that sit in front of the application servers, that the next call for a specific username should be directed to a specific application server. The reason the SIP account must be the exact same as the owning username is that the SIP proxies don’t have time to go looking things up in the database, they are designed to get the SIP packets to and from the other SIP servers as quickly as possible and introducing database checks would slow them down dramatically.

So the mechanism isn’t perfect but then again the original sipsorcery Google Voice call approach is not a beacon of purity either. Hopefully it should be enough to get people by.

With the SQL Azure migration complete and the second sipsorcery application server similarly bedded down now is a good time to provide the configuration options for SIP clients to avail of the new redundancy measures.

The quick steps to take to configure your SIP client are:

1. Do nothing.

In the majority of cases there will be nothing at all needed on the client side to allow it to failover between the two sipsorcery SIP servers. The sipsorcery SRV records are now configured for both sipsorcery.com and sip.sipsorcery.com (using either is exactly the same, I typically use just sipsorcery.com because it’s less typing).

For the failover mechanism to work a SIP client MUST support SRV records (RFC 3263: Session Initiation Protocol (SIP): Locating SIP Servers to be official about it). It’s also necessary that one of the two hostnames mentioned above, I’ll repeat them because they are critically important sipsorcery.com or sip.sipsorcery.com, are used and NOT an IP address or the hostname of one of the individual SIP servers.

There are still a few minor issues I am working on sorting out such as matching up GoogleVoice callbacks, which can now arrive at either of the two SIP servers, and fixing the event logging for the Silverlight console so that it gets the events from both server rather than just a single one. Apart from those issues the new sipsorcery deployment is working very well and given that it took 5 or so months of development work to make the changes to allow a multi-server deployment not to mention the work on Amazon’s SimpleDB that ended up not being used I am so far pretty happy with the way things are running.

The single point of failure in the sipsorcery system is now the Microsoft SQL Azure database platform. SQL Azure has a monthly SLA of SLA of 99.9% which would translate to 43.2 minutes of downtime in a 30 day month. That’s actually a pretty low level of reliability for a telecoms type service where five nines (26 seconds per month) is typically the bare minimum and six nines (2.6 seconds per month) is desired but hopefully the SQL Azure service will exceed expectations. Incidentally there has been an outage already in January, on the 17th between 0503 UTC and 0519 UTC the sipsorcery applications were able to read but not write to the SQL Azure database so that’s 16 minutes of the 44.6 minutes (January has 31 days so the SLA allows an extra 1.4 minutes of downtime) used up.

Now that Google have bought Gizmo it’s my guess that there will be a whole lot of work commencing at Goozimo (Google+Gizmo) around peer-to-peer SIP. The reason is that Goozimo will want to compete head on with Skype to become the communications solution of the masses and the only way to effectively compete is to switch from a centralised SIP model to a hybrid peer-to-peer SIP model.

Why? A centralised SIP model starts to get very expensive and very cumbersome when you have to proxy media. VoIP providers can just get away with it now when voice is the media they carry but what happens once that shifts to video and then high definition video and then multi-party, high definition video and … well you get the idea, the media payload sizes are just going to keep on growing. Even a company the size of Google that probably has per Mbps bandwidth costs in the sub USD1 range will struggle to absorb that level of traffic. And apart from the cost it’s just not a good architectural solution to take something which is inherently peer-to-peer, two end users talking to each other, and turn it into a peer-to-server-to-peer. VoIP providers at the moment don’t worry too much about it because unlike Skype the majority of their traffic is from end users to their PSTN gateways and the percentage of end user to end user calls is negligible. Like the media payload sizes that to will change in the coming years.

The problem for Goozimo is that SIP is poorly designed for peer-to-peer communications. I’ve harped on about this before but it’s always worth reiterating that the SIP designers must have been out on the booze the night before they were due to draw up the methods for dealing with NAT because they just left it out completely, a cardinal sin for any internet protocol. The only reason SIP has prospered with such a massive deficiency is that the only real competing protocol H.323 was designed by PSTN engineers and is even worse.

What can Goozimo do about it? That’s the question. Ideally they’d like to throw SIP away and do things properly and use a proper internet protocol such as XMPP. However that’s not really an option because of the size of the deployed SIP user base coupled with the manufacturing momentum behind it. It’s the same reason Google needed Gizmo rather than just expanding their GTalk service, the Google engineers know XMPP not SIP. My bet is that Goozimo will add to the plethora of SIP “enhancement” standards which must already be nearing triple figures and add a set of features that will make it easier to deal with NAT.

Will peer-to-peer SIP work? Yes, it has to. It’s either that or start from scratch with an alternative protocol and we’re already too far gone for that to happen: IPv4 and IPv6 being a case in point.

How will it work? The saving grace in the whole mess is that the solution probably isn’t that difficult. SIP developers have now had a lot of experience as to how to deal with mangling private IP addresses in the SDP payloads and can let each end of the SIP call know the socket the media should be sent to. The missing piece is the NAT in front of each SIP user agent allowing the media through. Most NATs will only permit an incoming packet through if there has already been an outgoing packet sent to the originating socket. That can be a problem when both ends of a SIP call are behind NAT and the port on one or both of the user agents has been re-mapped by NAT. Essentially that’s the problem that needs to be solved for peer-to-peer SIP to start working. There are different ways it could be done but it’s not so much the technical solution used as to a company the size of Google getting behind it and encouraging manufacturers to roll it out.

Interestingly a lot of NATs do not re-map ports by default, at least not until there is a conflict and they are forced to, and therefore SIP P2P calls are already quite feasible. The reason they are not more widespread comes back to the motivation of the commercial SIP Providers which is to get billable calls into their PSTN gateways. Supporting P2P SIP calls is not going to generate any revenue for them.

The sipsorcery service on the other hand is very interested in P2P SIP calls since being a free service it cannot afford the extra cost of proxying media. In fact every single calls that has ever been placed through the mysipswitch/sipsorcery services has been a P2P one. Generally the calls are between an end user and a SIP Provider but as far as the sipsorcery server is concerned the SIP Provider is just another end point and it treats the call exactly the same as if it was between two end users. A sipsorcery call between two end users will still have an issue if the SDP ports have been re-mapped by the NAT at either end but in practice that seems to be a small percentage of calls.

What does a P2P SIP call mean for an end user? The answer is not much for voice, it’s still better to stick those through a 3rd party provider to take advantage of the NAT handling in their gateway, but for video it’s a different story. Most people I know that use video calls use Skype and all report the video often drops or is choppy. The reason is that Skype’s P2P overlay network still relies on super nodes, which are just other Skype users with good bandwidth in close network vicinity, to proxy the media. When the Skype network gets busy there will be increased contention on the overlay network and the media will suffer. The ideal situation is for the media to travel directly between the two end user agents and not to be proxied by anyone. In the SIP network that provides the added advantage that the end user agents can find the best matching media capability between them rather than is currently the case where it’s the best matching capability between the two end user agents and the SIP Providers server.

As a practical example I have tested video calls with Counterpath’s Bria softphone through the sipsorcery.com service and it works very well. The video capability in the Bria’s is better than Skype and while there can still be chop and break on the video at least now it’s down only to the internet connections at either end of the call rather than also the ones of the Skype supernodes.

There is one trick to getting the Bria’s to work with sipsorcery and that is to ensure the call is made as a video call initially and not a voice call followed by an attempt to start a video one. In the latter case the re-INVITEs can end up with the wrong IP addresses as the sipsorcery server does not mangle in dialogue requests. If the call is placed as a video one straight away the sipsorcery server will mangle the initial SDP and the RTP carrying the video has the best chance of getting established. The diagram below shows the “Video Call” button that appears when the Bria is switched to video mode and it is the one that should be used to place calls through sipsorcery.

One thing I’ve been meaning to do for a while is a post on how to programatically connect to the SIP Sorcery provisioning service. The service is exposed over a SOAP 1.1 interface. This post provides a brief C# code example which demonstrates how to connect using WCF. At some stage I’d also like to provide a javascript based code sample using jquery or a similar library. That may motivate someone to write an alternative user interface to the Silverlight one and appease the people who dislike it for whatever reason.

The full source code for the C# sample can be dowloaded from here.

The SOAP standard does not include any mechanisms for authentication. There is a web service extension available that includes a mechanism in the form of WS-Security specifications. The problem is that the specification is quite bulky and the classes provided by WCF to make it easy to use are not supported by Silverlight.

An alternative to using a SOAP authentication mechanism is to use an HTTP one such as OAuth. The HTTP approach is appealing for at least two reasons: it’s light weight and easy to implement compared to WS-Security and it can be used for different application protocols which means if/when a REST provisioning endpoint is added the same authentication mechanism can be used.

Incorporating REST and OAuth into the SIPSorcery provisioning interface is a little way down the road and at the moment the authentication mechanism used has been designed to work easily with the Silverlight client. The existing mechanism is SOAP specific and involves two steps:

  • Step 1 – Call the Login method and if successful a token will be returned. The token is a 384 bit random number returned as a 96 byte string.
  • Step 2 – In all subsequent provisioning SOAP requests the token needs to be included in the SOAP header in an authid element.
  • Each token is only good for one hour or until it is passed to the Logout method. While the token is current it’s a critical piece of information that allows full access to a specific user’s account as such it should never be transmitted over an unencrypted connection. The SIPSorcery provisioning interface is only exposed via HTTPS which means there is no opportunity to send a token on anything but an encrypted connection.

    Below is an example of a SOAP envelope that includes the authentication token in the authid SOAP header. The SOAP request in this case is GetCustomer and the username parameter in the body is actually the username of the customer record being requested and nothing to do with authentication.

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Header>
        <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.sipsorcery.com/provisioning/IProvisioningService/GetCustomer</Action>
        <authid>8c441993d8df81d42bb5a6757f4370a504d972a21c5812166a3cc36292ccb53ab1cac2750e74815707b37ddea21cdae7</authid>
      </s:Header>
      <s:Body>
        <GetCustomer xmlns="http://www.sipsorcery.com/provisioning">
          <username>username</username>
        </GetCustomer>
      </s:Body>
    </s:Envelope>
    

    With authentication out of the way on to the C# sample.

  • Step 1 – Create a new C# console application in Visual Studio
  • Step 2 – In the Solution Explorer right click on the References folder and choose Add Service Reference.

    addserviceref

  • Step 3 – Set the service address to https://www.sipsorcery.com/provisioning.svc. To work properly with the sample code below set the namespace to Provisioning.

    setserviceref

  • Step 4 – Add the classes below to your console application. These classes are required to add a custom SOAP authentication header to each request sent to the service.

    (Code sample updated 7 Feb 2010 to adjust for a new security header format.)

    public class SIPSorceryProvisioningBehavior : IEndpointBehavior {
    
        private string m_authId;
    
        public SIPSorceryProvisioningBehavior(string authId) {
            m_authId = authId;
        }
    
        public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) {
            clientRuntime.MessageInspectors.Add(new SIPSorceryProvisioningMessageInspector(m_authId));
        }
    
        public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) {   return; }
        public void Validate(ServiceEndpoint serviceEndpoint) { return; }
        public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { return; }
    }
    
    public class SIPSorceryProvisioningMessageInspector : IClientMessageInspector {
            
        private string m_authId;
    
        public SIPSorceryProvisioningMessageInspector(string authId) {
            m_authId = authId;
        }
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel) {
            request.Headers.Add(new SIPSorcerySecurityHeader(m_authId));
            return null;
        }
    
        public void AfterReceiveReply(ref Message reply, object correlationState) { }
    }
    
     public class SIPSorcerySecurityHeader : MessageHeader
        {
            private const string SECURITY_NAMESPACE = "http://www.sipsorcery.com/security";
            private const string SECURITY_HEADER_NAME = "Security";
            private const string SECURITY_PREFIX = "sssec";
            private const string AUTHID_ELEMENT_NAME = "AuthID";
    
            private static ILog logger = AppState.logger;
    
            public string AuthID;
    
            public override bool MustUnderstand { get { return true; } }
            public override string Name { get { return SECURITY_HEADER_NAME; } }
            public override string Namespace { get { return SECURITY_NAMESPACE; } }
    
            public SIPSorcerySecurityHeader(string authID)
            {
                AuthID = authID;
            }
    
            protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
            {
                writer.WriteStartElement(SECURITY_PREFIX, AUTHID_ELEMENT_NAME, SECURITY_NAMESPACE);
                writer.WriteString(AuthID);
                writer.WriteEndElement();
            }
    
            protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
            {
                writer.WriteStartElement(SECURITY_PREFIX, this.Name, this.Namespace);
            }
    
            public static SIPSorcerySecurityHeader ParseHeader(OperationContext context)
            {
                try
                {
                    int headerIndex = context.IncomingMessageHeaders.FindHeader(SECURITY_HEADER_NAME, SECURITY_NAMESPACE);
                    if (headerIndex != -1)
                    {
                        XmlDictionaryReader reader = context.IncomingMessageHeaders.GetReaderAtHeader(headerIndex);
    
                        if (reader.IsStartElement(SECURITY_HEADER_NAME, SECURITY_NAMESPACE))
                        {
                            reader.ReadStartElement();
                            reader.MoveToContent();
    
                            if (reader.IsStartElement(AUTHID_ELEMENT_NAME, SECURITY_NAMESPACE))
                            {
                                string authID = reader.ReadElementContentAsString();
                                return new SIPSorcerySecurityHeader(authID);
                            }
                        }
                    }
                     return null;
                }
                catch (Exception excp)
                {
                    logger.Error("Exception SIPSorcerySecurityHeader ParseHeader. " + excp.Message);
                    throw;
                }
            }
        }
    
  • Step 5 – Now everything is ready to use the service. The code sample below shows how to do that.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    using System.Text;
    using System.Xml;
    
    namespace SIPSorcerySOAPConsole {
    
        class Program {
            static void Main(string[] args) {
                try {
                    Console.WriteLine("Starting SIP Sorcery SOAP Console");
    
                    // First step is to login and acquire an authid security token.
                    Provisioning.ProvisioningServiceClient client = new Provisioning.ProvisioningServiceClient();
                    string authID = client.Login("username", "password");
                    Console.WriteLine("authid=" + authID + ".");
    
                    // Once the security token has been acquired it needs to be set on all subsequent requests.
                    Provisioning.ProvisioningServiceClient authenticatedClient = new Provisioning.ProvisioningServiceClient();
                    authenticatedClient.ChannelFactory.Endpoint.Behaviors.Add(new SIPSorceryProvisioningBehavior(authID));
                    Customer customer = authenticatedClient.GetCustomer("username");
                    Console.WriteLine("First Name=" + customer.FirstName + ".");
                }
                catch (Exception excp) {
                    Console.WriteLine("Exception Main. " + excp.Message);
                }
                finally {
                    Console.WriteLine("finished, press any key to exit...");
                    Console.ReadLine();
                }
            }
        }
    }
    
  • If you’ve made it this far the next question you’ll have is “now that I can connect what can I do with the it?”. For the answer the best place to go is the source.

  • The interface is in IProvisioningService.
  • All but one of the classes for the returned objects are contained in the SIPSorcery.SIP.App assembly and the SIPAssets folder. The SIPAccount class for example.
  • The exception is the Customer class which is contained in the SIPSorcery.CRM assembly.
  • Finally we would request that the interface is used sensibly. It can be used to create new sipsorcery accounts (when they are enabled again) and as they are in tight supply there may be a temptation to automate their creation. At this point we do request users stick to one account each and while we are very reluctant to suspend or remove accounts and only do so as a last resort if one user’s actions have a large impact on everyone else we will do so.

    Enjoy and plese post a comment if you are successful in connecting to the provisioning service.

    Aaron

    Updated 25 Jan 2010: Adjusted for the new parameters required when using the sys.GoogleVoiceCall method in the sipsorcery dialplan.

    The “hacked” up Google Voice App on sipsorcery appears to have attracted some new people to the site. To help them I’m writing a quick tutorial about how they can quickly get up and running to place a call with the Google Voice app.

    Warning: People new to sipsorcery will probably be fine until they get to the dialplan configuration and will then start cursing in frustration: “why is this thing so *#!@ hard all I want to do is make a telephone call!”. The reason is that sipsorcery and mysipswitch before it were designed for people to be able to experiment with SIP stuff and try weird and wonderful things. The price for that power and flexibility has so far been ease of use. One day the plan is to re-create something like the dialplan wizard to make it simpler but so far it just hasn’t made it to the top of the list.

    Back to the promised tutorial.

    Following are the minimum steps you need to take to be able to place a call from sipsorcery to terminate with Google Voice.

    • 1. Login to the Google Voice site click Settings (in the top left) and then Phones on the main menu. On the Phones screen you must have a Gizmo number configured as shown below (note it doesn’t matter whether it’s ticked or not).

      Goog Voice - Phone

      Goog Voice - Phone

    • 2. The Gizmo number you have used in Google Voice MUST then be configured to forward calls to your sipsorcery account. You can do this by setting a forward at the Gizmo SIP Provider end or by registering the account from the sipsorcery end. The result in both cases is the same and it doesn’t matter which one you use. To register your Gizmo SIP Provider account from sipsorcery you need to create a new SIP Provider entry as shown below (use appropriate values for your account where I’ve blurred my own settings out).

      Important: As part of some updates made to sipsorcery for enhanced redundancy the contact registered or used with the callback SIP Provider MUST be username@sipsorcery.com where username is the same as the one used to login to the sipsorcery web site. If it’s not the same then there is around a 50% chance the Google Voice callback WILL NOT be matched up to the waiting SIP call that initiated it on the sipsorcery end.

      SIP Provider Details - Gizmo

      SIP Provider Details - Gizmo

    • 3. Now we’re ready to place a call. To do that you need to click on the Dial Plans menu in your sipsorcery account. I will assume that you are creating a new dialplan and will be overwriting the default one created for you.
      Google Voice - Minimal Dial Plan

      Google Voice - Minimal Dial Plan

      And so you can actually read it:

      sys.Log("starting dialplan...")
      sys.GoogleVoiceCall("emailaddress@gmail.com", "password", "1747612xxxx", "1132701859", ".*", 7)
      sys.Log("Sorry, Google Voice Call failed.")
      

      Here’s what each of the parameters mean:

      • emailaddress@gmail.com MUST be the email address you use to login to your Google Voice account.
      • password MUST be the password for the email address.
      • 1747612xxxx MUST be your Gizmo a number that has been registered on your Google Voice account and be the same as the one shown showing on your Google Voice Phones page in step 1. This is the number that Google Voice will place the callback on so calls to it must somehow be configured to arrive back to the sipsorcery servers typically this would be by registering a sipsorcery provider binding with the SIP provider that supplies the number.
      • 1132701859 this is the destination number you wish to call and can be ANY US landline number (I don’t know whether mobiles or any others will work).
      • .* this is a regular expression pattern that will be applied to any incoming calls that arrive on your sipsorcery account for 30 seconds after a sys.GoogleVoiceCall method has been used in your dialplan. The pattern is used to decide whether the incoming call is the callback from Google Voice and to bridge it with waiting SIP call. A pattern of .* means the very next incoming call will be matched, it’s the safest option for anyone unsure about regular expressions or confused about what this parameter means.
      • 7 this is the type of phone being used for the callback from Google Voice, The Google Voice web request requires that it be specified. The range of this option seems to be 1 to 7. To date it doesn’t seem to make any difference what number is used EXCEPT that if Gizmo is the callback provider 7 must be used. If it’s not Gizmo the safest bet is to use a value of 1.

    Once you have taken those 4 steps you need to configure your ATA, IP Phone or soft phone to use the sipsorcery SIP account and then place a call. If all goes according to plan you will get the following:

    • A ring tone on your phone almost straight away. This is generated by the sipsorcery server to let you know it’s started working.
    • Somewhere between 1 and 10 30 seconds later the phone will get answered and you will have a brief pause of silence followed by another ring tone. This time the ring tone is being generated by the Google Voice server and indicates the destination number you specified is ringing.

    That’s it, Easy ūüôā.

    Caveats. Google obviously didn’t intend for people to be able to hook up their SIP devices to make free calls. I assume free calls via the Callback mechanism on the Google Voice web site pays off by driving web traffic to the site. With a SIP call there is no such pay off. As such the sipsorcery solution and other solutions around the web are hacks. That means they are susceptible to breaking or being blocked it Google get annoyed with the SIP calls. On the mysipswitch Forums there are already reports of the occassional call failing with a HTTP 500 Server Error. Watching the sipsorcery logs I have seen a few calls getting the same. That error maybe because there was something about the call request Google didn’t like, you can test that by using the same values in a Callback from the Google Voice page, or it may be that the HTTP requests that are sent from sipsorcery to Google are occassionally going to get rejected for some reason (the 500 Server Error was caused by a bug in the sipsorcery code). The point is if you want to use this sort of solution on sipsorcery or elsewhere you will probably need to accept that not every call is going to work (that being said none of my own test calls have failed yet).

    Finally if you would like to get a little bit more adventurous with your dialplan and have it send the number you called in on as the destination for your Google Voice call you can use the one shown below.

    Google Voice Call - Advanced Dial Plan

    Google Voice Call - Advanced Dial Plan

    sys.Log("starting dialplan...")
    sys.GoogleVoiceCall("emailaddress@gmail.com", "password", "1747612xxxx", "#{req.URI.user}", ".*", 7)
    sys.Log("Sorry, Google Voice Call failed.")
    

    One of the new features of sipsorcery is the ability to create multiple dialplans. This means it’s now a lot easier to do a bit of testing if you’re struggling with a bit of Ruby script.

    As an example say you have an issue with a regular expression match (a topical subject on the forums at the moment) you could create a new dialplan and put some minimal regular expression matching code in it.

    sys.Log("webcallback dialplan starting...callback number=#{req.URI.User}")
    case req.URI.User
       when /*1234$/ then sys.Log("#{req.URI.User} matched /*1234$/")
       else sys.Log("No match")
    end
    

    In this case I have used my webcallback dialplan so that I can do a test by invoking the callback URL
    instead of having to call into my dialplan.

    To invoke the above dialplan I used the following URL, you will need to put in your own sipsorcery username for it to work for you.

    http://www.sipsorcery.com/callmanager.svc/webcallback?user=username&number=*1234

    I got the dialplan trace emailed to me and unsuprisingly the log messages were:

    DialPlan=> Dialplan trace commenced at 16 Jul 2009 18:36:08:180.
    DialPlan=> webcallback dialplan starting…callback number=*1234
    DialPlan=> *1234 matched /*1234$/

    One of the biggest enhancements in the sipsorcery service compared to the previous mysipswitch service is the number of different ways of processing incoming calls. The drivers for the enhancements were requests by various mysipswitch users for alternative or more flexible ways to process incoming calls. At this stage I believe pretty much every request in the area has been accommodated but unfortunately a side effect has been a number of sipsorcery users having difficulty getting their calls working as they expect. The intention of this post is to clarify the mechanisms available for incoming calls and how they work.

    Before delving into the incoming call processing mechanisms one point that needs to be clarified is the mysipswitch concept of SIP accounts and Extensions. An extension with mysipswitch was a SIP URI (e.g. sip:joe.bloggs@mysipswitch.com) that could be handed out and that was stored in a separate database table to the SIP accounts and that was looked up if no matching SIP account was found. Extensions were very much a bolt on to mysipswitch to cope with the fact that only a single SIP account could be created oer mysipswitch user. With sipsorcery the single SIP account restriction is gone and with it the need to have a separate concept of an extension. Instead there is now the option to create a SIP account that can be specified as incoming only and which will act the same as the mysipwitch Extensions.

    Add incoming only SIP account

    Add incoming only SIP account

    Now that that’s clarified onto the different options for processing incoming calls.

    • Direct to registered bindings,
    • In Dial Plan,
    • Suffix matching.

    Direct

    The Direct option is the default option and is the simplest. It works by forwarding any incoming calls to a SIP account to any currently registered bindings for that SIP account. To use this option the only thing required is that the In Dial Plan setting on the SIP account is left blank. As an example if I were to create a SIP account called joe.bloggs@sipsorcery.comand set up one of my SIP Providers to forward calls to sip:joe.bloggs@sipsorcery.com then to receive those calls all I need to do is register my SIP device with sipsorcery.com with a username of joe.bloggs. Up to 10 SIP devices can register with the same username and when an incoming call comes in they will all ring with the first one that picks up getting the call.

    In Dial Plan

    The In Dial plan is as the name suggests and the incoming call will be forwarded to the dialplan specified in the In Dial Plan setting for processing. Within the dialplan the call can be processed in any manner desired. An example of an in dialplan that accomplishes exactly the same as the previous Direct option for incoming call processing is shown below.

    sys.Log("dialplan defaultin starting...")
    sys.Log("call from #{req.Header.From.FromURI.ToString()} to #{req.URI.User}.")
    sys.Dial("myextension@local")
    

    In the above dialplan an incoming call to sip:myextension@sipsorcery.com will be sent to the defaultin dialplan for processing. Once there it will print the two log messages and then the call will be forwarded to all the current bindings registered for the myextension@sipsorcery.com SIP Account, i.e. exactly the same behaviour as the Direct option.

    Suffix Matching

    Another mechanism that was cobbled on, in the same way extensions were, to mysipswitch was the ability to process calls that had an arbitrary suffix with a prefix matching an existing SIP account username. By popular demand the same behaviour has been added to sipsorcery.

    As an example of how it works if I owned a SIP account called myextension@sipsorcery.comthen incoming calls to the following SIP URIs will also be accepted and processed in exactly the same way as myextension:

    • sip:x.myextension@sipsorcery.com
    • sip:1234.myextension@sipsorcery.com
    • sip:1234.5678.abcd.myextension@sipsorcery.com

    The crucial factor is all the URIs end with .myextension@sipsorcery.com note the ‘.’ it is the separator between the suffix and the SIP Acount name.

    Calls to other sipsorcery accounts from within a dialplan

    With sipsorcery if you placed a call to another sipsorcery SIP Account within a dialplan then that call will honour the In Dial Plan setting on the called SIP Account. For example if I use the forward below in my dialplan:

    sys.Dial("myextension@local")
    

    If the myextension SIP account has an In Dial Plan set then the call will now be sent to that dialplan for processing rather than directly to myextension’s registered bindings. If the In Dial Plan is not set then the Dial command will result in the call being forwarded directly to myextension’s registered bindings.

    This is a powerful and potentially dangerous feature since a chain of calls to local accounts or two accounts dialling each could result in a large number of dialplans being simultaneously processed. It is requested that suitable precautions be taken to avoid that happening for anyone that wished to make use of this feature.

    One additional point when calling local accounts within a dialplan is that if a forward is attempted to a SIP account from the same dialplan that is configured on its In Dial Plan setting then the dialplan will not be used, doing so would create an infinite loop, and instead the registered bindings will be used.

    And Finally…

    it’s not directly related to the incoming call processing mechanisms but if you find that calls are not reliably getting through to your SIP device from the sipsorcery server then more than likely your NAT is timing out the connection. The best way around that is to check your device for a NAT keep-alive option and activate it. NAT keep-alives work by sending a small packet every 15 to 30s from a SIP user agent to the server to keep the connection alive through the router. If there is no option on your user agent then you can select the option on the SIP Account at the sipsorcery end. This does the same thing in reverse. It’s not quite as good as NATs will respect traffic originating from the private side better than traffic originating from the public side but it should still help.

    In addition the expiry interval on your user agent can be reduced. The sipsorcery SIP registrar uses a default register expiry of 113s, sometimes reducing that to 60s can improve the durability of the connection between your user agent and the sipsorcery server through your NAT.

    And that’s it, please feel free to post comments with questions for any clarifications on the subject of incoming call processing but I would request thatyou not post comments with general support questions.

    Newer entries »