Skip to main content

smpp_codec/pdus/session_pdus/
outbind.rs

1use crate::common::{write_c_string, PduError, CMD_OUTBIND, HEADER_LEN};
2use std::io::{Cursor, Read, Write};
3
4/// Represents an Outbind PDU.
5///
6/// Sent by the SMSC to the ESME to request the ESME to initiate a Bind.
7#[derive(Debug, Clone)]
8pub struct OutbindRequest {
9    pub sequence_number: u32,
10    pub system_id: String,
11    pub password: String,
12}
13
14impl OutbindRequest {
15    /// Create a new Outbind Request.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use smpp_codec::pdus::OutbindRequest;
21    ///
22    /// let sequence_number: u32 = 1;
23    /// let outbind = OutbindRequest::new(
24    ///     sequence_number, // Sequence number
25    ///     "my_system_id".to_string(),
26    ///     "password".to_string(),
27    /// );
28    /// ```
29    pub fn new(sequence_number: u32, system_id: String, password: String) -> Self {
30        Self {
31            sequence_number,
32            system_id,
33            password,
34        }
35    }
36
37    /// Encode the struct into raw bytes for the network.
38    ///
39    /// # Errors
40    ///
41    /// Returns a [`PduError`] if:
42    /// * `system_id` exceeds 16 characters.
43    /// * `password` exceeds 9 characters.
44    /// * An I/O error occurs while writing.
45    ///
46    /// # Examples
47    ///
48    /// ```
49    /// # use smpp_codec::pdus::OutbindRequest;
50    /// # let sequence_number: u32 = 1;
51    /// # let outbind = OutbindRequest::new(sequence_number, "id".into(), "pwd".into());
52    /// let mut buffer = Vec::new();
53    /// outbind.encode(&mut buffer).expect("Encoding failed");
54    /// ```
55    pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
56        // Validate
57        if self.system_id.len() > 16 {
58            return Err(PduError::StringTooLong("system_id".into(), 16));
59        }
60        if self.password.len() > 9 {
61            return Err(PduError::StringTooLong("password".into(), 9));
62        }
63
64        let mut body = Vec::new();
65        write_c_string(&mut body, &self.system_id)?;
66        write_c_string(&mut body, &self.password)?;
67
68        let command_len = (HEADER_LEN + body.len()) as u32;
69
70        // Header
71        writer.write_all(&command_len.to_be_bytes())?;
72        writer.write_all(&CMD_OUTBIND.to_be_bytes())?;
73        writer.write_all(&0u32.to_be_bytes())?; // Status is always 0
74        writer.write_all(&self.sequence_number.to_be_bytes())?;
75
76        // Body
77        writer.write_all(&body)?;
78
79        Ok(())
80    }
81
82    /// Decode raw bytes from the network into the struct.
83    ///
84    /// # Errors
85    ///
86    /// Returns a [`PduError`] if:
87    /// * The buffer is too short.
88    /// * The buffer data is malformed.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// # use smpp_codec::pdus::OutbindRequest;
94    /// # let sequence_number: u32 = 1;
95    /// # let outbind = OutbindRequest::new(sequence_number, "id".into(), "pwd".into());
96    /// # let mut buffer = Vec::new();
97    /// # outbind.encode(&mut buffer).unwrap();
98    /// let decoded = OutbindRequest::decode(&buffer).expect("Decoding failed");
99    /// assert_eq!(decoded.system_id, "id");
100    /// ```
101    pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
102        if buffer.len() < HEADER_LEN {
103            return Err(PduError::BufferTooShort);
104        }
105
106        let mut cursor = Cursor::new(buffer);
107
108        // Skip Header (assuming caller checked ID, or we just consume it)
109        cursor.set_position(12); // Skip len, id, status
110        let mut bytes = [0u8; 4];
111        cursor.read_exact(&mut bytes)?;
112        let sequence_number = u32::from_be_bytes(bytes);
113
114        // Body
115        let system_id = crate::common::read_c_string(&mut cursor)?;
116        let password = crate::common::read_c_string(&mut cursor)?;
117
118        Ok(Self {
119            sequence_number,
120            system_id,
121            password,
122        })
123    }
124}