FreeSWITCH 1.2
上QQ阅读APP看书,第一时间看更新

Important concepts to understand

FreeSWITCH is a very versatile piece of software. One of the biggest reasons that it's so versatile is because the world of telephony is very dynamic. As the developers of the software, we often faced difficult choices when making decisions about how FreeSWITCH should behave in various situations. Quite often, we faced conundrums where a large number of potential users required the software to work in a specific way, and the others expected the exact opposite behavior. We easily support devices that behave properly, but at the same time we must adapt to tolerate many devices that blatantly violate specifications. FreeSWITCH was designed to scale, so we also had to design things so you can start out with a self-contained static configuration and be able to scale into using live dynamic configurations without missing a beat. This is a lot to swallow for a new user but don't fret. When you installed FreeSWITCH in the previous chapter, you also installed a fully functional example configuration that will get you through most of this book, with only a few minor modifications.

As we discussed in Chapter 1, Architecture of FreeSWITCH, FreeSWITCH is based on a central core fuelled by a central XML registry and orbited by several modules that communicate with each other via the core. We are going to use the example settings in the XML registry to register some phones and make a few test calls. When you make a call, the SIP module will push a request to the XML Dialplan, where the digits you dialed are matched against a series of patterns called regular expressions. Once a match has been found, the data from the XML extension that matched is copied into the channel locally, so it has a list of instructions that it will execute in the next stage of the call. It's possible to match more than one extension on the same pass of the Dialplan depending on the choice of configuration keywords. For these first few tests, just a single extension will be put to use, and you will have a chance to see all of the call data that is available whenever a channel is in the ROUTING state. (For details on channel states, see the Putting it all together section in Chapter 8, Advanced Dialplan Concepts.)

In telephony jargon, we call a connection between two devices a call leg. The term A leg is used to describe the communication path between the calling party (or caller) and FreeSWITCH. The term B leg is used to describe the communication path between the receiving party (or callee) and FreeSWITCH. Consider the following illustration:

If you are using a phone to call and listen to a demo extension then there is one call leg in use, that is, the connection between your phone and FreeSWITCH. If you dial digits that end up calling another phone currently registered to FreeSWITCH or push the call to a service provider to call your cellular phone, you then have two call legs—the first one, A leg, we explained, and another one, B leg, that connects FreeSWITCH and the other phone or service provider. Each leg of the call has its own unique properties, and a special relationship with the opposite leg in that particular call. When one or more legs of a call are exchanging media with each other, we call that a bridge. In a bridged, call, either leg of the call can perform certain operations on the other leg in the same bridge such as putting it on hold, transferring it to another extension, or joining it with a third party to form a three-way call.

Some calls only have one leg—there is a connection between one phone and FreeSWITCH, and FreeSWITCH interacts with the caller directly. Frequently, this type of interface is referred to as an IVR or Interactive Voice Response menu. Other examples of one-legged calls include a user connected to voicemail, as well as a caller connected to a conference room. IVRs are very powerful and you certainly have used them before if you have ever called a system that provides a list of choices and asks you to dial a digit indicating the choice you want to make. If you have ever used a calling card, this is also a form of IVR that asks you to dial your account number, PIN, and destination digits before completing your call. Some IVRs can even detect speech and react purely on special words that you may say at the appropriate time. With FreeSWITCH, it is simple to make an IVR, and we will learn a few ways to do this in Chapter 6, Using XML IVRs and Phrase Macros and Chapter 7, Dialplan Scripting with Lua.

The XML Dialplan separates the extensions into special groups called contexts. A context is an XML tag containing several extension elements. An extension is a collection of patterns to match against the dialed digits and a relative set of instructions to execute based on a positive or negative match against the patterns. Consider the following figure:

Every new call that enters the FreeSWITCH core must have a pre-ordained set of context, Dialplan, and extension digits to indicate where the call should be routed. In our examples, we will be using the XML Dialplan and the default Dialplan context. The extension digits will depend on what you dialed when you placed the call. Once you dial an extension, the SIP Endpoint module will insert all of the call data it has decoded from your SIP phone, set the Dialplan to XML, the context to default, and push the call's state to ROUTING. The default ROUTING logic in the core will look up the XML Dialplan module and push the call into its call hunt handler routine. This routine connects to the XML registry and searches the list of contexts for the default context. Once the context has been located, it parses each extension in the context, testing the patterns held in the condition tag until it finds one that matches. Each action tag within that condition tag contains an application and an optional data argument. These applications provided by the application modules that we discussed in Chapter 1, Architecture of FreeSWITCH, will be executed in order until the last one is reached or the call ends.

