Linux Fax Stack using Hylafax and t38modem
Find a file
2024-08-12 13:44:52 +02:00
README.md added libspandsp-dev dependency and note to ATO modem command 2024-08-12 13:44:52 +02:00

Linux Fax Stack Setup (HylaFax & SIP)

Linux Fax Stack using Hylafax and t38modem.

THIS GUIDE IS WIP

This guide was created using information from the opalvoid wiki (http://wiki.opalvoip.org/index.php?n=Main.HomePage)

Softwarestack

ptlib

(legacy) library for doing a little bit of everything.

Opal

Voice codec used by e.g. mumble.

t38modem

Emulates a serial modem from SIP connetion

Hylafax

Enterprise grade software, managing physical and emulated modems.

Has some problems: https://github.com/lexbailey/compilerfax/blob/main/hylafax_is_broken

Operating Systems

Unfortunately this software stack uses a lot of legacy software. Because of this, this guide was only tested on specific software versions

Debian 12 Bookworm

For Debian 12, we´ll only install dependencies which are hard requirements. For this guide we'll use ptlib 2.18.6 and opal 3.18.6.

Installing Requirements

First we'll need some packages

apt-get install build-essential git wget pkg-config libssl-dev libsrtp2-dev libspandsp-dev -y

Download sourcecode

Versions:

ptlib

./configure
make
make install

opal

./configure
make -j5
make runtest
make install

t38modem

If you are getting error about -1 not being able to be casted to a long unsigned int due to -Wnarrowing inside dle.cxx, you can add -Wno-narrowing after the CPPFLAGS in the Makefile to disable this error

git clone https://github.com/hehol/t38modem
cd t38modem
make

If running the t38modem executable, you should run these commands

cp /usr/local/lib/libpt.so.2.18.6 /lib
cp /usr/local/lib/libopal.so.3.18.6 /lib

To install t38modem run

cp ./t38modem /usr/local/bin

Ubuntu 20.04 LTS

Was tested on Ubuntu 20.04 LTS VM (VirtualBox, LXC?)

You can relies heavily on http://wiki.opalvoip.org/index.php?n=Main.HomePage

Versions:

Follow http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix and http://wiki.opalvoip.org/index.php?n=Main.HomePage but

  • Don't use libavformat-dev -> Compile error in Opal
  • Configure script needs pkg-config to be installed to find ptlib install
  • On SourceForge downloads .tar.bz2 files for *nix

Build PTLib

sudo apt install \
	g++ git make autoconf libpcap-dev libexpat1-dev libssl-dev libsasl2-dev libldap2-dev \
	unixodbc-dev liblua5.3-dev libv8-dev libncurses-dev libsdl2-dev \
	libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev pkg-config
  • PTLib will be installed in the /usr/local tree -> set PKG_CONFIG_PATH to be findable (compile time)
  • Set LD_LIBRARY_PATH to find PTLib at compile and run time
  • Set PTLIBPLUGINDIR (compile and run time)
  • (To compile as static library: ./configure --disable-shared)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z # compile and run time
 
cd ptlib-x.y.z/
./configure
make
sudo make install

Build Opal

sudo apt install \
	libsrtp2-dev libgsm1-dev libspeex-dev libopus-dev libx264-dev \
	libvpx-dev libtheora-dev libspandsp-dev dahdi
  • (To compile as static library: ./configure --disable-shared)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # compile and run time

cd opal-a.b.c/
./configure
make
sudo make install

t38modem

  • https://github.com/hehol/t38modem, Version 4.6.2
  • If you are getting error about -1 not being able to be casted to a long unsigned int due to -Wnarrowing inside dle.cxx, you can add -Wno-narrowing after the CPPFLAGS in the Makefile to disable this error
cd t38modem-x.y.z/
make
sudo cp ./t38modem /usr/local/bin
  • t38modem can only find Opal if LD_LIBRARY_PATH and PTLIBPLUGINDIR are environment variables to the program

Configuring t38modem

Init script

First we'll create the configuration directory under /etc using sudo mkdir -p /etc/t38modem/bin/.

Then create a file named /etc/t38modem/bin/run using the following content. It will be the script to manage the current status of t38modem.

#!/bin/bash
# /etc/t38modem/bin/run

export LD_LIBRARY_PATH=/usr/local/lib
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # Adjust lib versions!

case "$1" in
	start)
		. /etc/t38modem/config
		# defines
		# - T38MODEM_SIP_USERNAME
		# - T38MODEM_SIP_PASSWORD
		# - T38MODEM_SIP_SERVER

		COMMAND="t38modem -u T38modem --ptty +/dev/ttyT38-1 --sip-proxy ${T38MODEM_SIP_USERNAME}:${T38MODEM_SIP_PASSWORD}@${T38MODEM_SIP_SERVER} --sip-register ${T38MODEM_SIP_USERNAME}@${T38MODEM_SIP_SERVER},${T38MODEM_SIP_PASSWORD} --sip-listen udp\$:5060 --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"
		echo "${COMMAND}"
		exec $COMMAND > /dev/null 2>&1 &
		PID=$!
		echo "Starting t38modem with pid $PID (pidfile /run/t38modem.pid)"
		echo $PID > /run/t38modem.pid
	;;
	stop)
		if [ ! -f "/run/t38modem.pid" ]; then
			echo "t38modem is not running! (/run/t38modem.pid does not exist)"
			exit 1
		fi

		echo -n "Stopping t38modem pid: "
		PID=`cat /run/t38modem.pid`
		kill -9 $PID
		rm /run/t38modem.pid
		echo "${PID} Done"
	;;
	*)
		echo "Usage: $0 {start|stop}"
		exit 1
	;;
