Updated 22 Jan 2001 due to sipsorcery call manager service again being made available on an HTTP URL since there’s a problem with Tropo recognizing the sipsorcery SSL certificate. Note the service is still available on HTTPS as well as HTTP. Also it’s no longer necessary to use the workaround to get SIP headers in a Tropo dialplan. Calls can be forwarded directly to sip.tropo.com.

Updated 12 Apr 2010 due to sipsorcery call manager service migration to HTTPS.

Tropo is a hosted voice application platform that I and a number of other sipsorcery users have messed around with at various stages. At this point I would say Tropo is definitely the pick of the bunch from the voice application platforms I have tested out and some of the stuff that can be done in a couple of lines of script, such as speech recognition or text-to-speech, is pretty amazing.

One glaring ommission for me and again other sipsorcery users has been the lack of an elegant way to transfer calls away off the Tropo servers. Here’s a few posts from the Tropo Forums about transfers:

  • Call and Transfer (from jack9901)
  • transfer API
  • And I posted the same query regarding blind transfers at some point as well but it must have been cleaned out

The usage pattern a lot of people are after is to dial into the Tropo platform, do some processing, such as ask the user to enter a number, and then transfer the call back to a different system to do some different processing, such as forward the call to a 3rd party SIP provider. Tropo does support attended transfers but that has two big shortcomings:

  • 1. Because Tropo will ultimately be charging by the minute having their servers bridge the whole call after any application processing is done is an unneccessary expense,
  • 2. Adding an extra media server into the call path always introduces call quality concerns. Even if Tropo’s systems and network connections are the best in the World it’s extra latency on the call that’s not needed.

After the recent work I did to support transfers on the sipsorcery servers I started thinking about the Tropo problem again and realised there was a nice elegant solution. Instead of initiating the SIP transfer from Tropo I could get Tropo to send a HTTPS request to sipsorcery and have it do the transfer instead. So that’s what I’ve spent the last few days doing and the good news is it works perfectly (at least for me).

The steps are:

  • Create a new dialplan on your sipsorcery account called transfer, this is the dialplan the call will end up in when it comes back from Tropo,
  • In your sipsorcery diaplan set the From header user to something that can be used to uniquely identify the call:
        when /^232$/ then sys.Dial("999142xxx@sip.tropo.com")

    An old example of a sipsorcery dialplan is shown below. The difference between the two is that when sip.tropo.com is used instead of sip-noproxy.voxeo.net there is no way to access the SIP headers within a Tropo dialplan and a “hack” of setting the From header user is needed.

        when /^232$/ then sys.Dial("999142xxx@sip.tropo.com[fu=uniqueidxxx]")

    The From header user can be accessed in the Tropo system with $currentCall.callerID $currentCall.getHeader(“x-sbc-call-id”),

  • In your Tropo application the blind transfer needs to be initiated using a HTTPS request a Ruby example I’ve used is:
    require 'java'
    say "hello world"
    log "Call-ID=" + $currentCall.getHeader("x-sbc-call-id")
    svcURL = "http://www.sipsorcery.com/callmanager.svc/blindtransfer?user=username&callid=#{$currentCall.getHeader("x-sbc-call-id")}&destination=hold";
    url= java.net.URL.new svcURL
    conn = url.openConnection
    log "javaURL created"
    stm = conn.getInputStream
    transferResult = org.apache.commons.io.IOUtils.toString(stm)
    log transferResult
    say "" # Play some audio while transfer is being carried out.

    An old Tropo example, which will NOT work due to the call manager service no longer being provided on an HTTP URL, is shown below.

    require 'net/http'
    say "hello world"
    transferResult = Net::HTTP.get_response(URI.parse("http://sipsorcery.com/callmanager.svc/blindtransfer?user=username&callid=#{$currentCall.callerID}&destination=1234")).body
    log transferResult
    say "" # Play some audio while transfer is being carried out.

    The new blindtransfer web service method takes three parameters:

    • user must be your sipsorcery username,
    • callid is used to identify the call leg that’s being transferred out of the call. Tropo doesn’t seem to provide much access to the incoming call headers so I’ve tailored the sipsorcery end to be able to look up the call leg based on the From header URI user. That’s why it needs to be set to something reasonably unique in your sipsorcery dialplan,
    • destination this is the value that will end up in the sipsorcery transfer dialplan as req.URI.User.

For once the whole thing is easier than it sounds and I think for those people already familiar with sipsorcery and Tropo it will be an easy job to use the new mechanism. The great thing about it is that there is now an elegant way to solve the challenge of allowing a user to dial in and enter or say their number and then dial that number out through a different provider.