1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! # Rusmpp
//!
//! Rust implementation of the [SMPP v5](https://smpp.org/SMPP_v5.pdf) protocol.
//!
//! This is a low level library for implementing clients and servers. If you are looking for a client, check out [rusmppc](https://crates.io/crates/rusmppc).
//!
//! ```rust
//! # #[cfg(feature = "tokio-codec")]
//! # {
//! use core::error::Error;
//! use futures::{SinkExt, StreamExt};
//! use rusmpp::{
//! tokio_codec::{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`](https://docs.rs/tokio-util/latest/tokio_util/codec/trait.Encoder.html) and [`Decoder`](https://docs.rs/tokio-util/latest/tokio_util/codec/trait.Decoder.html) traits.
//! - `verbose`: Enables verbose error reports.
//! - `extra`: Enables encoding/decoding and concatenation support for [`SubmitSm`](crate::pdus::SubmitSm).
//! - `serde`: Implements [`Serialize`](https://docs.rs/serde/latest/serde/trait.Serialize.html) trait for all SMPP types.
//! - `serde-deserialize-unchecked`: Implements [`Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html) trait for all SMPP types, but does not check the validity of the data. Use with caution.
//! - `tracing`: Enables logging using [`tracing`](https://docs.rs/tracing/latest/tracing/).
//! - `pretty-hex-fmt`: Logs byte slices like `[0x00, 0x00, 0x00, 0x6F]` instead of `[00, 00, 00, 6F]`, if `tracing` feature is enabled.
//! - `char-fmt`: Logs byte slices as characters, if `tracing` feature is enabled.
//!
// #![deny(missing_docs)]
pub use ;