esac

exit 0

And then we'll have to make it executable like this.

sudo chmod +x /etc/t38modem/bin/run

Quick script overview

  • Using that script, it is possible to start or stop the emulated modem.
  • -t enables debugging
    • More t's is deeper debugging (e.g. -tttt)
  • You can of course run the t38modem command without this init script
  • If t38modem says it was able to create the virtual modem but /dev/ttyT38-1 is not available, you do not have sufficient permissions
  • Configuration is specified in /etc/t38modem/config

Create the configuration file

Create a file using the following contents at /etc/t38modem/config.

# /etc/t38modem/config
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"

You should give only root access to the config.

sudo chown root:root /etc/t38modem/config
sudo chmod 700 /etc/t38modem/config

Testing your setup

  • You can now communicate with your modem /dev/ttyT38-1, just as if it was a real Hayes compatible modem (https://www.computerhope.com/atcom.htm)
  • Test using minicom, configure it to point to our modem. Each command is initiated by a Return
    • Dial a number:
      • Get the attention of the modem: at -> OK
      • Dial: atd[NUMBER], replace '[NUMBER]' using the number, you want to call
      • If all works correctly you should be able to answer the phone and hear a single beep
    • Answer a call:
      • Get the attention of the modem: at -> OK
      • Call the number of your modem
      • -> RING
      • Answer the call: ata -> CONNECT
      • You should now hear your modem "talking" to you
  • Pitfalls:
    • If you are already connected to your SIP server it may not give proper response codes. My provider returns 500 Internal Server Error
    • Test the command before running the init script!
    • Do not try to used ATO to switch to a data connection, t38modem will return ERROR. Thats hardcoded in pmodeme.cxx in void ModemEngineBody::HandleCmdRest(PString &resp). Dont let that hodld you back.

systemd service

If you want to run a fax server, you can create a systemd service to let your emulated fax modem start automatically on system boot. To do this you have to copy paste the following into /etc/systemd/system/t38modem.service.

# /etc/systemd/system/t38modem.service
[Unit]
Description=t38modem
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/etc/t38modem/bin/run start
ExecStop=/etc/t38modem/bin/run stop
PIDFile=/run/t38modem.pid
KillMode=none
Restart=always

[Install]
WantedBy=multi-user.target

Enable and start the service using the following commands:

sudo systemctl daemon-reload
sudo systemctl enable t38modem.service
sudo systemctl start t38modem.service

Install HylaFax

  • Version 6

  • sudo apt install hylafax-server

    • Set Postfix Configuration to Local only in dpkg-reconfigure menu
  • Run sudo faxsetup

    • Add new modem
    • Enter correct modem port (ttyT38-1)
    • Enter dialing configuration
    • Accept default configuration for everything else
    • It should automatically detect it to be a T38FAX modem
  • Look at man sendfax to send faxes

  • fgetty (the service to receive faxes) should be enabled automatically

  • Bugs:

    • If you get some protocol errors, just let HylaFax do its thing. Fax over SIP is not stable at all in my experience

Cron

  • Alias your fax admin account as FaxMaster (/etc/aliases)
# /etc/aliases
# [...]
# HylaFax
FaxMaster: $USER # replace with fax admin account
  • Add standard tasks to crontab file: crontab -e
0       *       *       *       *       /usr/sbin/faxqclean
25      23      *       *       *       sh /usr/sbin/faxcron | mail FaxMaster

FaxDispatch

TODO

  • TODO: Test on Debian / RockPi / RaspberryPi
  • TODO: Test on Eventphone Infra
  • TODO: Package t38modem with service files and config