smpp_codec/pdus/session_pdus/
alert_notification.rs1use crate::common::{
2 read_c_string, write_c_string, Npi, PduError, Ton, CMD_ALERT_NOTIFICATION, HEADER_LEN,
3};
4use crate::tlv::Tlv;
5use std::io::{Cursor, Read, Write};
6
7#[derive(Debug, Clone, PartialEq)]
11pub struct AlertNotification {
12 pub sequence_number: u32,
14 pub source_addr_ton: Ton,
16 pub source_addr_npi: Npi,
18 pub source_addr: String, pub esme_addr_ton: Ton,
22 pub esme_addr_npi: Npi,
24 pub esme_addr: String, pub optional_params: Vec<Tlv>,
28}
29
30impl AlertNotification {
31 pub fn new(sequence_number: u32, source_addr: String, esme_addr: String) -> Self {
46 Self {
47 sequence_number,
48 source_addr_ton: Ton::Unknown,
49 source_addr_npi: Npi::Unknown,
50 source_addr,
51 esme_addr_ton: Ton::Unknown,
52 esme_addr_npi: Npi::Unknown,
53 esme_addr,
54 optional_params: Vec::new(),
55 }
56 }
57
58 pub fn with_source_addr(mut self, ton: Ton, npi: Npi, addr: String) -> Self {
61 self.source_addr_ton = ton;
62 self.source_addr_npi = npi;
63 self.source_addr = addr;
64 self
65 }
66
67 pub fn with_esme_addr(mut self, ton: Ton, npi: Npi, addr: String) -> Self {
69 self.esme_addr_ton = ton;
70 self.esme_addr_npi = npi;
71 self.esme_addr = addr;
72 self
73 }
74
75 pub fn add_tlv(&mut self, tlv: Tlv) {
77 self.optional_params.push(tlv);
78 }
79
80 pub fn encode(&self, writer: &mut impl Write) -> Result<(), PduError> {
99 if self.source_addr.len() > 65 {
101 return Err(PduError::StringTooLong("source_addr".into(), 65));
102 }
103 if self.esme_addr.len() > 65 {
104 return Err(PduError::StringTooLong("esme_addr".into(), 65));
105 }
106
107 let mut body_len = 1 + 1 + self.source_addr.len() + 1 + 1 + 1 + self.esme_addr.len() + 1; for tlv in &self.optional_params {
113 body_len += 4 + tlv.value.len();
114 }
115
116 let command_len = (HEADER_LEN + body_len) as u32;
118 writer.write_all(&command_len.to_be_bytes())?;
119 writer.write_all(&CMD_ALERT_NOTIFICATION.to_be_bytes())?;
120 writer.write_all(&0u32.to_be_bytes())?;
121 writer.write_all(&self.sequence_number.to_be_bytes())?;
122
123 writer.write_all(&[self.source_addr_ton as u8, self.source_addr_npi as u8])?;
125 write_c_string(writer, &self.source_addr)?;
126
127 writer.write_all(&[self.esme_addr_ton as u8, self.esme_addr_npi as u8])?;
129 write_c_string(writer, &self.esme_addr)?;
130
131 for tlv in &self.optional_params {
133 tlv.encode(writer)?;
134 }
135
136 Ok(())
137 }
138
139 pub fn decode(buffer: &[u8]) -> Result<Self, PduError> {
159 if buffer.len() < HEADER_LEN {
160 return Err(PduError::BufferTooShort);
161 }
162
163 let mut cursor = Cursor::new(buffer);
164 cursor.set_position(12);
166 let mut bytes = [0u8; 4];
167 cursor.read_exact(&mut bytes)?;
168 let sequence_number = u32::from_be_bytes(bytes);
169
170 let mut u8_buf = [0u8; 1];
172
173 cursor.read_exact(&mut u8_buf)?;
174 let source_addr_ton = Ton::from(u8_buf[0]);
175 cursor.read_exact(&mut u8_buf)?;
176 let source_addr_npi = Npi::from(u8_buf[0]);
177 let source_addr = read_c_string(&mut cursor)?;
178
179 cursor.read_exact(&mut u8_buf)?;
180 let esme_addr_ton = Ton::from(u8_buf[0]);
181 cursor.read_exact(&mut u8_buf)?;
182 let esme_addr_npi = Npi::from(u8_buf[0]);
183 let esme_addr = read_c_string(&mut cursor)?;
184
185 let mut optional_params = Vec::new();
187 while let Some(tlv) = Tlv::decode(&mut cursor)? {
188 optional_params.push(tlv);
189 }
190
191 Ok(Self {
192 sequence_number,
193 source_addr_ton,
194 source_addr_npi,
195 source_addr,
196 esme_addr_ton,
197 esme_addr_npi,
198 esme_addr,
199 optional_params,
200 })
201 }
202}