Tuesday, May 02, 2017

Command line Twilio client - part 2

[This is continuation of the previous post]

The command line SIP endpoint included in my rtclite project allows SIP registration to register with a SIP server to receive SIP calls. For example, you can signup for a free SIP account at iptel.org, download rtclite and py-audio on OS X, open two terminals, run the rtclite.app.sip.caller app on one to register, and on another to place a call as follows:

$ python -m rtclite.app.sip.caller --domain=iptel.org --user myuser --samplerate=48000 --listen --register --authuser myuser --authpass mypassword

$ python -m rtclite.app.sip.caller --port 5094 --user anything --samplerate=48000 --to sip:myuser@iptel.org

This will register the first instance as sip:myuser@iptel.org and place a call from the second instance as sip:anything@my-local-host to the first instance. The app is configured by default to auto-answer incoming calls. Since both the instances are on the same machine, I use a different listening SIP port, 5094, for the second instance. Use the -v option to enable detailed SIP log. Use Ctrl-C to terminate the call and to unregister.

In this article I describe how to use this command line SIP endpoint to register with Twilio to receive calls. I also describe the main differences between normal SIP registration and Twilio specific SIP registration based call flows.

Register to Twilio from command line SIP endpoint to receive calls 

Since my last post, Twilio has added the SIP registration feature. The approach is described on the provider's website including the steps for creating SIP domain/endpoint such as yourname.sip.twilio.com. Once the SIP domain is created, configure the IP access control list as well as SIP credentials for the domain. Using one is enough, but using both provides more protection. Also enable SIP registration for that domain using the SIP credentials. I have put two SIP accounts in my credentials list, myuser1 and myuser2, for the example below.

Create and assign an enhanced TwiML for handling incoming voice call on that domain. The following example shows how to use the To header as is. Alternatively, you can create programmable server-side scripts to derive the target SIP address.

  <Dial timeout="20"><Sip>{{To}}</Sip></Dial>

Open two terminals on your Mac OS X as before, and run the caller app instances as follows.

$ python -m rtclite.app.sip.caller --domain=yourname.sip.us1.twilio.com --user myuser2 --samplerate=48000 --listen --register --authuser myuser2 --authpass mypassword2

$ python -m rtclite.app.sip.caller --port 5094 --domain=yourname.sip.us1.twilio.com --user myuser1 --samplerate=48000 --to sip:myuser2@yourname.sip.us1.twilio.com --authuser myuser1 --authpass mypassword1

The first instance registers as myuser2, the second instance uses myuser1 to call the first instance myuser2. The Twilio's SIP registration is currently enabled only in one zone, hence the specific domain containing us1 must be specified for both receiver and caller instances. Use the -v option to enable detailed SIP log. Use Ctrl-C to terminate the call and to unregister. As in the previous post, this uses G.711 audio.

The SIP destination specified in TwiML could instead be any other SIP address, e.g., on any other non-Twilio domain. For example,

  <Dial timeout="20"><Sip>sip:kundan10@iptel.org</Sip></Dial>

This will send the SIP call to that SIP address.

Differences with regular SIP registration call flow

Summary of registration call flow differences between standard SIP (e.g., iptel.org) and Twilio SIP services are as follows.
  1. Media anchored at Twilio: With Twilio, the SIP media path always flows through the Twilio server, unlike the previous iptel.org based example, where the media path is end-to-end. The Twilio call flow works by decoupling the caller and receiver - the caller app connects to the Twilio service which runs the TwiML specified above in the first call leg, which in turn dials out the SIP destination in the second call leg. Since the SIP destination happens to be one registered with Twilio service, the service connects to the receiver app. Being in the media path enables the service to inject intermediate TwiML elements such as interactive dialog or digit collection. On the other hand, it could introduce additional latency on the media path.
  2. Proxy authentication vs. Authentication: Unlike iptel.org service, which challenges the registering app using 401 response code, the Twilio service challenges using 407 response code. Although most user agents do not care, and provide the right authorization response when challenged, the semantics of the two are different. A 407 response code indicates more a SIP outbound proxy or B2BUA to challenge any request reaching the service, whereas a 401 indicates being challenged by the serving user agent such as a SIP registrar.
  3. Registered endpoint is not reachable directly: On iptel.org service, when an endpoint registers as user, myuser,  any other SIP endpoint can reach that user via that SIP service. On Twilio, when an endpoint registers as user, myuser, it can only be reached by the Twilio service, e.g., using the example TwiML tag shown above. If a SIP endpoint attempts to reach, say, sip:myuser@yourname.sip.us1.twilio.com directly via SIP, it will reach the Twilio service, which will not reach the registered user, myuser, unless the associated voice URL TwiML is configured to dial-out to that SIP address. For example, dialing out to myuser could create a SIP call to anotheruser or join a conference or queue the call depending on the TwiML. This is more flexible, but not same as the standard SIP registration based call flow.
If you happen to try out SIP registration and call flows using my rtclite project, please drop me a note. If you face any issues, please send the SIP log using the -v option.