Switching to VoIP
14.1. Fax and Modems
Fax machines and modems encode digital data into analog sound signals for transport across the PSTN. At the local CO, these analog sound signals are digitized into PCM digital signals at 64 kbps. After being transported over the network, the CO at the opposite end of the link decodes the PCM signal and plays it back for the analog receiver, whose job it is to reassemble it into a facsimile of the original digital data. Since the maximum rate of transmission on a POTS line is 64 kbps, faxes and modems can't transmit data very quickly (one twenty-fourth the speed of a T1). Even with compression techniques, which introduce signaling overhead, most modems will never transmit data faster than about 54 kbps. They are limited by the digital resolution of the sound pathway they use.
The challenge posed by VoIP is this: codecs like G.729A distort the sound signal by compressing it using lossy vocoder algorithms such as CELP. When a modem or fax's analog sound signal is encoded and decoded using vocoders, it becomes distorted , such that the device on the receiving end of the transmission is receiving a different analog signal than the one that was sent. The side effect of compressed VoIP codecs is that faxes and modems simply don't work. So devices that rely on modems, such as some burglary alarm systems, TiVo consoles, and maybe that old-fashioned Amiga 1000 computer, have a hard time getting along in a VoIP network. (Series 2 TiVo devices can work using the Internet instead of a modemcheck out http://www.tivo.com/adapters.)
There are a few ways to tackle this problem. The first and most obvious is to avoid lossy codecs and use only non-lossy codecs like G.711 and G.722. It won't distort the analog modem signals as long as jitter is under control. But avoiding lossy codecs may not be possible, especially on bandwidth-starved WANs. Fortunately, the ITU has two recommendations to aid in migration of fax to VoIP. Both are discussed in this chapter. There is no real answer to the matter of modems, however. The ITU's V.150.1 standard describes how to relay modem signals over a converged network, but no open reference implementations exist yet. One could argue that it's a bit arcane to use a modem in a converged network, since any data sent by the modem could be sent hundreds of times faster using Ethernet. In other words, if you have an Ethernet connection, use that instead of the modem.
14.1.1. T.30, T.37, and T.38
The ITU's T.30 recommendation describes how fax devices should work. Just about all legacy fax machines (and fax software) are T.30-compliant. The T.38 protocol is the ITU's recommendation for sending faxes over data networks. T.38 software runs on a server that can perform T.30 fax signaling in order to send and receive fax transmissions over analog lines to fax machines. The server encodes the fax signals into packets and sends them to a T.38 server that can decode the fax signals on behalf of a receiving fax machine. This circumvents reliance on in-band faxing and increases the efficiency of fax transmission over the network. T.38 has a few nicknames, including Group 3 faxing and FoIP (Fax over IP). The T.37 protocol is another ITU recommendation. It also allows faxes to be sent over the IP network, but T.37 doesn't package fax signals into its own packets. Instead, it creates SMTP mail messages using MIME-encoded TIFF (Tagged Image File Format) files. These messages can be sent directly to an SMTP mail server for delivery to email users, or they can be sent to another T.37 server for delivery to a fax machine. T.37 has a few advantages over T.38, among them its ease of integration with standards-based email. T.37 is a store-and-forward protocol, meaning it can hold onto messages if they aren't deliverable at the moment. T.38 has no such capability. 14.1.1.1 ATAs and fax/modem support
To support a fax machine on the VoIP network, you might think all you have to do is plug it into an analog telephone adapter (ATA) and configure that adapter to only use G.711. But this won't always work. Other VoIP devices on the network may alter the sound encoding somewhere along the fax machine's call path , possibly crippling it. There are three ways to ensure faxes can traverse your VoIP network:
There's only one way to positively ensure modem traffic can traverse your VoIP network:
14.1.2. Project 14.1. Turn Your Linux Box into a Fax Machine
14.1.2.1 What you need for this project:
Asterisk offers a built-in fax-detection mechanism. This allows you to handle faxes that are sent to your Asterisk PBX on a POTS line. Asterisk's Answer( ) command triggers the fax detection. If an incoming fax is detected , Asterisk automatically transfers the call to the special extension called fax , if it exists. In order to use this special extension, you'll need to compile and install the SpanDSP package. Download the latest version from ftp.opencall.org, and unzip the file into /usr/src/spandsp . To compile it, issue these commands: # ./configure --prefix=/usr # make; make install # cp app_rxfax.c /usr/src/asterisk/apps # cp app_txfax.c /usr/src/asterisk/apps # cp Makefile.patch /usr/src/asterisk/apps # cd /usr/src/asterisk/apps # patch <Makefile.patch
These commands compile the SpanDSP package, which provides a source code patch for Asterisk. Thus, you'll need to recompile Asterisk now: # cd ../asterisk # make clean ; make install
The next step is to enable fax detection on the Zaptel channel you want to use for faxing. This doesn't stop the channel from being used for normal voice calls; it just enables the channel to discern fax calls from normal calls. To enable this function, be sure that the channel's section in /etc/asterisk/zapata.conf has this entry: faxdetect=both
The valid parameters for the faxdetect option are incoming , outgoing , both , and no . By default, fax detection is disabled. 14.1.2.2 Receiving faxes
Now, consider the following snippet from a dial-plan: [incoming-local] exten => s,1,Answer exten => s,2,Dial(SIP/202,45,rm) exten => s,3,voicemail(202) exten => fax,1,SetVar(TIFFILE=/var/spool/faxes/thisfax.tif) exten => fax,2,rxfax(${TIFFILE})
In this context, the Answer( ) command triggers fax detection. If there's no fax, the dial-plan calls for a call to SIP peer 202. If there is a fax, the fax extension takes over, saving the fax image into a TIFF file. Another script could then process the file however you see fit, perhaps printing it immediately, like this: exten => fax,1,SetVar(TIFFILE=/var/spool/faxes/thisfax.tif) exten => fax,2,rxfax(${TIFFILE}) ; dump the fax file to the default printer and remove the fax file exten => fax,3,System('tiff2ps ${TIFFILE} lpr') exten => fax,4,System('rm ${TIFFILE}')
14.1.2.3 Sending faxes
Receiving faxes with Asterisk is quite a bit easier than sending them. This is because, when receiving them, the work of scanning them into a digital form is already done. This is the part neither Asterisk nor SpanDSP addresses. These packages can very easily fax a TIFF file. So it's up to you to get that TIFF file in a path where SpanDSP can grab it. This can happen any number of ways. You could create a simple web interface that allows you to upload TIFF files to the server, or if you've got the right software, you could just scan them directly using the Linux machine. I don't recommend either of these approaches, however, because neither of them provides a straightforward way of telling Asterisk where to send the fax. Fortunately, the Hylafax package provides a solution. 14.1.3. Project 14.2. Build an Inbound Fax-to-Email Gateway
14.1.3.1 What you need for this project:
In Project 14.1, we built a configuration to direct all incoming faxes from Zaptel channels to a file, which, in turn, we could have automatically printed. But if the server were working on behalf of many possible fax recipients, we would have to rely on the incoming fax's cover sheet to know which recipient it's destined for. Worse still, we'd have to go to the printer, pick up the fax, and hand-deliver it to the correct person. There's a better way, of course: email. It's just as easy to email that TIFF file to somebody's inbox as it is to print it: exten => fax,1,SetVar(TIFFILE=/var/spool/faxes/thisfax=${CALLERIDNUM}.tif) exten => fax,2,rxfax(${TIFFILE}) ; email the fax file to the receptionist and then delete it exten => fax,3,SetVar(EMAIL=receptionist@oreilly.com) exten => fax,3,System('mewencode -e ${TIFFILE} mail -s fax ${EMAIL}') exten => fax,4,System('rm ${TIFFILE}')
This configuration receives the fax, MIME-encodes it using the mewencode command (a standard part of most Linux distributions), and emails it to the email address stored in the ${EMAIL} variable. This is a catchall solutionit sends every fax that's received to the same recipient, who can then forward (and screen if necessary) to the appropriate person based on the content of each fax message. 14.1.3.2 Automatic fax routing
In order to have the Linux server automatically route each fax to the right recipient (instead of a certain email user doing it), we must have a way of associating each fax with the correct recipient. We'll have to associate a certain line (or a certain DID) with each user, so that, whenever a fax is received on that line (or DID), we'll know where to route it. Each phone line's number, or each DID number if we're using a PRI, will become a single user 's fax number. 14.1.3.3 Fax routing with DIDs
In order to associate a DID with a particular user's email address, we can use an LDAP inquiry. An LDAP client library for Linux, openldap , provides applications the ability to access LDAP servers and perform such inquiries. Your LDAP server may be an Exchange or Lotus Domino server where directory information is stored. The Red Hat distribution includes openldap and its developer packages. But you'll need more than just the LDAP client library. You'll also need an actual LDAP client for Asterisk, like Sven Slezak's LDAPGet package. Download it from http://www.mezzo.net/asterisk and unzip it into the Asterisk source directory, /usr/src/asterisk . Next, as root, copy the app_ldap.so file into /usr/src/asterisk/apps . Then, use a text editor to add app_ldap.so to the list of applications that begin with APPS= in /usr/src/asterisk/apps/Makefile . While you've got the make file open, also add the following rule just below above the app_voicemail.so line: app_ldap.so : app_ldap.o $(CC) $(SOLINK) -o $@ $< -llber -lldap
Now, LDAPGet is ready to be compiled. Save your changes in the text editor and exit back to the shell, where you'll issue these commands to compile the package: # cd /usr/src/asterisk # make; make install
If Asterisk isn't currently running, start it. Then, go to the Asterisk command line load the LDAPGet module (alternatively, you could just restart Asterisk): pbx*CLI> load app_ldap.so pbx*CLI> show application LDAPget
The show application command will confirm the module is installed and loaded by showing you a brief description of the LDAPGet dial-plan command. Now, you can set up the LDAP inquiry your dial-plan will use to get email addresses based on the DID provided by ${EXTEN} . To set this query up, open /etc/asterisk/ldap.conf . It may not exist yet, since you've only just compiled the LDAP module. Create an entry like this in ldap.conf : [mailfromdid] host = ldap.oreilly.com user = cn=root,ou=People,o=oreilly.com pass = jarsflood base = ou=Addressbook,o=oreilly.com filter = (&(objectClass=person)((fax=%s))) attribute = email convert = UTF-8,ISO-8859-1
This configuration will cause the LDAP inquiry to ldap.oreilly.com asking for an object of the person class with the attribute fax equal to the value of the %s token (which will be replaced with the DID at runtime). The attribute setting tells the inquiry which attribute from the object to return as a value to the dial-plan's variable. This may seem confusing right now, but it should be clearer once you see how the LDAPGet command is used in the dial-plan. In the context where your incoming PSTN calls begin (specified in zapata.conf ), you can capture the DID from the ${EXTEN} variable, and use it to supply an argument to an LDAP inquiry. If the inquiry is successful, Asterisk's LDAP client will return the email address to which the fax number (i.e., DID) is associated, as in this snippet of extensions.conf : [incoming-pstn] exten => s,1,SetVar(DID=${EXTEN}) exten => s,2,Answer exten => s,3,Ringing ; allow 4 seconds for the fax detection exten => s,4,Wait(4) ; if no fax, send this call to be handled elsewhere exten => s,3,GoTo(incoming-voice) ; here's the fax handling extension, which sends the call to the ; 'inc-fax' context exten => fax,1,Goto(inc-fax,1,1) [inc-fax] exten => s,1,SetVar(TIFFILE=/var/spool/faxes/${DID}.tif) ; The 'mailfromdid' LDAP inquiry is defined in Asterisk's ldap.conf file. exten => s,2,LDAPGet(EMAIL=mailfromdid/${DID}) ; If the LDAP inquiry succeeds, priority will be 2+1. exten => s,3,rxfax(${TIFFILE}) exten => s,4,GoTo(105) ; If the LDAP lookup fails, priority will be 2+101. exten => s,103,SetVar(EMAIL=receptionist@oreilly.com) exten => s,104,rxfax(${TIFFILE}) ; Now, email the fax file to whichever email address was decided upon. exten => s,105,System('uuencode ${TIFFILE} uuenc mail -s fax ${EMAIL}') exten => s,106,System('rm ${TIFFILE}') [incoming-voice] ; non-fax calls are handled here
The sum of all this compiling and config-tuning is that different email recipients now have assigned fax numbers on the PRI (or assigned POTS lines for their exclusive use as inbound fax lines). When you send a fax to Todd's fax number, Todd receives the email. When you send it to Susie's, Susie receives the email, and so on. Of course, it's up to you to populate your LDAP server with the right information and to make sure the inquiry config in ldap.conf matches your LDAP server's schema.
14.1.3.4 For those who prefer PDF files
In the last project, we used the tiff2ps command to create a printable version of the fax, but with a few extra steps, we can turn it into a PDF file, too. PDF may be preferable to TIFF when using email as we are in this project. Consider the following dial-plan changes to the [inc-fax] context: exten => s,105,System('tiff2ps -2eaz -w 8.5 -h 11 ${TIFFILE} ps2pdf \ >${TIFFILE}.ps') exten => s,106,System('uuencode ${TIFFILE}.ps uuenc mail -s fax ${EMAIL}') exten => s,107,System('rm -f ${TIFFILE}*')
Now, instead of just encoding the TIFF file and emailing it, the file is converted to a PostScript file, then to a PDF file, before being uuencoded and emailed to the appropriate recipient. 14.1.3.5 Simulating T.37
This project can be taken one step further, to crudely simulate T.37that is, using SMTP to trunk faxes back and forth between email systems that have analog fax endpoints connected to them. In a scenario with three offices and multiple fax machines at each office, you could build a fax bank that routes the faxes to the right machines, anywhere within those three offices. Each participating server would be configured to package incoming faxes into mail messages, as before, but they'd also need to be able to automatically decode incoming email, save the TIFF file attachment to a temporary directory, and fax it to the correct fax machine using the SpanDSP txfax( ) dial-plan command. 14.1.4. FoIP Solutions
14.1.4.1 Cisco AVVID
Cisco media gateway routers can host analog telephone ports. Cisco implements T.37 and T.38 protocols on their analog telephone interface cards, so that, once you provision T.37 or T.38, you can connect a fax machine and have reliable faxing over IP. IOS commands are provided for administration of fax functionality on firmware loads for the Cisco 2600XM, 2800, 3700, and 3800 series routers. More information is available by searching Cisco's web site at http://www.cisco.com. 14.1.4.2 Avaya Media Servers
The Communication Manager software platform for Avaya's Media Server chassis provides support for fax machines connected to analog ports. Avaya supports both T.37 and T.38, though its T.38 support is older and more refined. Only Media Servers with analog ports can host fax machines. More information is available by searching Avaya's web site at http://www.avaya.com. 14.1.4.3 Other solutions
Nortel, Alcatel, and other, smaller vendors offer T.38 support. Chapter 16 contains a listing of web sites for commercial PBX vendors so you can investigate commercial solutions further. 14.1.4.4 Commercial soft fax solutions
Since fax is a largely legacy technology that has been replaced, for better or worse, by email, you may want to consider the option of dropping the use of fax machines and switching to a 100% soft environment for faxing. Commercial software products like Interstar's Lightingfax and ACCPAC's faxServe can turn a Windows server into a fax concentrator that can route incoming and outgoing faxes to and from users' desktops. For a Macintosh-compatible commercial solution, try 4-sight fax from Soft Solutions. 14.1.4.5 Hylafax
Without a lot of hacking, Asterisk just doesn't make a good day-to-day, occasional -use fax server for outbound fax transmittals. There are better solutions to this need already. One of them is Hylafax, a freely available fax server for Linux and BSD operating systems. Hylafax can use standard fax/modems, which also makes it cheaper to implement than Asterisk with (comparatively expensive) Digium voice cards. Hylafax can be obtained from http://www.hylafax.org. 14.1.5. Hosted Fax
If all that dial-plan configuration seems a bit over the top, consider using a hosted fax service provider instead. Some service providers host fax servers with lots of PRI circuits, allowing subscribers to send and receive faxes from a desktop computer using the Internet. This is a stress-free alternative to implementing FoIP. Here is a partial list of hosted fax service providers:
|