Chapter 19. Fax

Have no fear of perfection. You’ll never reach it.

Salvador Dali

The concept of facsimile transmission has been around for over 100 years, but it was not until the 1980s that the use of fax machines became essential in business. This lasted for perhaps two decades. Then the Internet came along, and very shortly after that, the fax quickly became almost irrelevant.

What Is a Fax?

A fax machine allows a facsimile (copy) of a document to be transmitted across a telephone line. In the Internet age, this sort of functionality seems useless; however, prior to ubiquitous Internet access, this was a very useful thing indeed. Fax machines scan a document into a digital format, transmit the digital information in a manner similar to that used by an analog modem, and then convert and print the received information on the other end.

Ways to Handle Faxes in Asterisk

Asterisk offers the ability to both send and receive faxes, but it should be noted that all Asterisk is doing is the basics of fax transport. This means that providing a complete experience to your users will require external programs and resources beyond what Asterisk delivers.

Asterisk Fax can:

  • Recognize an incoming fax connection, and negotiate a session

  • Store (receive) the incoming fax as a Tagged Image File Format (TIFF) file

  • Accept TIFF files in a fax-compatible format

  • Transmit TIFF files to another fax machine

Asterisk Fax cannot:

  • Print faxes

  • Accept documents for transmission in any format other than TIFF

Receiving is relatively simple, since the format of the document is determined at the sending end, and thus all Asterisk needs to do is store the document.

Transmitting is somewhat more complex, since the transmitting end is responsible for ensuring that the document to be sent is in the correct format for faxing. This typically places a burden on the user to understand how to create a properly formatted document, or requires complex client or server software to handle the formatting (for example, through a print driver installed on the local PC) and placement of the fax job in a location where the server can grab it and transmit it.

spandsp

Initially, the only way to handle faxing in Asterisk was through the spandsp library. spandsp provides a multitude of Digital Signal Processing (DSP) capabilities, but in this context all we are interested in is its fax functionality.

Asterisk has the hooks built in to make use of spandsp, but due to incompatible licenses, the spandsp libraries must be downloaded and compiled separately from Asterisk. Also, since spandsp was not written only for Asterisk, it will not assume that it is being installed for Asterisk. This means that a few extra steps will be required to ensure Asterisk can use spandsp.

Obtaining spandsp

As of this writing, the current version of spandsp is 0.0.6.

Download and extract the spandsp source code as follows:

$ mkdir ~/src/asterisk-complete/thirdparty
$ cd ~/src/asterisk-complete/thirdparty
$ wget http://www.soft-switch.org/downloads/spandsp/spandsp-0.0.6pre17.tgz
$ tar zxvf spandsp-0.0.6pre17.tgz
$ cd spandsp-0.0.6

Compiling and Installing spandsp

The spandsp software should compile and install with the following commands:

$ ./configure
$ make
$ sudo make install

This will install the library in the /usr/local/lib/ folder. On many Linux systems this folder is not automatically part of the library path (libpath), so it will need to be added manually.

Adding the spandsp Library to Your libpath

In order to make the spandsp library visible to all applications on the system, the folder where it is located must be added to the libpath for the system. This is typically done by editing files in the /etc/ld.so.conf.d/ directory. You simply need to ensure that one of the files in that directory has /usr/local/lib listed. If not, the following command will create a suitable file for you:

$ sudo cat >> /etc/ld.so.conf.d/usrlocallib.conf
/usr/local/lib

Press Ctrl+D to save the file, then run the ldconfig command to refresh the library paths:

$ sudo ldconfig

You are now ready to recompile Asterisk for spandsp support.

Recompiling Asterisk with spandsp Support

Since the spandsp library was probably not installed on the system when Asterisk was first compiled, you will need to do a quick recompile of Asterisk in order to have the spandsp support added:

$ cd ~/src/asterisk-complete/asterisk/1.8/
$ ./configure
$ make menuselect

Ensure that under the Resource Modules heading, the section for spandsp looks like this:

[*] res_fax_spandsp

If you see this instead:

XXX res_fax_spandsp

