Skip to content

J93d/smpp-codec

Repository files navigation

SMPP Codec (Rust)

A Rust library for encoding and decoding Short Message Peer-to-Peer (SMPP) v5.0 PDUs.

Crates.io Coverage Documentation License: Apache 2.0

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 specifications.
  • TLV Support: Includes a comprehensive list of Tag-Length-Value (TLV) optional parameters.
  • Tracing Support: Optional instrumentation using the tracing crate (use features = ["tracing"]).
  • Dependency: Built with standard library + rand.

Compatibility

The minimum supported Rust version (MSRV) is 1.65.0.

Usage

Add this to your Cargo.toml:

[dependencies]
smpp-codec = { version = "0.3.0", features = ["tracing"] }

Or

[dependencies]
smpp-codec = { git = "https://github.com/J93d/smpp-codec.git" }
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);
        }
    }
}
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...
    }
}
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...
    }
}
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)

The benchmark was done on a Windows 11 laptop and it may vary

Request Name Encoding Time Enc Rate (Mop/s) Decoding Time Dec Rate (Mop/s)
BindRequest 7.24ms 13.80 46.47ms 2.15
BindResponse 14.47ms 6.91 17.25ms 5.80
OutbindRequest 0.91ms 110.22 14.05ms 7.12
UnbindRequest 0.40ms 249.44 0.21ms 485.91
UnbindResponse 0.41ms 243.01 4.91ms 20.36
EnquireLinkRequest 0.49ms 205.09 0.21ms 485.91
EnquireLinkResponse 0.48ms 207.56 5.11ms 19.59
GenericNack 0.40ms 252.53 4.81ms 20.77
AlertNotification 1.25ms 79.76 13.80ms 7.24
SubmitSmRequest 6.31ms 15.84 23.16ms 4.32
SubmitSmRequest (Multi) 20.16ms 14.88 71.26ms 4.21
SubmitSmResponse 13.20ms 7.58 11.65ms 8.58
SubmitMultiRequest 4.00ms 24.97 38.88ms 2.57
SubmitMultiResponse 6.57ms 15.21 11.43ms 8.75
DeliverSmRequest 6.11ms 16.36 23.37ms 4.28
DeliverSmResponse 5.98ms 16.72 5.80ms 17.24
DataSmRequest 2.31ms 43.36 26.69ms 3.75
DataSmResponse 6.29ms 15.89 11.52ms 8.68
CancelSmRequest 1.93ms 51.74 20.39ms 4.90
CancelSmResponse 0.41ms 241.14 5.04ms 19.84
QuerySmRequest 1.12ms 89.36 14.68ms 6.81
QuerySmResponse 1.01ms 98.58 11.68ms 8.56
BroadcastSmRequest 3.63ms 27.55 28.60ms 3.50
BroadcastSmResponse 6.42ms 15.58 11.28ms 8.86
ReplaceSmRequest 2.19ms 45.71 20.97ms 4.77
ReplaceSmResponse 0.46ms 217.58 4.72ms 21.18
QueryBroadcastSmRequest 1.19ms 83.79 13.57ms 7.37
QueryBroadcastSmResponse 0.79ms 125.91 11.08ms 9.02
CancelBroadcastSmRequest 1.58ms 63.34 20.53ms 4.87
CancelBroadcastSmResponse 0.37ms 268.96 4.72ms 21.17

License

This project is licensed under the Apache-2.0 license.

About

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

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages