Creating a Dialplan in Asterisk 1.6: Part 2

Exclusive offer: get 50% off this eBook here
Asterisk 1.6

Asterisk 1.6 — Save 50%

Build feature-rich telephony systems with Asterisk

£14.99    £7.50
by Barrie Dempster David Gomillion David Merel | September 2009 | Networking & Telephony

In the previous part of the article by Barrie Dempster, David Gomillion, and David Merel we saw how to create a context, extension, and outgoing extensions. In this part we will learn about Advanced Call Distribution, Automated attendants, and System services.

Advanced Call Distribution

What exactly is Advanced Call Distribution ? Many phone systems tout this feature, but most do not adequately define what it means. Basically, it refers to using call queues, parking calls for another user to answer, and Direct Inward Dialing (DID).

So that we keep our focus, we will look at each of these elements individually.

Call queues

We have already configured call queues through the /etc/asterisk/queues.conf file. As we go through how we're going to use our queues, we may decide we want to change the way our queues are configured. There is absolutely no problem with changing the configuration so that it more accurately reflects our needs. Just remember that we need to issue a reload on the Asterisk console, or type #asterisk –r –x reload at the command line.

The power and flexibility of other ACD systems can be matched or exceeded by Asterisk. As we evaluate our needs, we should remember that configuring a single aspect of Asterisk sometimes requires changes to more than one file. For example, queues will be configured both in the queues.conf file and the extensions.conf file. We will discuss how to set up extensions.conf to give us the desired result.

When dealing with call queues, we need to think about the two types of users we have. First, we have the caller who calls in and waits in the queue for the next agent. We can think of this person as our customer. Next, we have the agents who work the queue. We can think of these people as our users.

As a business, we have to decide what we want our customers' experience to be. Our call queue can make it sound like a phone is ringing. Or we can use music on hold while the customer waits. We can also announce call position and estimated wait time if we want to.

When we place customers in a queue, we use the Queue application. To place a caller in the queue named bob, we would use something like:

exten => 1000,1,Queue(bob)

Suppose we have an operator's extension. As Ollie the operator may have more than one call at a time, we decide to give him a call queue. His calls are always about a minute long. The customers waiting for him are going to be there because they got lost in a system of menus. His queue will be named operator.

In this instance, we will choose to have the customer hear the ring, so they will believe they are about to be helped. The sound of ringing should not last more than about a minute. We will not announce call queue length because our customer should not know that he or she is in a queue.

The entry for this queue would be:

exten => 0,1,Queue(operator|tr)

Notice our use of options. Options for the queue application include:

  • t: Allow the user to transfer the customer.
  • T: Allow the customer to transfer the user.
  • d: This is a data-quality call.
  • H: Allow the customer to hang up by hitting *.
  • n: Do not retry on timeout. The next step in the dialplan will be executed.
  • r: Give the customer the ringing sound instead of music on hold.

