Crate rusmpp

Source
Expand description

§Rusmpp

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(())
}

§Features

  • tokio-codec: Implements Encoder and Decoder traits for the CommandCodec.
  • tracing: Enables logging using tracing.
  • arbitrary: Implements Arbitrary trait for all 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.

Modules§

codec
Codec for encoding and decoding SMPP PDUs.
command
SMPP command.
decode
Traits for decoding SMPP values.
encode
Traits for encoding SMPP values.
fields
SMPP Fields.
pdus
SMPP PDUs.
session
Session state of the ESME <-> MC session.
tlvs
Tagged Length Value Field.
types
Core SMPP types.
values
SMPP values.

Structs§

Command
SMPP command.

Enums§

CommandId
Identifies the SMPP operation e.g. submit_sm, bind_transmitter etc.
CommandStatus
Represents the means by which an ESME or MC sends an error code to its peer.
Pdu
SMPP PDU.