smpp-codec 0.1.0

A comprehensive SMPP 3.4 protocol codec for Rust.
Documentation
# SMPP Codec (Rust)


A Rust library for encoding and decoding Short Message Peer-to-Peer (SMPP) v3.4 Protocol Data Units (PDUs).

> [!WARNING]
> **Disclaimer**:Portions of this codebase were generated by Google's Gemini AI. 
> While efforts have been made to ensure correctness, users should review and test the code thoroughly before using it in production environments.

## Features


- **PDU Support**: Currently supports Session Management PDUs (Bind, Unbind, EnquireLink, AlertNotification, Outlbind, GenericNack).
- **TLV Support**: Includes a comprehensive list of Tag-Length-Value (TLV) optional parameters.
- **Zero-Dependency Core**: Built with standard library usages (mostly) to keep it lightweight.

## Usage


Add this to your `Cargo.toml`:

```toml
[dependencies]
smpp-codec = { path = "." } # Or git url
```

### Example: Binding as Transceiver


```rust
use smpp_codec::common::{BindMode, Ton, Npi};
use smpp_codec::pdus::BindRequest;

fn main() {
    let bind_req = BindRequest::new(
        1, // Sequence Number
        BindMode::Transceiver,
        "my_system_id".to_string(),
        "password".to_string(),
    ).with_address_range(Ton::International, Npi::Isdn, "12345".to_string());

    let mut buffer = Vec::new();
    bind_req.encode(&mut buffer).unwrap();
    
    // Send `buffer` over TCP stream...
}
```

### 2. Submit Short Message


```rust
use smpp_codec::pdus::{SubmitSmRequest, MessageSplitter, SplitMode, EncodingType};

fn main() {
    let text = "Hello, world!".to_string();
    
    // Split message (handles encoding and valid chunking)
    let (parts, data_coding) = MessageSplitter::split(
        text,
        EncodingType::Gsm7Bit, 
        SplitMode::Udh // Use UDH for concatenation
    ).unwrap();

    // Iterate over parts and send each PDU
    for (i, part) in parts.into_iter().enumerate() {
        let mut submit_req = SubmitSmRequest::new(
            (i + 2) as u32, // Sequence Number
            "source_addr".to_string(),
            "dest_addr".to_string(),
            part,
        );
        submit_req.data_coding = data_coding; // Important: Set correct encoding!

        let mut buffer = Vec::new();
        submit_req.encode(&mut buffer).unwrap();
        // Send buffer...
    }
}
```

### 3. Deliver Short Message

(Included in `examples/deliver_sm.rs`)

```rust
use smpp_codec::pdus::{DeliverSmRequest, MessageSplitter, SplitMode, EncodingType};

fn main() {
    let text = "Incoming message...".to_string();
    
    // Split message
    let (parts, data_coding) = MessageSplitter::split(
        text,
        EncodingType::Gsm7Bit, 
        SplitMode::Udh 
    ).unwrap();
    
    let parts_len = parts.len();

    for (i, part) in parts.into_iter().enumerate() {
        let mut deliver_req = DeliverSmRequest::new(
            (i + 100) as u32,
            "sender".to_string(),
            "shortcode".to_string(),
            part,
        );
        deliver_req.data_coding = data_coding;

        // CRITICAL: Set UDHI bit (0x40) if using UDH
        if parts_len > 1 {
            deliver_req.esm_class |= 0x40;
        }

        let mut buffer = Vec::new();
        deliver_req.encode(&mut buffer).unwrap();
        // Send buffer...
    }
}
```

### 4. Unbind


```rust
use smpp_codec::pdus::UnbindRequest;

fn main() {
    let unbind_req = UnbindRequest::new(3); // Sequence Number

    let mut buffer = Vec::new();
    unbind_req.encode(&mut buffer).unwrap();
}
```

## Running cargo test --test benchmarks --release -- --nocapture


| Request Name              | Encoding Time | Enc Rate (Mop/s) | Decoding Time | Dec Rate (Mop/s)|
|---------------------------|---------------|------------------|---------------|-----------------|
| BindRequest               | 2.11ms        | 47.48            | 46.71ms       | 2.14            |
| BindResponse              | 6.26ms        | 15.97            | 11.09ms       | 9.02            |
| OutbindRequest            | 12.68ms       | 7.89             | 12.51ms       | 7.99            |
| UnbindRequest             | 0.61ms        | 162.63           | 0.23ms        | 434.40          |
| UnbindResponse            | 0.43ms        | 234.69           | 5.27ms        | 18.96           |
| EnquireLinkRequest        | 0.36ms        | 274.65           | 0.18ms        | 543.77          |
| EnquireLinkResponse       | 0.41ms        | 245.64           | 4.79ms        | 20.89           |
| GenericNack               | 0.40ms        | 252.78           | 30.67ms       | 3.26            |
| AlertNotification         | 13.50ms       | 7.41             | 13.38ms       | 7.48            |
| SubmitSmRequest (Multi)| 2.81s         | 10.66            | 10.37s        | 2.89            |
| SubmitSmResponse          | 39.00ms       | 2.56             | 36.65ms       | 2.73            |
| DeliverSmRequest          | 5.34ms        | 18.73            | 47.83ms       | 2.09            |
| DeliverSmResponse         | 0.42ms        | 237.53           | 5.30ms        | 18.86           |
| CancelSmRequest           | 20.31ms       | 4.92             | 19.05ms       | 5.25            |
| CancelSmResponse          | 0.42ms        | 240.56           | 5.24ms        | 19.09           |
| QuerySmRequest            | 13.44ms       | 7.44             | 12.70ms       | 7.88            |
| QuerySmResponse           | 13.31ms       | 7.51             | 11.57ms       | 8.65            |

## License


This project is licensed under the Apache-2.0 license.

## Running Tests


```sh
cargo test
```