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

378 lines
8.8 KiB
Markdown

# 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
```bash
cargo build --release
```
### Install
```bash
sudo ./deployment/install.sh
```
## Configuration
Configuration file: `/opt/telfax/config.toml`
```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:
```json
{
"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:
```json
{
"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:
```json
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Job queued successfully"
}
```
#### List Jobs
```
GET /api/fax/jobs
```
Response:
```json
{
"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
```bash
sudo systemctl start telfax
```
### Stop
```bash
sudo systemctl stop telfax
```
### Enable (auto-start on boot)
```bash
sudo systemctl enable telfax
```
### View Logs
```bash
# 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
```bash
telfax send 0212345678 /path/to/document.pdf \
--device /dev/cu.usbmodem123456781 \
--class 2 \
--resolution fine \
--to "Recipient" \
--from "Sender" \
--subject "Subject"
```
### Receive Fax
```bash
telfax receive \
--device /dev/cu.usbmodem123456781 \
--rings 2 \
--output /var/lib/telfax/received \
--class 2
```
### Detect Modem
```bash
telfax detect /dev/cu.usbmodem123456781
```
### Generate Cover Page
```bash
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
```bash
cargo test
```
### Building Release
```bash
cargo build --release
```
## License
MIT License
## Support
For issues and feature requests, please open an issue on GitHub.