The arguments to the applications can contain channel variables, a special group of name/value pairs that are designed to influence the channel behavior, and provide a way to store important call data. They look similar to the special pre-processor variables we recently discussed, but only a single dollar sign is used rather than two. ${destination_number}, for instance, tells you what digits the caller dialed, and is the primary value used to route calls. The condition tags use the field attribute to denote which value to run the pattern match against. If this value is one of the special variables held in the caller profile, you can omit the ${} for simplicity's sake.

The special caller profile variables are as follows. Some may seem unusual at first, but as you use FreeSWITCH more, you will see where these all come into play:

  • username
  • dialplan
  • caller_id_name
  • caller_id_number
  • callee_id_name
  • callee_id_number
  • network_addr
  • ani
  • aniii
  • rdnis
  • destination_number
  • source
  • uuid
  • context

The caller profile is just a collection of special information that every call has in common, which is passed along from one leg to another. This information can be accessed the same way as other variables, and should be considered read-only, as the data is provided by the initial call setup. Following is a real example from the default configuration, which uses the tone generator in the core to play a rendition of the popular song from the 1980's video game, Tetris:

<extension name="tone_stream">
  <condition field="destination_number" 
    expression="^9198$">
    <action application="answer"/>
    <action application="playback"  
      data="tone_stream://path=${base_dir} 
      /conf/tetris.ttml;loops=10"/>
  </condition>
</extension>

As you can see, it uses field="destination_number" to check if you dialed 9198, and if you did, it answers the call and plays the tone stream. It uses ${base_dir} to denote the location where the configuration is stored so it can deduce the path to the correct file containing the tone data. (Don't worry if this seems like a lot to digest. We will be explaining this information in more detail.) You have had a chance to see FreeSWITCH in action by making a few test calls to the various example extensions that are found in the example config. Channel variables can be very useful when integrating outside information about a call, which you may want to set and retrieve later in your own applications. These variables might contain information such as the caller's account number, which is useful if someone calls in to manage their account. There is an interface to set variables in the application interface provided by the set application. Consider the following example:

<action application="set" data="customer_id=1234"/>

From this point on, the channel variable customer_id will contain the value 1234. If the value is not changed prior to the call ending then this value will also be available in the Call Detail Record (CDR) data.

As the XML registry can be rather large and scary, we have designed it to be loaded from several smaller files spread out into the configuration directory in logical order. This means that rather than digging into one giant file, you can locate smaller, simpler files, each of which can be used to configure a specific type of functionality in FreeSWITCH.

Note

The FreeSWITCH wiki contains a large diagram showing how the example config is laid out: http://wiki.freeswitch.org/wiki/Default_config#Overview_Diagram_of_the_Demo_Configuration.

Once FreeSWITCH loads the main registry (a file called freeswitch.xml), the file is run through a special pre-processor that scans the file for special directives, which are replaced in the file with the contents of other files. In some cases, the pre-processor also sets global variables. This means that you can set important variables once in the top-level configuration file and reference them later in the deeper sections of the registry. Take an IP address or domain name for instance. Pretend that you have some significant IP address, say, 74.112.132.98. If you use this value multiple times in your configuration, you can put the following line somewhere at the top of the first file that is loaded:

<X-PRE-PROCESS cmd="set" data="my_ip=74.112.132.98"/>

Now you can place $${my_ip} in your configuration where you want your IP address to appear. This expansion is done by the pre-processor, so in the final XML generated and loaded by FreeSWITCH, the IP will appear as if it was hardcoded into the file everywhere $${my_ip} appeared.

Another great feature of the XML pre-processor is the ability to include other files with a single line. Following is an example line used in the example config to load all the files from a particular directory in place inside the default Dialplan context:

<X-PRE-PROCESS cmd="include" data="default/*.xml"/>

This means that every single file in the default folder that ends with .xml will be included in place of the preceding line. This makes it possible to create new extensions in their own dedicated files and include them into your Dialplan without disturbing the default.xml file (the file containing the default Dialplan context).