Thus, we told the Queue application to make the customer hear the ring, and the user (Ollie) the ability to transfer calls (as he's the operator).

Now, suppose we have Rebecca, the receptionist at SIP phone 1006. When Ollie goes to the bathroom, we want our poor lost customers to be routed to her. So we could use the following in our extensions.conf file:

exten => 0,1,Queue(operator|trn)
exten => 0,2,Dial(SIP/1006)

Now, Rebecca had better answer this. Until she does, the phone will continue to ring. Notice that this call will never end up in Rebecca's voicemail, as it is not transferred to her extension, but instead dials her phone directly.

We have adequately addressed the customer's experience. But now we need to look at how our users will join and leave the queue. Previously, we discussed the power and flexibility of using agents in queues. As with most things in Asterisk, there are many ways we can associate members to queues. The three main ways are—statically, dynamically, and by using agents.

Our first option is to have members statically assigned to the queue. In order to do this, we use the member directive in the queues.conf file. This is most helpful when we have a queue with fixed members, such as a switchboard queue.

Our second option is to allow members to log in dynamically. We do this through the AddQueueMember application. An example of this would be:

exten => 8101,1,AddQueueMember(myqueue|SIP/1001)

Whenever anybody dials extension 8101, the telephone handset SIP/1001 would be added to the queue named myqueue. All that we would have to do is define a login extension for every member of every queue.

What happens when this member no longer wishes to be in the queue? We use the RemoveQueueMember application, like this:

exten => 8201,1,RemoveQueueMember(myqueue|SIP/1001)

With this configuration, whenever anybody dials extension 8201, the telephone handset at SIP/1001 is removed. Again, we would have to define a logout extension for each member of the queue.

Suppose we did not wish to define a login and logout extension for each member. We have the option of leaving off the interface (SIP/1001 in the previous example) and having Asterisk use our current extension. While this is very useful, Asterisk does not always use the right value. However, if it works for all extensions that need to be in the queue, we would only have to define one login and one logout per queue. The code would look like:

exten => 8101,1,AddQueueMember(myqueue)
exten => 8201,1,RemoveQueueMember(myqueue)

This is better than having to define a login and logout for each member of each queue, but sometimes users are not good at remembering multiple extensions to dial. The AddQueueMember application will jump to priority n+101 if that interface is already a member of the queue. Therefore, we could define an extension like:

exten => 8101,1,Answer
exten => 8101,2,AddQueueMember(myqueue)
exten => 8101,3,Playback(agent-loginok)
exten => 8101,4,Hangup
exten => 8101,103,RemoveQueueMember(myqueue)
exten => 8101,102,Playback(agent-loggedoff)
exten => 8101,105,Hangup

When we define it this way, a user dialing extension 8101 is logged in if not already a member of the queue, or logged out if in the queue. Also, we added a confirmation to the action, so that the user can know if they are now in or out of the queue. Notice that before we could use the Playback application, we had to answer the call. If we have a lot of these, we could define a macro extension, like:

[macro-queueloginout]
exten => s,1,Answer
exten => s,2,AddQueueMember(${ARG1})
exten => s,3,Playback(agent-loginok)
exten => s,4,Hangup
exten => s,103,RemoveQueueMember(${ARG1})
exten => s,104,Playback(agent-loggedoff)
exten => s,105,Hangup
. . .
[default]
exten => 8101,1,Macro(queueloginout|queue1)
exten => 8102,1,Macro(queueloginout|queue2)
exten => 8103,1,Macro(queueloginout|queue3)

And thus we see that using a macro will save us five lines in our extensions.conf for every queue after the first. This is how we can add queue members dynamically.

Our final option for adding queue members is by using Asterisk's agent settings. We were able to define agents in /etc/asterisk/agents.conf. We create an agent by defining an ID and a password, and listing the agent's name.

In the queues.conf, we could define agents as members of queues. Calls will not be sent to agents unless they are logged in. In this way, queues can be both dynamic and static—they are static when we do not change the members of the queues, but dynamic when calls will go to different handsets based upon which agents are logged in.

There are two main types of agents in this world. There are the archetypical large call center agents who work with a headset and never hear rings, and there are the lower-volume agents whose phone rings each time a call comes in. Asterisk has the flexibility to handle both types of agents, even in the same queue.

First, imagine a huge call center that takes millions of phone calls per day. Each agent is in multiple queues, and we have set each queue to use an announcement at the beginning of calls to let the agent know which queue the call is coming in from. As employees arrive for their shift, they sit down at an empty station, plug in their headset, and log in. Each employee will hear music in between calls, and then hear a beep, and the call will be connected. To accomplish this, we use the line:

exten => 8001,1,AgentLogin

Through the normal login, the call is kept active the whole time. The agents will logout by hanging up the phone. This allows large call centers to be quieter, as the distraction of ringing phones will be removed. It also allows for more efficient answering of lines, as the time required to pick up the phone is eliminated.

When our users arrive at work and wish to log in, they call extension 8001, where they are prompted for their agent ID, password, and then an extension number at which they will take calls. This is how Asterisk knows how to reach them. Our agents can log out when using AgentCallbackLogin by going through the same procedure as for login, with the exception that when they are prompted for their extension, they press the # key.

It may be a good idea for us to review agents.conf. If we defined autologoff, then after the specified number of seconds of ringing, the agent will be automatically logged off. If we set ackcall to yes, then agents must press the # key to accept calls. If we created a wrapuptime (defined in milliseconds), then Asterisk will wait that many milliseconds before sending another call to the agent. These options can help us make our phone system as user friendly as we want it to be.

Through the use of call queues, we can distribute our incoming calls efficiently and effectively. We have plenty of options, and can mix and match these three ways of joining users to queues.

Call parking

In many businesses across the United States, an operator can be heard announcing "John, you have a call on line 3. John, line 3." In Asterisk, we don't really have lines the way analog PBXs do. Our users are accustomed to not having to transfer calls, especially when they may not know exactly where John is.

Asterisk uses a feature known as call parking to accomplish this same goal. Our users will transfer calls to a special extension, which will then tell them what extension to call in order to retrieve the call. Then our users can direct the intended recipient to dial that extension and connect to the call.

In order to be able to use this feature, we must define our parking lot. This is done in the /etc/asterisk/parking.conf file. In this file, there are only a few options that we will need to configure. First, we must create the extension that people are to dial in order to park calls. This can be whatever extension is convenient for us. Then we will define a list of extensions on which to place parked calls. These extensions will be what users dial to retrieve a parked call. Next, we will define what context we want our parked calls to be in. Finally, we will define how many seconds a call remains parked before ringing back to the user who parked it. Here is an example:

[general]
parkext => 8100
parkpos => 8101-8199
context => parkedcalls
parkingtime => 120

These settings would mean that we can park calls by dialing 8100, and the call will be placed in extensions 8101 through 8199, giving us the ability to have up to 99 parked calls at any given time. The calls will be in the context called parkedcalls, which means we should be careful to include it in any context where users should be able to park and retrieve calls.

When our users transfer a call to extension 8100, they will hear Asterisk read out the extension that the call has been placed on. They can now make a note of it and notify the appropriate co-worker of the extension to reach the calling customer on. If the call is not picked up within the given parkingtime, then the call will ring back to the user who parked the call.

By using call parking, we can help our users by providing a feature similar to that of previous generations of PBXs. This also allows users to collaborate and redirect callers to other users who are better equipped to handle our customers' needs.

Direct Inward Dialing (DID)

Suppose we work at a healthcare company with over 100 employees. We have two PRI lines coming in, and only three switchboard agents to handle incoming calls. As a healthcare company, we schedule many appointments, answer questions about prescriptions, and help patients with billing questions. These three agents are always busy.

Now suppose the IT guy's wife calls in to ask if he wants sprouts or mash with his dinner. Do we want our switchboard agents to have to answer the call, find out who it is and what they want, and then transfer the call, or would we rather want the IT guy's wife to call her husband directly?

This is where Direct Inward Dialing (DID) comes in handy. DID is a service provided by phone companies where they send an agreed-upon set of digits, depending on the number the customer dialed. For most phone companies, the sent digits will be the full ten-digit number (in the United States). But this can be as small as the last digit.

All right, so the phone company is sending digits. What are we going to do with them? Imagine you have a PRI coming in to your office, and only ten phone numbers—a block from (850) 555-5550 to 5559. Your phone company has agreed to send you only the last digit dialed, which will be from 0 to 9, because you are guaranteed for this to be unique. Asterisk can route calls based on this DID information.

If we have our PRI line's channels defined to go into a context called incoming, this context could look like:

[incoming]
s,1,Goto(default,s,1)
i,1,Goto(default,s,1)
t,1,Goto(default,s,1)
0,1,Goto(default,1234,1)
1,1,Goto(default,2345,1)
2,1,Goto(default,3456,1)
3,1,Goto(default,4567,1)
4,1,Goto(default,5678,1)
5,1,Goto(default,6789,1)
6,1,Goto(default,7890,1)
7,1,Goto(default,1111,1)
8,1,Goto(default,1111,1)
9,1,Goto(default,1111,1)

There are a few things we should notice about this. First, we handled the error cases. What if a glitch at the phone company results in four digits being sent? We cannot allow a simple mistake on their end to interrupt our ability to receive phone calls.

Secondly, we are using Goto statements. We've briefly discussed how they can be both good and bad. In this case, if a user moves from one extension to another by using Goto, we have to update it only in the default context.

Finally, we are allowed to send multiple incoming DIDs to the same extension, if we so desire, as in the last three lines shown in the previous code. This might be useful if extension 1111 is the operator, and we do not yet have the number 7, 8, or 9 assigned to a user.

Of course, in real life this is going to get much more complicated, as phone numbers will probably come in with the full ten digits. But the concept is the same—we can define extensions based upon information that the phone company sends when the call is established.

By using DIDs, we can cut down on bottlenecks and give direct access to certain extensions. This tool of Asterisk helps make our phone system fast, efficient, and friendly to our users and customers.

 

Asterisk 1.6 Build feature-rich telephony systems with Asterisk
Published: September 2009
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

Automated attendants

Any time we call a large company, we are greeted by a computer voice, asking us to route our call based on what we want or need. We are all familiar with call menus. While we won't get into a philosophical debate about how good or bad they are, we will talk about how to make them.

Suppose we want to create a menu of options such as, "For a billing question, press 1, to request a configuration change press 2 ….". Now suppose you press 1, and you hear the option, "For help reading your statement, press 1, if you wish to dispute a charge, press 2, …". This is just a standard phone tree, with which most users are comfortable. Asterisk knows which extension to execute based upon what context we are currently in.

Suppose that your customer service representatives are on SIP/1000, and the manager whom you wish to handle all disputes is on SIP/1001. Then, you have technicians on SIP/1002 and SIP/1003. Our configuration file could look like:

[mainmenu]
exten => s,1,Answer
exten => s,2,DigitTimeout(5)
exten => s,3,ResponseTimeout(30)
exten => s,4,Background(welcome)
exten => s,5,Background(options)
exten => 1,1,Goto(billing,s,1)
exten => 2,1,Dial(SIP/1002&SIP/1003)
[billing]
exten => s,1,Answer
exten => s,2,DigitTimeout(5)
exten => s,3,ResponseTimeout(30)
exten => s,4,Background(billingoptions)
exten => 1,1,Dial(SIP/1000)
exten => 2,1,Dial(SIP/1001)

There are some very important points to make here. It is good to define your digit and response timeouts each time you are going to give an option to the user. This makes your dialplan easier to understand and maintain. Also, notice that we must use the Answer command before being able to play back files. Remember that Background allows for user input to be captured during the file, while Playback does not.

Also notice that we issued the Answer command in the billing menu as well. If we knew that nobody could ever get into the billing menu without having passed through the main menu, we could probably leave the command out. However, it does not have any serious adverse consequences, and by leaving it in, we are able to offer a direct line to the billing department, if we ever choose to do so.

Suppose we want to have users to be able to dial any extension at any time. All we have to do is use the magical include => default in each of the contexts. This can cause the same delay in dialing that we discussed previously in the section Creating outgoing extensions, so it should be used with care. Also, users sometimes mash buttons at random, and may stumble across random extensions, frustrating the user. Some organizations have chosen to have users press a specific digit to be able to dial extensions directly to deal with these problems.

On another design note, most customers do not like being trapped for long periods of time in menu systems. Care should be taken to ensure menus do not get too deep. Also, it is easier for customers if you don't give too many options in one level.

Care must also be taken in selecting invalid and timeout responses. But most importantly, we have to do something. Leaving a customer in limbo with nowhere to go and no prompts to get them there is not a friendly move.

Let's build on our previous system with these concepts in mind. Of course, the prompts would be updated to suggest using the new features. For the purpose of this example, let's assume our receptionist is on SIP phone 1004.

[mainmenu]
exten => s,1,Answer
exten => s,2,DigitTimeout(5)
exten => s,3,ResponseTimeout(30)
exten => s,4,Background(welcome)
exten => s,5,Background(options)
exten => 1,1,Goto(billing,s,1)
exten => 2,1,Dial(SIP/1002&SIP/1003)
exten => 3,1,Goto(dialbyext,s,1)
exten => t,1,Goto(s,1,1)
exten => i,1,Goto(s,1,1)
exten => 0,1,Dial(SIP/1004)
[billing]
exten => s,1,Answer
exten => s,2,DigitTimeout(5)
exten => s,3,ResponseTimeout(30)
exten => s,4,Background(billingoptions)
exten => t,1,Goto(billing,s,1)
exten => i,1,Goto(billing,s,1)
exten => 1,1,Dial(SIP/1000)
exten => 2,1,Dial(SIP/1001)
exten => *,1,Goto(mainmenu,s,1) ; escape to the previous menu
exten => 0,1,Dial(SIP/1004)
[dialbyext]
exten => s,1,Answer
exten => s,2,DigitTimeout(5)
exten => s,3,ResponseTimeout(30)
exten => s,4,Backgroud(enterextension)
exten => i,1,Playback(invalid)
exten => i,2,Goto(dialbyext,s,1)
exten => t,1,Playback(imsorryididntgetthat)
exten => t,2,Goto(dialbyext,s,1)
exten => *,1,Goto(mainmenu,s,1)
exten => 0,1,Dial(SIP/1004)
include => default

This is a pretty good system. We can build whatever we need using these concepts. Each menu system will be different, based on your needs. The menu system is easy to update according to your changing needs. As a reminder, when you have updated the dialplan, you can refresh it by executing the reload command at the console. This command does not interrupt calls that are currently in progress.

We should take a moment and discuss what a good menu is and what a bad menu is. We should put our most commonly chosen option first. We should not confuse our customers with too many choices. We should have errors that take you back one step, instead of all the way to the beginning of the menu. We should give an operator who can help people if they get lost. Finally, we should strive not to have our menu any deeper than four steps.

If we keep these design principles in mind, our automated attendant can be the best employee we've ever had. No demands, never sick, and always cheerful and ready to help!

System services

We have talked about how to create contexts, extensions, and how to make our system powerful. Some of the ideas we have discussed will be useful in some situations, yet not applicable in others. All of them work together to make Asterisk a flexible solution for many different needs. There are still other uses that we won't get into, as the need for them is less frequent.

There are some basic system services that we have not yet discussed. We configured our voicemail users. Asterisk also includes an application called directory that reads the voicemail configuration and allows callers to look up an extension based on the user's last name. In the section Creating an extension (Part 1), we saw how to send calls to voicemail. How do users retrieve messages? How do we use this directory?

exten => 8000,1,VoicemailMain(@default)
exten => 8888,1,Directory(default)
exten => 8888,2,Goto(1)

As you can see, providing access to the directory (extension 8888) and voicemail (extension 8000) is easy. But priority 2 of extension 8888 may seem odd. This is in here because the directory seems to crash from time to time. By setting priority 2 to place the user back into the directory, the failure is almost transparent to our users.

In priority 1 of extension 8000, we tell Asterisk to send people to voicemail in the default context. If we have only one context, we can usually get away without defining the context. However, it is better to be safe. In the directory application, we must define what context to use, which we specified as default. Both of these contexts should match the context listed in the voicemail.conf file.

When our users call the directory, they will be prompted to enter the first three letters of the person's last name. Pulling from the voicemail.conf file by default, Asterisk will search for all matches. If users have recorded their name (option 0, 3 in VoicemailMain), then Asterisk will play the file where the person speaks their name, otherwise, Asterisk will spell the complete name out. When it finds the person our user is looking for, they press 1. Asterisk immediately tries to dial that person.

Here we need to talk about naming our contexts. If our voicemail context is called foo, then Asterisk will try to dial extension@foo. However, if our extensions are all defined in a context called bar, then the directory will fail. Therefore, we must make sure that the contexts in voicemail.conf (where we define the voicemail entry) and the contexts in extensions.conf (where we define the extension) match.

Now suppose we want to record prompts for our menus. Asterisk can play standard Windows .wav files. However, getting the files recorded and into the phone system may not be the most convenient thing to do. Therefore, we can create a simple extension to allow us to record a prompt. We will allow users to input a four-digit name for the file so that they can record many prompts before having to sort them. The prompts will be stored in /tmp, and be recorded as .wav files. Let's assume we have files called enter4digits and record-instructions, as well as a file called 1toaccept2torerecord3torecordanother.

exten => 8200,1,Goto(record,s,1)
[record]
exten => s,1,Answer
exten => s,2,Read(RECORD|enter4digits|4)
exten => s,3,Playback(record-instructions)
exten => s,4,Record(/tmp/recording-${RECORD}|wav)
exten => s,5,Wait(2)
exten => s,6,Playback(/tmp/recording-${RECORD})
exten => s,7,ResponseTimeout(10)
exten => s,8,Background(1toaccept2torerecord3torecordanother)
exten => 1,1,Hangup
exten => 2,1,Goto(s,3)
exten => 3,1,Goto(s,2)

This little context will give us the option of recording whatever custom prompt we want, in a .wav format. We could add a timeout extension and an invalid extension if we so desire, just as we have done in other contexts.

Another great service that Asterisk provides is conferencing. We configured meetme.conf so that we could have conference rooms. For users to be able to enter the conference rooms, we must create an extension giving us access.

Suppose we have 10 conference rooms, which we want to place on extensions 8900 to 8909. We also named our conferences 8900 to 8909 in meetme.conf. Our extensions.conf should contain:

exten => 8900,1,MeetMe(8900)
exten => 8900,2,Goto(default,s,1)
exten => 8901,1,MeetMe(8901)
exten => 8901,2,Goto(default,s,1)
exten => 8902,1,MeetMe(8902)
exten => 8902,2,Goto(default,s,1)
. . .
exten => 8909,1,MeetMe(8909)
exten => 8909,2,Goto(default,s,1)

If we use a little bit of variable magic, we can get these lines down to:

exten => _890X,1,MeetMe(${EXTEN})
exten => _890X,2,Goto(default,s,1)

So, we see that by making our MeetMe conference number the same as the extension number that users dial to join, our lives are made a little bit easier. Also, by having all our conferences in a block of 10 or 100, we are able to use pattern matching to make our extensions.conf shorter.

Another service we may wish to have is a MusicOnHold extension. It will do nothing but play the music on hold that is currently running. This can be a useful tool for the administrator to check if the music is even running, or to check the volume on a handset. In order to add a MusicOnHold extension, we would add something like:

exten => 8010,1,MusicOnHold(default)

This extension will play the music that is playing on hold in the default class, as configured in the musiconhold.conf file. It will only end when the caller hangs up the phone. But we need to remember that it is not like the background music of some phone systems, in that it does tie up the line that is listening to the music. If calls come in while a user is listening to the music on hold, they will go through the normal procedure for a phone being busy.

Summary

In this part of the article we looked at Advanced Call Distribution covering details such as Call queues, Call parking, and Direct Inward Dialing. We also looked at Automated attendants and System services.

If you have read this article you may be interested to view :

Asterisk 1.6 Build feature-rich telephony systems with Asterisk
Published: September 2009
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

About the Author :


Barrie Dempster

Barrie Dempster is currently employed as a Senior Security Consultant for NGS Software Ltd a world-renowned security consultancy well known for their focus in enterprise-level application vulnerability research and database security. He has a background in Infrastructure and Information Security in a number of specialised environments such as financial services institutions, telecommunications companies, call centres, and other organisations across multiple continents. Barrie has experience in the integration of network infrastructure and telecommunications systems requiring high calibre secure design, testing and management. He has been involved in a variety of projects from the design and implementation of Internet banking systems to large-scale conferencing and telephony infrastructure, as well as penetration testing and other security assessments of business critical infrastructure.

David Gomillion

David Gomillion currently serves as Director of Information Technology for the Eye Center of North Florida. There, he orchestrates all of the technological undertakings of this four-location medical practice, including computers, software (off-the-shelf and custom development), server systems, telephony, networking, as well as specialized diagnostic and treatment systems. David received a Bachelor's of Science in Computer Science from Brigham Young University in August, 2005. There he learned the theory behind his computer experience, and became a much more efficient programmer. David has worked actively in the Information Technology sector since his freshman year at BYU. He has been a Networking Assistant, an Assistant Network Administrator, a Supervisor of a large Network and Server Operations unit, a Network Administrator, and finally a Director of Information Technology. Through his increasing responsibilities, he has learned to prioritize needs and wants, and applies this ability to his Asterisk installations.

David Merel

David Merel is the founder and CEO of Thinkbright LLC a local/long distance telephone company as well as a cutting-edge Voice Over IP carrier, providing businesses of all sizes with sophisticated and low cost VOIP solutions.

David started Thinkbright in 2005 and continues to manage the company and its employees, all of whom are dedicated IT professionals. He acts as the company’s chief architect, designing new technologies that have added significant revenues to the company’s operations. During his many years at Thinkbright, David has worked with the latest Voice Over IP technology, including all VOIP equipment from major manufacturers such as Cisco, Polycom, Grandstream, and Aastra. He also works with customers ranging from small businesses to Fortune 500 companies, and interacts with system integrators and IT consultants who call Thinkbright on a daily basis for assistance with all of the VOIP solutions that Thinkbright offers. Thinkbright manages its own PBX system, providing customers with PBX features such as Auto Attendants, Waiting Rooms, and Ring Groups, or assists customers in managing their own PBX network while providing these customers with the service for incoming and outgoing calls.

David has many years of experience with Trixbox and Asterisk, and has installed countless custom configurations and deployments using those solutions.

David earned a Bachelor of Arts triple majoring in philosophy, politics and law from SUNY Binghamton. David holds a CCNA (a Cisco Certified Network Associate) certificate and is proficient in over 10 languages and databases, various operating systems, VOIP and related protocol, and other business applications.

Books From Packt

FreePBX 2.5 Powerful Telephony Solutions
FreePBX 2.5 Powerful Telephony Solutions

Cacti 0.8 Network Monitoring
Cacti 0.8 Network Monitoring

Building Enterprise Ready Telephony Systems with sipXecs 4.0
Building Enterprise Ready Telephony Systems with sipXecs 4.0

Building Telephony Systems with OpenSER
Building Telephony Systems with OpenSER

trixbox CE 2.6
trixbox CE 2.6

Asterisk 1.4 – the Professional’s Guide
Asterisk 1.4 – the Professional’s Guide

Zabbix 1.6 Network Monitoring [RAW]
Zabbix 1.6 Network Monitoring [RAW]

ModSecurity 2.5
ModSecurity 2.5

 

 

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software