Files
telfax/README_ENTERPRISE.md
Warren 55bca92691 V1.0: Class 1 fax — real-world 4-page send to external number confirmed
Core features:
- Class 1 T.30 protocol: full send/receive implementation
- HDLC: DLE-stuffing, FCS strip, USR5637 bit-reversal handling
- T.4 MH encoder/decoder (1728px A4 standard)
- Document pipeline: PDF (Ghostscript), PNG, TIFF input
- Width clamping: US Letter 1734px → 1728px fax standard
- Cover page: CJK rasterization (TW/CN/JP/EN), TIFF + HTML output
- OCR verification: Tesseract 5 with eng+chi_tra, CJK space-tolerant
- API server (axum): health, send, jobs, cover, retry, cancel
- Background worker: auto-poll queue, speed fallback, retry policy
- Modem detection, pool management

Real-world test results (2026-07-23):
- V90 → 25153038: 4 pages, V.17 12000 bps, 2:33 ✅
- USR5637 → 25153038: 4 pages, V.17 12000 bps, 2:26 ✅
- Both faxes confirmed received on remote machine

Tested: loopback (100% pixel match), multi-page, all input formats,
cover pages, OCR verify, API endpoints, worker processing.
13 unit tests pass, 0 new clippy warnings.
2026-07-24 18:47:15 +08:00

8.8 KiB

Telfax Enterprise Fax Server

A production-ready fax server built in Rust, supporting Class 1 and Class 2 fax protocols.

Features

Core Features

  • ✅ Class 2 fax protocol (auto T.30 handling)
  • ✅ Class 1 fax protocol (manual T.30 handling)
  • ✅ T.4 MH encoding/decoding
  • ✅ PDF/TIFF/Image document conversion
  • ✅ Chinese cover page generation (PingFang font)

Enterprise Features

  • ✅ REST API for job management
  • ✅ Token-based authentication
  • ✅ Modem pool management (multi-modem support)
  • ✅ Job queue with persistence (SQLite)
  • ✅ Retry logic with exponential backoff
  • ✅ Speed fallback on training failure
  • ✅ Prometheus metrics endpoint
  • ✅ systemd integration
  • ✅ Structured logging (journal-compatible)

Architecture

┌─────────────────────────────────────────────────────────┐
│                     telfax Server                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌──────────────┐    ┌──────────────┐                  │
│  │  REST API    │────│  Job Queue   │                  │
│  │  (Axum)      │    │  (SQLite)    │                  │
│  └──────────────┘    └──────────────┘                  │
│         │                   │                          │
│         │            ┌──────▼──────┐                   │
│         │            │   Worker    │                   │
│         │            │   Executor  │                   │
│         │            └─────────────┘                   │
│         │                   │                          │
│         │            ┌──────▼──────┐                   │
│         │            │ Modem Pool  │                   │
│         │            │  Manager    │                   │
│         │            └─────────────┘                   │
│         │                   │                          │
│         │         ┌─────────▼─────────┐                │
│         │         │                   │                │
│         │    ┌────▼────┐        ┌─────▼─────┐          │
│         │    │  V90    │        │  USR5637  │          │
│         │    │ Class 2 │        │  Class 1  │          │
│         │    │ Primary │        │  Fallback │          │
│         │    └─────────┘        └───────────┘          │
│         │                                              │
│  ┌──────▼──────────────────────────────┐              │
│  │         Monitoring Layer            │              │
│  │  ├─ Metrics (Prometheus)            │              │
│  │  ├─ Logging (systemd journal)       │              │
│  │  └─ Health checks                   │              │
│  └─────────────────────────────────────┘              │
│                                                        │
└────────────────────────────────────────────────────────┘

Installation

Prerequisites

  • Rust 1.70+ (for building)
  • systemd (for service management)
  • Ghostscript (for PDF conversion)

Build

cargo build --release

Install

sudo ./deployment/install.sh

Configuration

Configuration file: /opt/telfax/config.toml

[server]
listen = "0.0.0.0:3000"
log_level = "info"

[auth]
rate_limit_per_ip = 100
rate_limit_per_token = 500

[[auth.tokens]]
token = "your-secret-admin-token-here"
permissions = "admin"

[[modems]]
device = "/dev/cu.usbmodem123456781"
name = "V90"
class = 2
priority = 1
enabled = true

