55bca92691
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.
378 lines
8.8 KiB
Markdown
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. |