docker/t38modem | ||
README.md |
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 opalvoip wiki (http://wiki.opalvoip.org/index.php?n=Main.HomePage)
Software stack
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 connection
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:
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
ptlib
./configure
make
make install
opal
./configure
make -j5
make runtest
make install
t38modem
If you are getting an 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:
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
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
- Version 2.18.6
- Dependency of Opal, bundled with Opal source code (SourceForge)
- http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix
- TODO: Remove dependencies, most of them are optional
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 -> setPKG_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
- Version 3.18.6
- http://wiki.opalvoip.org/index.php?n=Main.BuildingOpalUnix
- Dont use
libavcodec-dev
-> Compile error - TODO: Remove dependencies, most of them are optional
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
- https://github.com/T38Modem/t38modem could also be used, but seems to be not as maintained
- If you are getting error about
-1
not being able to be casted to along unsigned int
due to-Wnarrowing
insidedle.cxx
, you can add-Wno-narrowing
after theCPPFLAGS
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
andPTLIBPLUGINDIR
are environment variables to the program
Configuring t38modem
Init script
- To automatically start t38modem, you need to create Systemd services, as well as start and stop scripts
- script is adapted from https://web.archive.org/web/20111231021042/https://www.foriamroot.org/hylafax-6-0-debian-or-ubuntu-t38modem-1-0-asterisk-1-6/
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-2.18.6:/usr/local/lib/opal-3.18.6 # Adjust lib versions!
if [ -z "${1}" ]; then
>&2 echo "Config file path not set! Aborting..."
exit 1
fi
. "${1}"
command="t38modem --ptty +/dev/ttyT38-${T38MODEM_PTTY_ID} --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 --stun ${T38MODEM_STUN_SERVER} --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"
if [ "$T38MODEM_DISABLE_T38" = true ]; then
command="${command} --disable-t38-mode --audio"
fi
exec $command
And then we'll have to make it executable like this.
sudo chmod +x /etc/t38modem/bin/run
Quick script overview
- Using this script, it is possible to start t38modem with a config file as an argument
-t
enables debugging- More
t
's is deeper debugging (e.g.-tttt
)
- More
- 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/XX
Create the configuration file
Create a file using the following contents at /etc/t38modem/config/XX
.
# /etc/t38modem/config
T38MODEM_PTTY_ID="XX" # /dev/ttyT38-XX
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"
T38MODEM_STUN_SERVER="stun.example.com:1234"
T38MODEM_DISABLE_T38=false # enable if your SIP server prefers G.711
You should give only root access to the config.
sudo chown root:root -R /etc/t38modem/config/
sudo chmod 700 -R /etc/t38modem/config/
Testing your setup
- You can now communicate with your modem
/dev/ttyT38-XX
, 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
- Get the attention of the modem:
- 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
- Get the attention of the modem:
- Dial a number:
- 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 returnERROR
. Thats hardcoded inpmodeme.cxx
invoid ModemEngineBody::HandleCmdRest(PString &resp)
. Dont let that hodld you back.
- If you are already connected to your SIP server it may not give proper response codes. My provider returns
systemd service
If you want to run a fax server, you can create a systemd service template 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
AssertPathExists=/etc/t38modem/config/%i
[Service]
Type=simple
Restart=always
ExecStart=/etc/t38modem/bin/run /etc/t38modem/config/%i
[Install]
WantedBy=multi-user.target
Enable and start the service for your config file (/etc/t38modem/config/XX
) using the following commands:
sudo systemctl daemon-reload
sudo systemctl enable t38modem@XX.service
sudo systemctl start t38modem@XX.service
Install HylaFax
These instructions were tested using Hylafax version 6
sudo apt install hylafax-server
- Set Postfix Configuration to Local only in dpkg-reconfigure menu
Configure HylaFax
-
Run
sudo faxsetup
- Add new modem
- Enter correct modem port (
ttyT38-XX
) - Enter dialing configuration (see Dial Rules for Eventphone EPVPN)
- 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
- If your call is cleared because it
Could not find common media capabilities
t38modem may not have been able to load PTLib or Opal. Check your library paths!
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
Dial Rules for Eventphone EPVPN
If you want to use Eventhone EPVPN, you can apply the following dial settings onto your modems.
You can find the config at /etc/hylafax/config.ttyT38-1
.
In this case ttyT38-1
is the modem block device.
# /etc/hylafax/config.ttyXX
CountryCode: 1
AreaCode: 999
FaxDispatch
TODO
- TODO: Test on Debian / RockPi / RaspberryPi
- TODO: Test on Eventphone Infra
- TODO: Package t38modem with service files and config