udptl 0.1.0

UDPTL (UDP Transport Layer) codec and socket for T.38 fax
Documentation
# udptl

UDPTL (UDP Transport Layer) codec and socket for T.38 fax over IP.

Implements the UDPTL packet format defined in ITU-T T.38 with both redundancy and FEC error recovery modes. Wire-compatible with SpanDSP.

## Usage

```toml
[dependencies]
udptl = "0.1"
```

### Async (tokio, default)

```rust
use udptl::AsyncUdptlSocket;

let socket = tokio::net::UdpSocket::bind("0.0.0.0:0").await?;
let udptl = AsyncUdptlSocket::new(socket);
udptl.connect("192.168.1.100:9000".parse()?);

// Send an IFP packet (redundancy added automatically)
udptl.send_ifp(&ifp_data).await?;

// Receive
let packet = udptl.recv_packet().await?;
println!("{}", packet); // UDPTL seq=0 primary=128B redundant=3
```

### Sync

```toml
[dependencies]
udptl = { version = "0.1", default-features = false }
```

```rust
use udptl::UdptlSocket;

let socket = std::net::UdpSocket::bind("0.0.0.0:0")?;
let udptl = UdptlSocket::new(socket);
udptl.connect("192.168.1.100:9000".parse()?);

udptl.send_ifp(&ifp_data)?;
let packet = udptl.recv_packet()?;
```

### Codec only

Encode and decode packets without a socket:

```rust
use udptl::{UdptlPacket, ErrorRecovery};

// Decode
let packet = UdptlPacket::decode(&wire_bytes)?;

// Encode
let packet = UdptlPacket::with_redundancy(0, ifp_data, redundant_packets);
let bytes = packet.encode();

// FEC mode
let packet = UdptlPacket::with_fec(0, ifp_data, 3, fec_entries);
let bytes = packet.encode();
```

## Configuration

```rust
use udptl::{UdptlSocket, UdptlConfig, ErrorCorrectionScheme};

let config = UdptlConfig {
    error_correction: ErrorCorrectionScheme::Redundancy,
    max_redundancy: 3,
    fec_span: 3,
    fec_entries: 3,
    max_packet_size: 512,
};
let udptl = UdptlSocket::with_config(socket, config);
```

## License

MIT

## AI DISCLAIMER

Bro this is slop city deluxe. I heavily supervised the model but it's 2026, get real. **No warranties express or implied** etc etc.