[[modems]]
device = "/dev/cu.usbmodem00000021"
name = "USR5637"
class = 1
priority = 2
enabled = true

[queue]
database = "/var/lib/telfax/queue.db"
max_retries = 3
retry_intervals = [60, 300, 900]

[fax]
station_id = "+886-2-1234-5678"
header = "Your Company Name"
resolution = "fine"
speed_fallback = true
default_class = 2

API Reference

Authentication

All API endpoints require Bearer token authentication:

Authorization: Bearer <your-token>

Endpoints

Health Check

GET /api/health

Response:

{
  "status": "healthy",
  "uptime_seconds": 3600,
  "modems": [
    {
      "name": "V90",
      "device": "/dev/cu.usbmodem123456781",
      "status": "idle"
    }
  ],
  "queue": {
    "pending": 5,
    "active": 1,
    "failed": 2
  }
}

Send Fax

POST /api/fax/send

Request:

{
  "recipient": "0212345678",
  "document_path": "/path/to/document.pdf",
  "cover_to": "Recipient Name",
  "cover_from": "Your Company",
  "cover_subject": "Invoice #123",
  "cover_notes": "Additional notes"
}

Response:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "message": "Job queued successfully"
}

List Jobs

GET /api/fax/jobs

Response:

{
  "jobs": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "recipient": "0212345678",
      "status": "Queued",
      "pages": 3,
      "retries": 0,
      "created_at": "2024-07-05T12:00:00Z",
      "updated_at": "2024-07-05T12:00:00Z"
    }
  ],
  "total": 1
}

Get Job

GET /api/fax/jobs/{id}

Cancel Job

DELETE /api/fax/jobs/{id}

Retry Job

POST /api/fax/jobs/{id}/retry

Update Cover Page

PUT /api/fax/jobs/{id}/cover

Metrics

GET /api/metrics

Prometheus-compatible metrics:

fax_jobs_total 10
fax_jobs_completed 8
fax_jobs_failed 2
fax_jobs_queued 0
fax_pages_sent_total 24
fax_bytes_sent_total 1234567
modem_errors_total 3

Service Management

Start

sudo systemctl start telfax

Stop

sudo systemctl stop telfax

Enable (auto-start on boot)

sudo systemctl enable telfax

View Logs

# Follow logs
journalctl -u telfax -f

# Today's logs
journalctl -u telfax --since today

# Only errors
journalctl -u telfax -p err

CLI Commands

Send Fax

telfax send 0212345678 /path/to/document.pdf \
  --device /dev/cu.usbmodem123456781 \
  --class 2 \
  --resolution fine \
  --to "Recipient" \
  --from "Sender" \
  --subject "Subject"

Receive Fax

telfax receive \
  --device /dev/cu.usbmodem123456781 \
  --rings 2 \
  --output /var/lib/telfax/received \
  --class 2

Detect Modem

telfax detect /dev/cu.usbmodem123456781

Generate Cover Page

telfax cover-create \
  --to "Recipient" \
  --from "Sender" \
  --subject "Subject" \
  --note "Notes" \
  --pages 3 \
  --output cover.html

Worker Configuration

The background worker processes jobs from the queue:

  • Poll Interval: 5 seconds (checks for pending jobs)
  • Retry Policy: 3 retries with exponential backoff (1min, 5min, 15min)
  • Speed Fallback: On training failure, lowers speed: 14400 → 12000 → 9600 → 7200 → 4800
  • Concurrent Jobs: 1 per modem (configurable)

Monitoring

Health Check Endpoint

GET /api/health

Prometheus Metrics

GET /api/metrics

Logging

All logs go to systemd journal with structured fields:

  • job_id: Current job being processed
  • modem_name: Modem in use
  • status: Operation status

Development

Project Structure

src/
├── api/           # REST API routes and auth
├── config_new/    # Configuration management
├── document/      # PDF/TIFF handling, cover pages
├── error/         # Error types
├── fax/           # Fax protocols (Class 1/2)
├── modem/         # Modem driver and pool
├── monitoring/    # Metrics and health checks
├── ocr/           # OCR (optional)
├── preview/       # HTML preview generation
├── queue/         # Job queue and persistence
├── worker/        # Background job executor
└── main.rs        # CLI entry point

Running Tests

cargo test

Building Release

cargo build --release

License

MIT License

Support

For issues and feature requests, please open an issue on GitHub.