smpp-codec 0.2.1

A comprehensive SMPP v5 protocol codec for Rust.
Documentation
<h1 align="center">SMPP Codec (Rust)</h1>

<p align="center"><b>A Rust library for encoding and decoding Short Message Peer-to-Peer (SMPP) v5.0 PDUs.</b></p>

<p align="center">
  <a href="https://crates.io/crates/smpp-codec"><img alt="Crates.io" src="https://img.shields.io/crates/v/smpp-codec"></a>
  <a href="https://sonarcloud.io/summary/new_code?id=J93d_smpp-codec"><img alt="Coverage" src="https://img.shields.io/sonar/coverage/J93d_smpp-codec?server=https%3A%2F%2Fsonarcloud.io"></a>
  <a href="https://docs.rs/smpp-codec"><img alt="Documentation" src="https://img.shields.io/docsrs/smpp-codec"></a>
  <a href="https://opensource.org/license/apache-2-0"><img alt="License: Apache 2.0" src="https://img.shields.io/github/license/j93d/smpp-codec"></a>
</p>

> [!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**: Supports all PDU's as per [SMPP v5.0]https://smpp.org/SMPP_v5.pdf specifications.
- **TLV Support**: Includes a comprehensive list of Tag-Length-Value (TLV) optional parameters.
- **Dependency**: Built with standard library + [rand]https://crates.io/crates/rand/0.9.2.

## Compatibility


The minimum supported Rust version (MSRV) is **1.63.0**.

## Usage


Add this to your `Cargo.toml`:

```toml
[dependencies]
smpp-codec = 0.2.1
```
Or
```toml
[dependencies]
smpp-codec = { git = "https://github.com/J93d/smpp-codec.git" }
```

## [Examples:]https://github.com/J93d/smpp-codec/tree/master/examples


### [Binding as Transceiver]https://github.com/J93d/smpp-codec/blob/master/examples/bind_transceiver.rs


```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();
    match bind_req.encode(&mut buffer) {
        Ok(_) => {
            bind_req.encode(&mut buffer);    
            // Send `buffer` over TCP stream...
        }
        Err(e) => {
            eprintln!("Failed to encode: {:?}", e);
        }
    }
}
```

### [Submit Short Message]https://github.com/J93d/smpp-codec/blob/master/examples/submit_sm.rs


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

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

    // 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).expect("Failed to encode PDU");
        // Send buffer...
    }
}
```

### [Deliver Short Message]https://github.com/J93d/smpp-codec/blob/master/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 
    ).expect("Failed to split message");
    
    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).expect("Failed to encode PDU");
        // Send buffer...
    }
}
```

### [Unbind]https://github.com/J93d/smpp-codec/blob/master/examples/unbind.rs


```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).expect("Failed to encode PDU");
}
```

## Benchmark (cargo test --test benchmarks --release -- --nocapture)




| Request Name              | Encoding Time | Enc Rate (Mop/s) | Decoding Time | Dec Rate (Mop/s) |
|---------------------------|---------------|------------------|---------------|------------------|
| BindRequest               | 6.20ms        | 16.14            | 73.24ms       | 1.37             |
| BindResponse              | 7.90ms        | 12.66            | 11.48ms       | 8.71             |
| OutbindRequest            | 0.90ms        | 111.26           | 13.22ms       | 7.57             |
| UnbindRequest             | 0.37ms        | 272.55           | 0.23ms        | 433.09           |
| UnbindResponse            | 0.48ms        | 206.83           | 4.90ms        | 20.40            |
| EnquireLinkRequest        | 0.44ms        | 227.12           | 0.20ms        | 500.25           |
| EnquireLinkResponse       | 0.42ms        | 240.50           | 4.95ms        | 20.18            |
| GenericNack               | 0.43ms        | 231.37           | 30.21ms       | 3.31             |
| AlertNotification         | 1.36ms        | 73.76            | 14.04ms       | 7.12             |
| SubmitSmRequest           | 7.94ms        | 12.60            | 49.84ms       | 2.01             |
| SubmitSmRequest (Multi)   | 20.51ms       | 14.62            | 74.64ms       | 4.02             |
| SubmitSmResponse          | 39.47ms       | 2.53             | 38.77ms       | 2.58             |
| SubmitMulti               | 3.72ms        | 26.90            | 37.38ms       | 2.68             |
| SubmitMultiResp           | 6.03ms        | 16.59            | 13.08ms       | 7.64             |
| DeliverSmRequest          | 5.84ms        | 17.12            | 48.42ms       | 2.07             |
| DeliverSmResponse         | 6.38ms        | 15.67            | 6.07ms        | 16.49            |
| DataSm                    | 2.33ms        | 42.97            | 56.34ms       | 1.78             |
| DataSmResp                | 6.12ms        | 16.33            | 12.74ms       | 7.85             |
| CancelSmRequest           | 2.67ms        | 37.47            | 29.67ms       | 3.37             |
| CancelSmResponse          | 0.40ms        | 249.94           | 7.27ms        | 13.75            |
| QuerySmRequest            | 1.17ms        | 85.69            | 17.63ms       | 5.67             |
| QuerySmResponse           | 2.64ms        | 37.86            | 16.16ms       | 6.19             |
| BroadcastSm               | 3.79ms        | 26.37            | 63.79ms       | 1.57             |
| BroadcastSmResp           | 10.20ms       | 9.80             | 16.99ms       | 5.89             |
| ReplaceSm                 | 2.29ms        | 43.62            | 55.82ms       | 1.79             |
| ReplaceSmResp             | 0.55ms        | 180.28           | 6.36ms        | 15.73            |
| QueryBroadcastSm          | 1.35ms        | 74.13            | 17.71ms       | 5.65             |
| QueryBroadcastSmResp      | 0.85ms        | 117.84           | 12.60ms       | 7.94             |
| CancelBroadcastSm         | 1.69ms        | 59.29            | 24.60ms       | 4.06             |
| CancelBroadcastSmResp     | 0.44ms        | 229.67           | 6.11ms        | 16.37            |

## License


This project is licensed under the Apache-2.0 license.