Ruby Dial Plans
Posted: Tue Mar 25, 2008 10:08 am
Hi All,
[Ed. 13 Aug 2008 - Small change to sys.Respond]
[Ed. 16 Aug 2008 - Added new method sys.GTalk]
[Ed: 21 Sep 2008 - Clarified dial string for sys.Dial command]
As of 25 Mar 2008 dial plans can now be written as Ruby (http://www.ruby-doc.org/docs/ProgrammingRuby/) scripts. Using a script instead of a single command allows much greater flexibility in power for processing calls.
To specify a dialplan should be interpreted as Ruby the dialplan must have #Ruby on the first line. An example of a minimalist Ruby dialplan is:
#Ruby
sys.Dial("blueface")
All the standard Ruby expressions and constructs are available for use and in addition two locally scoped variables are added to all dialplan scripts for each call processed:
- sys (stands for System) and contains some helper methods and dialplan commands.
- req (stands for Request) and contains the received INVITE request,
Reference:
sys.Callback(string dest1, string dest2) - Initiates a call to dest1 and if successful then calls dest2 and bridges the calls together. The dest1 and dest2 parameters are SIP Provider constructs.
sys.Dial(string provider) - Equivalent of the current dialplan Switch, SwitchCall or Dial command. The provider parameter must match a SIP Provider name and the Dial command will forward the call to that SIP Provider.
The dial string format is:
[dst@]provider[, true]
dst - is the optional call destination. If not specified the call destination of the initiating request will be used. The dst can also make use of the initiating request value by using ${dst} or ${dst:n} to trim n characters from the start.
provider - must be a provider name or a valid DNS host name.
true - if present inidcates a trace is required.
Examples:
sys.Dial(string provider, int timeout) - Same as the previous Dial method except that the timeout indicates a maximum amount of time the call will ring for before giving up and returning execution to the script.
string sys.ENUMLookup(string number) - Attempts to resolve an e164 number to a SIP URI, if successful the SIP URI is returned otherwise nil. The number passwed to the ENUMLookup method must have the domain the ENUM lookup is to be performed in included.
Examples of correctly formatted numbers:
0.0.0.0.2.4.2.5.1.3.5.3.enum.org
35315242000.enum.org
+35315242000.enum.org
003531524200.enum.org
Examples of incorrectly formatted numbers:
35315242000
0.0.0.0.2.4.2.5.1.3.5.3
SIPAddressBinding[] sys.GetBindings() - Gets a list of bindings for your SIP account. If you do not have a device registered with the sipswitch then None will be returned.
sys.GTalk(string username, string password, string sendToUser, string message) - Attempts to send a message to a gTalk user. The username and password must belong to a valid gTalk user and should be entered without @gmail.com or any other host portion. The sendToUser is the gTalk username of the account to send the message to (can be the same as username) also without the @gtalk.com or any other host portion. The message is the text that will be attempted to be sent.
Note that at times it can take quite a while to establish a connection to the gTalk network and the sipswitch dialplan will only wait for a maximum of 5s. In the very limited testing undertaken so far the first attempt to send a message wil often timeout but subsequent ones will then work.
bool sys.In and bool sys.Out - Can be used to determine whether a call being processed by the dialplan is an outgoing or incoming call. An outgoing call is one you as the owner of the dialplan are placing. An incoming call is one being received from an external caller to you.
Note about sys.Username , this is a variable representing your username so it must not be changed! If you want to test it, use the log function : sys.Log("#{sys.Username} is really cool")
bool sys.IsAvailable() - Is used to check whether the dial plan owner's account has a SIP account online. The function returns true if there is a current binding and false otherwise.
sys.Log(string message) - Logs a message to both the monitoring screen and the telnet console. Allows debugging and informational messages to be provided as part of Ruby dialplans.
sys.Respond(int statusCode, string reasonPhrase) - Sends a SIP response to the caller with the specified SIP response code and reason.
If the status code is <= 199 then it is treated as an informational response and the dialplan script keeps running. If the status code is >= 200 then it's treated as a final response to the client and the script terminates after the response is sent.
sys.Trace = true|false - Activates or deactivates tracing of dial plan calls. The trace will be sent to the email address registered on the owning sipsiwtch account once the call is answered or is unsuccessful.
req.URI - The SIP URI for the incoming request.
req.URI.User - The user portion of the request URI this is the value used in the non-Ruby dial plans as ${EXTEN} or ${dst}.
req.URI.Host - The host portion of the request URI.
req.Header - The SIP Headers for the incoming request.
req.Header.From - The SIP From header for the incoming request.
req.Header.From.FromURI - The URI portion of the From header.
req.Header.From.FromName - The name portion of the From header.
req.Header.To - The SIP To header for the incoming request.
req.Header.To.ToURI - The URI portion of the To header.
req.Header.To.ToName - The name portion of the To header.
req.Header.Contact[0] - The first Contact header in the incoming Request.
req.Header.Contact[0].ContactURI - The URI of the first Contact header.
req.Header.Contact[0].ContactName - The Name of the first Contact header.
req.Header.CSeq
req.Header.CallId
etc.
A special case is req.Header.From which is what most SIP Providers will use to set custom callerid's if they support it. Unfortunately the From header is also normally used to identify who you are so changing it can affect your ability to authenticate your call.
It is possible to customise the From header on a forwarded call.
The above script would result in a From header of:
From: "Joe Bloggs" <sip:01234567@mydomain.com>
The field that is generally used for authentication is req.Header.From.FromURI.User so be aware your calls could fail if it is modified.
Some of the above fields are strings and can be used directly in log messages. If you get an error logging an object add ToString() at the end of it. For example:
sys.Log("Call received for #{req.URI.ToString()}")
An example of a Ruby dialplan that is equivalent to the non-Ruby approach is:
#Ruby
sys.Log("call received uri=#{req.URI.ToString()}")
case req.URI.User
when "123" then sys.Dial("fwd")
when "456" then sys.Dial("voipstunt")
else sys.Dial("blueface")
end
The documentation above is far from complete but should serve to help get anyone interested started.
Note of warning: The Ruby engine in use by the sipswitch is a development project called IronRuby (http://www.ironruby.net/) and there are almost certainly going to be issues with the implementation at this early stage.
Second note of warning: The following strings are not permitted anywhere in a Ruby dialplan: require, include, system, :: and `. This is to prevent scripts from executing privileged operations on the sipswitch server.
Regards,
Aaron
[Ed. 13 Aug 2008 - Small change to sys.Respond]
[Ed. 16 Aug 2008 - Added new method sys.GTalk]
[Ed: 21 Sep 2008 - Clarified dial string for sys.Dial command]
As of 25 Mar 2008 dial plans can now be written as Ruby (http://www.ruby-doc.org/docs/ProgrammingRuby/) scripts. Using a script instead of a single command allows much greater flexibility in power for processing calls.
To specify a dialplan should be interpreted as Ruby the dialplan must have #Ruby on the first line. An example of a minimalist Ruby dialplan is:
#Ruby
sys.Dial("blueface")
All the standard Ruby expressions and constructs are available for use and in addition two locally scoped variables are added to all dialplan scripts for each call processed:
- sys (stands for System) and contains some helper methods and dialplan commands.
- req (stands for Request) and contains the received INVITE request,
Reference:
sys.Callback(string dest1, string dest2) - Initiates a call to dest1 and if successful then calls dest2 and bridges the calls together. The dest1 and dest2 parameters are SIP Provider constructs.
Code: Select all
# Ruby dialplan example for sys.Callback
sys.Log("call received uri=#{req.URI.User}")
sys.Callback("012345@blueface", "023456@voipstunt")
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("blueface") if req.URI.User.StartsWith("3")
sys.Respond(404, "No dialplan match")
[dst@]provider[, true]
dst - is the optional call destination. If not specified the call destination of the initiating request will be used. The dst can also make use of the initiating request value by using ${dst} or ${dst:n} to trim n characters from the start.
provider - must be a provider name or a valid DNS host name.
true - if present inidcates a trace is required.
Examples:
Code: Select all
sys.Dial("provider1")
sys.Dial("1234@provider1")
sys.Dial("1234@provider1, true")
sys.Dial("${dst:1}@provider1")
Code: Select all
# Ruby dialplan example for sys.Dial
sys.Log("call received uri=#{req.URI.User}")
sys.Dial("provider1", 10)
sys.Dial("provider2", 15)
sys.Dial("provider3", 10)
sys.Respond(404, "No forwards answered")
Examples of correctly formatted numbers:
0.0.0.0.2.4.2.5.1.3.5.3.enum.org
35315242000.enum.org
+35315242000.enum.org
003531524200.enum.org
Examples of incorrectly formatted numbers:
35315242000
0.0.0.0.2.4.2.5.1.3.5.3
Code: Select all
# Ruby dialplan example for sys.ENUMLookup
enumuri = sys.ENUMLookup("35315242000.mysipswitch.com")
if enumuri != nil
sys.Dial(enumuri)
else
sys.Respond(404, "ENUM lookup failed")
end
Code: Select all
#Ruby dialplan example for sys.GetBindings()
if sys.IsAvailable() then
bindings = sys.GetBindings()
bindings.each { |binding| sys.Log("#{binding.ContactSIPURI.Host}.") }
end
Code: Select all
#Ruby dialplan example for sys.GTalk.
sys.GTalk("joe.bloggs", "password", "jane.doe", "Hello World!")
sys.GTalk("joe.bloggs", "password", "jane.doe", "#{req.URI.User}")
bool sys.In and bool sys.Out - Can be used to determine whether a call being processed by the dialplan is an outgoing or incoming call. An outgoing call is one you as the owner of the dialplan are placing. An incoming call is one being received from an external caller to you.
Code: Select all
#Ruby dialplan example for sys.In and sys.Out
if sys.Out then # sys.In can also be used in the same manner.
sys.Log("Outgoing call from user domain=#{sys.FromDomain}.")
sys.Dial("blueface")
else
sys.Log("Incoming call to domain=#{sys.ToDomain}.")
if sys.IsAvailable() then
sys.Log("#{sys.Username} is online.")
sys.Dial("local")
else
sys.Log("#{sys.Username} is not online.")
sys.Respond(480, "#{sys.Username} Not online")
end
end
bool sys.IsAvailable() - Is used to check whether the dial plan owner's account has a SIP account online. The function returns true if there is a current binding and false otherwise.
Code: Select all
#Ruby dialplan example for sys.IsAvailable()
sys.Log("call received uri=#{req.URI.User} from #{req.Header.From.FromURI.User}")
sys.Log("isavailable=#{sys.IsAvailable().ToString()}.")
if sys.IsAvailable()
sys.Dial("me@local")
else
sys.Dial("mymobile@provider")
end
Code: Select all
# Ruby dialplan example for sys.Log
sys.Log("Log message from Ruby dialplan.")
sys.Log("Incoming call for uri=#{req.URI.User}.").
Code: Select all
# Ruby dialplan example for sys.Respond
sys.Respond(404, "No dialplan match")
sys.Trace = true|false - Activates or deactivates tracing of dial plan calls. The trace will be sent to the email address registered on the owning sipsiwtch account once the call is answered or is unsuccessful.
Code: Select all
# Ruby dialplan example to turn tracing on
sys.Trace = true
req.URI - The SIP URI for the incoming request.
req.URI.User - The user portion of the request URI this is the value used in the non-Ruby dial plans as ${EXTEN} or ${dst}.
req.URI.Host - The host portion of the request URI.
req.Header - The SIP Headers for the incoming request.
req.Header.From - The SIP From header for the incoming request.
req.Header.From.FromURI - The URI portion of the From header.
req.Header.From.FromName - The name portion of the From header.
req.Header.To - The SIP To header for the incoming request.
req.Header.To.ToURI - The URI portion of the To header.
req.Header.To.ToName - The name portion of the To header.
req.Header.Contact[0] - The first Contact header in the incoming Request.
req.Header.Contact[0].ContactURI - The URI of the first Contact header.
req.Header.Contact[0].ContactName - The Name of the first Contact header.
req.Header.CSeq
req.Header.CallId
etc.
A special case is req.Header.From which is what most SIP Providers will use to set custom callerid's if they support it. Unfortunately the From header is also normally used to identify who you are so changing it can affect your ability to authenticate your call.
It is possible to customise the From header on a forwarded call.
Code: Select all
req.Header.From.FromURI.User = "01234567"
req.Header.from.FromURI.Host = "mydomain.com"
req.Header.From.FromName = "Joe Bloggs"
From: "Joe Bloggs" <sip:01234567@mydomain.com>
The field that is generally used for authentication is req.Header.From.FromURI.User so be aware your calls could fail if it is modified.
Some of the above fields are strings and can be used directly in log messages. If you get an error logging an object add ToString() at the end of it. For example:
sys.Log("Call received for #{req.URI.ToString()}")
An example of a Ruby dialplan that is equivalent to the non-Ruby approach is:
#Ruby
sys.Log("call received uri=#{req.URI.ToString()}")
case req.URI.User
when "123" then sys.Dial("fwd")
when "456" then sys.Dial("voipstunt")
else sys.Dial("blueface")
end
The documentation above is far from complete but should serve to help get anyone interested started.
Note of warning: The Ruby engine in use by the sipswitch is a development project called IronRuby (http://www.ironruby.net/) and there are almost certainly going to be issues with the implementation at this early stage.
Second note of warning: The following strings are not permitted anywhere in a Ruby dialplan: require, include, system, :: and `. This is to prevent scripts from executing privileged operations on the sipswitch server.
Regards,
Aaron