Fax

Fax

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 Asterisk is only doing 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.6pre21.tgz
$ tar zxvf spandsp-0.0.6pre21.tgz
$ cd spandsp-0.0.6

Compiling and Installing spandsp

As spandsp relies heavily on image libraries, you will need to install several dependent packages. Ubuntu makes this relatively easy, because you can install one package and dependencies take care of the rest:
$ sudo apt-get install libtiff-dev
Or, on RHEL:
$ sudo yum install -y libtiff-devel

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/11/
$ ./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
;noload => res_fax_digium.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. 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. We also recommend running the benchfax test program multiple times to verify which processor core is best on your system. In one case, the FFA core optimized for the Core 2 Duo actually performed better on an old dual-core Pentium II system, which was clearly incorrect. Repeat testing bore out which core produced consistently better results.

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
;noload => res_fax_spandsp.so

We typically put the noload statements in pairs, then uncomment only one of them, depending upon which one we want to test. This makes switching between them as simple as commenting one out and uncommenting the other.

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. It has become popular to offer PDF as a delivery format for received faxes mainly due to many TIFF image viewers only expecting a single image contained within. If you’re viewing a received TIFF image, expecting to see multiple pages, and only the first page is shown, the image viewer is often the culprit. It is often easier simply to translate your TIFF image to a PDF and view that, rather than trying to figure out which image program will let you see the multiple pages of a TIFF fax image.

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)
• 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 so 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

A subset of the TIFF file format has for a long time been the de facto file format used for faxes. However, as image viewers regularly only show the first page of a fax stored within a TIFF, directly viewing the image often results in a disappointment (or worse, a false diagnosis that only the first page seems to have been received).

Once the incoming fax call has been completed, the resulting TIFF file can be opened directly from the folder where it was stored or converted to PDF. You can install a helpful command-line utility called tiff2pdf to do the translation, which can be installed on RHEL with the command:
$ sudo yum install libtiff
and on Ubuntu with:
$ sudo apt-get install libtiff-tools

Once installed, the program can be a little tricky; it will output the source of the PDF to your screen, unless you redirect the output to a file. This apparent shortcoming of the utility is actually a feature; we use it with mail attachments that can take a command as an argument, so the TIFF image is stored on our Asterisk server, since it is smaller than the resulting PDF. If that seems too complicated, you can also simply create a PDF file:
$ tiff2pdf filename.tiff > filename.pdf

or, use the command to send the aforementioned attachment without storing an intermediate file:

#!/usr/bin/perl

use MIME::Lite;
my ($filename,$person,$email) = @ARGV;

my $msg = MIME::Lite->new(
From     => ‘fax-server@shifteight.org’,
To         => $email,
Subject => “Fax received!”,
Type     => ‘multipart/mixed’
);
$msg->attach(
Type   => ‘TEXT’,
Data    => “Dear $person,\n\n\tYou have received a fax. ” .
“It is attached.\n\n–The ShiftEight Fax Server\n”
);
$msg->attach(
Type    => ‘application/pdf’,
Path     => “/usr/bin/tiff2pdf -a \”$cidname\”
“/var/spool/asterisk/faxes/$filename |”,
Filename     => “fax.pdf”,
Disposition => ‘attachment’
);
$msg->send;
The use of the MIME::Lite package is beyond the scope of this book; however, as it makes it very easy to illustrate the use of the tiff2pdf utility, we felt it was worth its inclusion.

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 Asterisk knows enough detail about the fax, 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 dif‐ ficult 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 above Perl script installed as /opt/asteriskbook/bin/sendfax.pl):

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(/opt/asteriskbook/bin/sendfax.pl ${FAXDEST}/${tempfax}.tif
“Leif Madsen” lmadsen@shifteight.org)

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 -1. Possible values for the faxdetect option in chan_dahdi.conf

b11

b12

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 -2 covers the possible values for the faxdetect option in sip.conf.

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

b13

Using T.38

One of the first things you’ll notice when trying to receive faxes from a VoIP service provider is the outstanding rate of failures. As discussed above, fax is particularly finicky about the latency between the endpoints, and some fax machines simply will give up quickly rather than trying to negotiate, while others will work fine. In a strictly audio- based fax-over-VoIP scenario, we’ve seen a success rate of less than 50 percent when attempting to receive faxes, and many sending fax machines simply won’t work at all. T.38 is particularly helpful here, as the protocol is designed to negotiate around this issue with latency. In its simplest sense, T.38 simply receives the fax piecemeal on one side, sends the resulting pieces of the image over VoIP, then retransmits the fax on the other end. By avoiding the idiosyncrasies of the fax signal, the success rate can be increased to over 90 percent.

Fortunately, there’s very little you need to do to enable the T.38 signaling; simply enable
t38pt_udptl in sip.conf:
t38pt_udptl = yes
This enables T.38 fax negotiation, if the remote endpoint supports it, and if not, SendFax will attempt to fall back to audio-based transmittal.

Outgoing Fax Handling

Transmitting faxes from Asterisk is somewhat more difficult than receiving them. The reason is simply 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 into 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,NoOp()
same => n,SendFAX(/path/to/fax/file,dz)

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 some‐thing 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},z)

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 experiment to find other ways to generate the TIFF.

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 RHEL 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, which presents the challenge of ensuring that users submit their documents 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.

To provide this capability, one of the first things you’d have to do is make a change to your /etc/aliases file, to 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”

Example-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-2013 – 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(“\n”, “”)))
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\r
Username: %s\r
Secret: %s\r
\r
Action: Originate\r
Channel: Local/s@sendfax/n\r
Context: receivefax\r
Extension: s\r
Priority: 1\r
SetVar: SUBJECT=%s\r
\r
Action: Logoff\r
\r
“”” % (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 at a very rudimentary level and proved the basic concept. If you want to put email-to-fax into production, you should understand that you will have more work to do before you have something actually 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 -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.

B1.1

Figure -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.

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 3 buffer for fax calls and delay the 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.

T.38 Gateway

Another form of fax pass-through is T.38 gateway support, which was added in Asterisk 10. In this scenario, Asterisk is passing through a fax with a T.38-capable endpoint on one side and a traditional fax endpoint on the other. One example would be if you had a fax machine connected to an FXS port on the Asterisk machine and forwarded the fax calls out to a SIP provider that supports T.38.

This example scenario is fairly straightforward to implement. The key is enabling T.38 gateway support using the FAXOPT dialplan function. For this example, let us assume that all outgoing fax calls from the local fax machine are sent to the outgoing-fax
context. The following dialplan would enable T.38 gateway support and send the call off to the T.38-capable SIP provider:

        [outgoing-fax]

exten => _1NXXNXXXXXX,1,NoOp()
same => n,Set(FAXOPT(gateway)=yes)
same => n,Dial(SIP/t38provider)
Additionally, you can set a timeout on the T.38 gateway mode so that it gets turned back off if there is no fax activity within the specified timeout. To set the timeout, it’s provided as a part of setting the FAXOPT function:
; Disable T.38 gateway if there is no fax activity within 10 seconds
same => n,Set(FAXOPT(gateway)=yes,10)