| Crates.io | rusmpp |
| lib.rs | rusmpp |
| version | 0.2.3 |
| created_at | 2024-03-02 10:45:44.122791+00 |
| updated_at | 2025-09-09 19:11:12.478144+00 |
| description | A Rust SMPP library. |
| homepage | |
| repository | https://github.com/JadKHaddad/Rusmpp |
| max_upload_size | |
| id | 1159607 |
| size | 718,232 |
Rust implementation of the SMPP v5 protocol.
This is a low level library for implementing clients and servers. If you are looking for a client, check out rusmppc.
use core::error::Error;
use futures::{SinkExt, StreamExt};
use rusmpp::{
codec::{tokio::EncodeError, CommandCodec},
Command, CommandId, CommandStatus, Pdu,
};
use tokio::io::DuplexStream;
use tokio_util::codec::Framed;
use tracing::info;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Rusmpp produces a lot of logs while decoding and encoding PDUs.
// You can filter them out by setting the `rusmpp` target to `off`,
// or by disabling the `tracing` feature.
tracing_subscriber::fmt()
.with_env_filter("client=info,server=info,rusmpp=trace")
.init();
// In-memory duplex stream to simulate a server and client.
let (server_stream, client_stream) = tokio::io::duplex(4096);
launch_server(server_stream).await?;
// The CommandCodec encodes/decodes SMPP commands into/from bytes.
let mut framed = Framed::new(client_stream, CommandCodec::new());
// Rusmpp takes care of setting the correct command ID.
let command = Command::new(CommandStatus::EsmeRok, 1, Pdu::EnquireLink);
info!(target: "client", "EnquireLink sent");
framed.send(command).await?;
while let Some(Ok(command)) = framed.next().await {
if let CommandId::EnquireLinkResp = command.id() {
info!(target: "client", "EnquireLink response received");
break;
}
}
Ok(())
}
async fn launch_server(stream: DuplexStream) -> Result<(), Box<dyn Error>> {
tokio::spawn(async move {
let mut framed = Framed::new(stream, CommandCodec::new());
while let Some(Ok(command)) = framed.next().await {
if let CommandId::EnquireLink = command.id() {
info!(target: "server", "EnquireLink received");
// We can also use the Command::builder() to create commands.
let response = Command::builder()
.status(CommandStatus::EsmeRok)
.sequence_number(command.sequence_number())
.pdu(Pdu::EnquireLinkResp);
framed.send(response).await?;
info!(target: "server", "EnquireLink response sent");
break;
}
}
Ok::<(), EncodeError>(())
});
Ok(())
}
See the examples directory for more examples.
tokio-codec: Implements Encoder and Decoder traits for the CommandCodec.tracing: Enables logging using tracing.arbitrary: Implements Arbitrary trait for all SMPP types.verbose: Enables verbose error reports.pretty-hex-fmt: Logs byte slices like [0x00, 0x00, 0x00, 0x6F] instead of [00, 00, 00, 6F], if tracing feature is enabled.serde: Implements Serialize trait for all SMPP types.serde-deserialize-unchecked: Implements Deserialize trait for all SMPP types, but does not check the validity of the data. Use with caution.Licensed under either of
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.