It means that Asterisk was not able to find the spandsp library.

Once you have verified that Asterisk can see spandsp, you are ready to recompile. Save and exit from menuselect, and run the following:

$ make
$ make install

You can verify that spandsp is working with Asterisk by issuing the following command from the Asterisk CLI:

*CLI> module show like res_fax_spandsp.so

At this point the SendFAX() and ReceiveFAX() dialplan applications will be available to you.

Disabling spandsp (Should You Want to Test Digium Fax)

The spandsp library and the Digium fax library, discussed in the next section, are mutually exclusive. If you want to try out the Digium fax product, you will need to ensure that spandsp does not load. To disable spandsp in Asterisk, simply edit your /etc/asterisk/modules.conf file as follows:

noload => res_fax_spandsp.so

Save the changes and restart Asterisk.

Digium Fax For Asterisk

Digium Fax For Asterisk (FFA) was developed out of a strong desire from the Asterisk community to have a Digium-supported fax mechanism in Asterisk. Free for single-channel use, this product can also be licensed from Digium to handle more than one simultaneous fax channel.

Obtaining Digium FFA

Digium FFA can be obtained from the Digium website (http://www.digium.com). The process of downloading, installing, and registering this library is thoroughly documented in the Fax For Asterisk Administrator Manual, which you can also download from Digium. You will need to register at the Digium website in order to obtain your free single-channel fax license key and download the admin manual. There is also a comprehensive README file included with the software, which details the steps necessary to get Digium FFA going on your system.

Disabling Digium FFA (Should You Want to Test spandsp)

The Digium FFA library and the spandsp library are mutually exclusive. If you want to try out spandsp, you will need to ensure that Digium FFA does not load. To disable FFA, simply edit your /etc/asterisk/modules.conf file as follows:

noload => res_fax_digium.so

Save the changes and restart Asterisk.

Incoming Fax Handling

Received faxes are commonly encoded in Tagged Image File Format (TIFF). This graphics file format, while not as well known as JPEG or GIF, is not as obscure as one might think. In fact, we suspect your computer (whether you’re running Windows, Linux, or MacOS) will already have the ability to interpret TIFF files built in. While it has become popular to offer PDF as a delivery format for received faxes, we’re not sure this is strictly required, since TIFF is so ubiquitous.

Received faxes will be stored by Asterisk as files. Where those files are stored will depend on several factors, including:

  • What software you are using to simulate a fax modem (e.g., IAXmodem, Digium ReceiveFAX, etc.)

  • The location in your filesystem that you have configured for storage of received faxes

  • Any post-receipt processing you have decided to perform on the files

In the dialplan, you will need to build in enough intelligence to name faxes in such a way that they will be distinct from each other. There are many channel variables and functions that can be used for this purpose, such as the STRFTIME() function. Asterisk can easily handle capturing the fax to a file, but you will need to make sense out of what happens to that file once it is stored on the system.

Fax to TIFF

The Tagged Image File Format is not very well known, but it is actually more common than you might realize, and since it is natively supported on Windows, MacOS, and Linux, TIFF files can be viewed on pretty much any computer with the most basic graphics viewer. A subset of the TIFF file format has for a long time been the de facto file format used for faxes.

Since Asterisk will receive and store faxes in TIFF format, there is no post-processing required. Once the incoming fax call has been completed, the resulting TIFF file can be opened directly from the folder where it was stored (or perhaps emailed to the intended user).

Fax to Email

Once Asterisk has received a fax, the resulting TIFF file needs a way to get to its final destination: a person.

The key consideration is that unless the information that Asterisk knows about the fax is sufficiently detailed, it may not be possible to deduce the intended recipient without having someone actually read the fax (it is common for a fax to have a cover page with the recipient’s information written on it, which even the most capable text recognition software would have a difficult time making sense of). In other words, unless you dedicate a DID to each user who might receive a fax, Asterisk isn’t going to be able to do much more than send all faxes to a single email address. You could code something in the dialplan to handle this, though, or have an external cron job or other daemon handle distributing the received faxes.

A simple dialplan to handle fax to email might look something like this (you will need the mail program mutt installed on your system):

exten => fax,1,Verbose(3,Incoming fax)
; folder where your incoming faxes will initially be stored
  same => n,Set(FAXDEST=/tmp) 

; put a timestamp on this call so the resulting file is unique
  same => n,Set(tempfax=${STRFTIME(,,%C%y%m%d%H%M)}) 
  same => n,ReceiveFax(${FAXDEST}/${tempfax}.tif)
  same => n,Verbose(3,- Fax receipt completed with status: ${FAXSTATUS})

; *** This line should not have any line breaks
  same => n,System(echo | mutt -a ${FAXDEST}/${tempfax} 
-s "received fax" [email protected])

Obviously, this sample would not be suitable for production (for example, it does not handle fax failure); however, it would be enough to start prototyping a more fully featured incoming fax handler.

Fax Detection

You may have a dedicated phone number for receiving faxes. However, with Asterisk, that is not a requirement. Asterisk has the ability to detect that an incoming call is a fax and can handle it differently in the dialplan. Fax detection is available for both DAHDI and SIP channels. To enable it for DAHDI, set the faxdetect option in /etc/asterisk/chan_dahdi.conf. In most cases, you should set this option to incoming. Table 19-1 lists the possible values for the faxdetect option in chan_dahdi.conf.

Table 19-1. Possible values for the faxdetect option in chan_dahdi.conf

ValueDescription
incomingEnables fax detection on inbound calls. When a fax is detected, applies the faxbuffers option if it has been set and redirects the call to the fax extension in the dialplan. For more information on the faxbuffers option, see Using Fax Buffers in chan_dahdi.conf.
outgoingEnables fax detection on outbound calls. The dialplan is not executing on an outbound channel. If a fax is detected, the faxbuffers option will be applied and the channel will be redirected and start executing the dialplan at the fax extension.
bothEnables fax detection for both incoming and outgoing calls.
noDisables fax detection. This is the default.

To enable fax detection for SIP calls, you must set the faxdetect option in /etc/asterisk/sip.conf. This option may be set in the [general] section, or for a specific peer. Table 19-2 covers the possible values for the faxdetect option in sip.conf.

Table 19-2. Possible values for the faxdetect option in sip.conf

ValueDescription
cngEnables fax detection by watching the audio for a CNG tone. If a CNG tone is detected, redirects the call to the fax extension in the dialplan.
t38Redirects the call to the fax extension in the dialplan if a T.38 reinvite is received.
yesEnables both cng and t38 fax detection.
noDisables fax detection. This is the default.

Outgoing Fax Handling

Transmitting faxes from Asterisk is somewhat more difficult than receiving them. The reason for this is simply due to the fact that the preparation of the fax prior to transmission involves more work. There isn’t anything particularly complex about fax transmittal, but you will need to make some design decisions about things like:

  • How to get the source fax file formatted for Asterisk

  • How to get the source fax file onto the Asterisk system (specifically, into some folder where Asterisk can access it)

  • What to do with transmitted faxes (save them? delete them? move them somewhere?)

  • How to handle transmission errors

Transmitting a Fax from Asterisk

To transmit a fax from Asterisk, you must have a TIFF file. How you generate this TIFF is important, and may involve many steps. However, from Asterisk’s perspective the sending of a fax is fairly straightforward. You simply run the SendFAX() dialplan application, passing it the path to a valid TIFF file:

exten => faxthis,1,SendFAX(/path/to/fax/file,d)

In practice, you will normally want to set some parameters prior to transmission, so a complete extension for sending a fax using Digium’s Fax For Asterisk might look something like this:

exten => faxthis,1,Verbose(2,Set options and transmit fax)

; some folder where your outgoing faxes will be found
  same => n,Set(faxlocation=/tmp) 

; In production you would probably not want to hardcode the filename
  same => n,Set(faxfile=faxfile.tif) 
  same => n,Set(FAXOPT(headerinfo)=Fax from ShiftEight.org)
  same => n,Set(FAXOPT(localstationid=4169671111)
  same => n,SendFax(${faxlocation}/${faxfile})

File Format for Faxing

The real trick of sending a fax is having a source file that is in a format that the fax engine can handle. At a basic level, these files are known as TIFF files; however, the TIFF spec allows for all sorts of parameters, not all of which are compatible with fax and not many of which are documented in any useful way. Additionally, the types of TIFF formats that spandsp can handle are different from those Digium FFA will handle.

In the absence of one simple, clear specification of what TIFF file format will work for sending faxes from Asterisk, we will instead document what we know to work, and leave it up to the reader to perform any experimentation required to find other ways to generate the TIFF.[165]

Digium’s Fax For Asterisk Administration Manual documents a process for converting a PDF file into a TIFF using commonly available Linux command-line tools. While kludgy, this method should allow you to build Linux scripts to handle the file conversion, and your users will be able to submit PDFs as fax jobs.

You will need the ghostscript PDF interpreter, which can be installed in CentOS by the command:

$ sudo yum -y install ghostscript

and in Ubuntu with:

$ sudo apt-get install ghostscript

Once installed, ghostscript can convert the PDF into an Asterisk-compatible TIFF file with the following command:

$ gs -q -dNOPAUSE -dBATCH -sDEVICE=tiffg4 -sPAPERSIZE=letter -sOutputFile=<dest> <src>

Replace <dest> with the name of the output file, and specify the location of your source PDF with <src>.

The ghostscript program should create a TIFF file from your PDF that will be suitable for transmission using Asterisk SendFax().

An Experiment in Email to Fax

Many users would like to be able to send emails as fax documents. The primary challenge with this is ensuring that what the users submit is in a format suitable for faxing. This ultimately requires some form of application development, which is outside the scope of this book.

What we have done is provided a simple example of some methods that at least provide a starting point for delivering email to fax capabilities.

One of the first changes that you would need to make in order to handle this is a change to your /etc/aliases file, which will redirect incoming faxes to an application that can handle them. We are not actually aware of any app that can do this, so you’ll have to write one. The change to your /etc/aliases file would look something like this:

fax:   "| /path/to/program/that/will/handle/incoming/fax/emails"

In our case, Russell built a little Python script called fax.py, so our /etc/aliases file would read something like this:

fax:   "| /asteriskpbx/fax.py"

We have included a copy of the Python script we developed for your reference in Example 19-1. Note that this file is not suitable for production, but merely serves as an example of how a very basic kind of email to fax functionality might be implemented.

Example 19-1. Proof of concept email to fax gateway, fax.py

#!/usr/bin/env python
"""Poor Man's Email to Fax Gateway.

This is a proof of concept email to fax gateway.  There are multiple aspects
that would have to be improved for it to be used in a production environment.

Copyright (C) 2010 - Russell Bryant, Leif Madsen, Jim Van Meggelen
Asterisk: The Definitive Guide
"""

import sys
import os
import email
import base64
import shutil
import socket


AMI_HOST = "localhost"
AMI_PORT = 5038
AMI_USER = "hello"
AMI_PASS = "world"

# This script will pull a TIFF out of an email and save it off to disk to allow
# the SendFax() application in Asterisk to send it.  This is the location on
# disk where the TIFF will be stored.
TIFF_LOCATION = "/tmp/loremipsum.tif"


# Read an email from stdin and parse it.
msg = email.message_from_file(sys.stdin)

# For testing purposes, if you wanted to read an email from a file, you could
# do this, instead.
#try:
#    f = open("email.txt", "r")
#    msg = email.message_from_file(f)
#    f.close()
#except IOError:
#    print "Failed to open email input file."
#    sys.exit(1)

# This next part pulls out a TIFF file attachment from the email and saves it
# off to disk in a format that can be used by the SendFax() application.  This
# part of the script is incredibly non-flexible.  It assumes that the TIFF file
# will be in a specific location in the structure of the message (the second
# part of the payload, after the main body).  Further, it assumes that the
# encoding of the TIFF attachment is base64.  This was the case for the test
# email that we were using that we generated with mutt.  Emails sent by users'
# desktop email clients will vary in _many_ ways.  To be used with user-
# generated emails, this section would have to be much more flexible.
try:
    f2 = open(TIFF_LOCATION, "w")
    f2.write(base64.b64decode(msg.get_payload()[1].get_payload().replace("
", "")))
    f2.close()
except IOError:
    print "Failed to open file for saving off TIFF attachment."
    sys.exit(1)

# Now that we have a TIFF file to fax, connect to the Asterisk Manager Interface
# to originate a call.
ami_commands = """Action: Login

Username: %s

Secret: %s



Action: Originate

Channel: Local/s@sendfax/n

Context: receivefax

Extension: s

Priority: 1

SetVar: SUBJECT=%s



Action: Logoff



""" % (AMI_USER, AMI_PASS, msg['subject'])

print ami_commands

def my_send(s, data):
    """Ensure that we send out the whole data buffer.
    """
    sent = 0
    while sent < len(data):
        res = s.send(data[sent:])
        if res == 0:
            break
        sent = sent + res

def my_recv(s):
    """Read input until there is nothing else to read.
    """
    while True:
        res = s.recv(4096)
        if len(res) == 0:
            break
        print res

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((AMI_HOST, AMI_PORT))
my_send(s, ami_commands)
my_recv(s)
s.shutdown(socket.SHUT_RDWR)
s.close()

We tested this out at a very rudimentary level, and proved the basic concept. If you want to put email to fax into production, you need to understand that you will have more work to do on the application development side in order to deliver something that will actually be robust enough to turn over to an average group of users.

Fax Pass-Through

In theory, it should be possible to connect a traditional fax machine to an FXS port of some sort and then pass incoming faxes to that device (see Figure 19-1). This concept is attractive for a few reasons:

  1. It allows you to integrate existing fax machines with your Asterisk system.

  2. It requires far less configuration in the dialplan.

Unfortunately, fax pass-through is not the home run we would like it to be. The analog carrier signal that two fax machines use to communicate is a delicate thing, and any corruption of that signal will often cause a transmission failure. In an Asterisk system performing pass-through, internal timing issues, coupled with signal attenuation, can create an environment that is unstable for fax use, especially for larger (multipage) faxes.

Typical fax pass-through

Figure 19-1. Typical fax pass-through

If you are using fax on a casual basis (mostly noncritical, one-page faxes), this sort of setup can work well. If faxing is critical to your business, or you are often expecting multipage faxes, we must reluctantly recommend that you connect your fax machines directly to the PSTN and leave Asterisk out of it.

Using Fax Buffers in chan_dahdi.conf

Many of the problems with fax pass-through are caused by inconsistent timing. Since faxes are more tolerant of latency than voice calls (a fax has to be able to travel halfway around the world, which takes a few dozen milliseconds), the introduction of a buffer in DAHDI (which is strictly used for faxes) has reportedly corrected many of the problems that have plagued fax pass-through.

As of this writing, this is a fairly new configuration option. The currently preferred setting is as follows:

faxbuffers => 12,half

This would be placed in your /etc/asterisk/chan_dahdi.conf file and would cause chan_dahdi to create a 96 ms buffer for fax calls and delay start of transmission until the buffer was half full.

You would also need to set faxdetect, since the fax buffers are part of the faxdetect functionality:

faxdetect = both

We have not extensively tested this capability yet, but anecdotal evidence suggests that this should greatly improve the performance of fax pass-through in Asterisk.

Conclusion

Fax is a technology whose days are behind it. Having said that, it remains popular. Asterisk has some interesting technology built into it that allows you some level of creativity in how you handle faxes. With careful planning and system design, and a patient prototyping and debugging phase, you can use your Asterisk system to handle faxing in creative ways.



[165] One format we tried was using the Microsoft Office Document Image Writer, which offers “TIFF-monochrome fax” as an output format. This seemed too good to be true, which is exactly what it turned out to be (neither spandsp nor Digium FFA could handle the resulting file). It would have been ideal to have found something common to Windows PCs that could be used by users to “print” an Asterisk-compatible TIFF file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset